a3baeb64717db0b5744cfb3480d12b0bb03aa068
[platform/framework/web/wrt-plugins-common.git] / src / wrt-popup / ace / popup-bin / Popup.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        Popup.c
18  * @author      Janusz Kozerski (j.kozerski@samsung.com)
19  * @version     1.0
20  */
21
22 /*
23  * This is just a example pop-up that shows how to use a new C-API in
24  * wrt-security.
25  * This pop-up should be re-implemented by members of NGWAP.
26  */
27
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <vector>
33 #include <ctime>
34
35 #include <Elementary.h>
36
37 #include <dpl/log/log.h>
38 #include <dpl/serialization.h>
39 #include <ace_api_common.h>
40 #include <ace_api_popup_validation.h>
41
42 #include "popup-runner.h"
43 #include "Popup.h"
44
45 namespace { // anonymous
46 static void set_validity_from_checkbox(struct ace_popup_data *pdp)
47 {
48     if (NULL == pdp) {
49         LogError("pdp is NULL; return");
50         return;
51     }
52
53     if (pdp->always) {
54         LogDebug("Remember ALWAYS");
55         pdp->remember_choice = ACE_ALWAYS;
56         return;
57     }
58     if (pdp->per_session) {
59         LogDebug("Remember PER_SESSION");
60         pdp->remember_choice = ACE_PER_SESSION;
61         return;
62     }
63     LogDebug("Remember ONCE");
64     pdp->remember_choice = ACE_ONCE;
65     return;
66 }
67
68 static void on_done(void)
69 {
70     // Quit the efl-mainloop
71     LogDebug("elm_exit()");
72     elm_exit();
73 }
74
75 static void grant_answer(void *data,
76                          Evas_Object * /* obj */,
77                          void * /* event_info */)
78 {
79     LogDebug("grant_answer");
80     if (NULL == data) {
81         LogError("data is NULL; return");
82         return;
83     }
84     struct ace_popup_data *pdp = static_cast <struct ace_popup_data *>(data);
85
86     set_validity_from_checkbox(pdp);
87
88     ace_popup_validation_initialize();
89     pdp->validation_return = ace_validate_answer(
90             ACE_TRUE,
91             pdp->remember_choice,
92             pdp->resource_name,
93             pdp->session_id,
94             &(pdp->param_list),
95             pdp->handle,
96             &(pdp->validation_result));
97     ace_popup_validation_shutdown();
98
99     on_done();
100 }
101
102 static void deny_answer(void *data,
103                         Evas_Object * /* obj */,
104                         void * /* event_info */)
105 {
106     LogDebug("deny_answer");
107     if (NULL == data) {
108         LogError("data is NULL; return");
109         return;
110     }
111     struct ace_popup_data *pdp = static_cast <struct ace_popup_data *>(data);
112
113     set_validity_from_checkbox(pdp);
114
115     ace_popup_validation_initialize();
116     pdp->validation_return = ace_validate_answer(
117             ACE_FALSE,
118             pdp->remember_choice,
119             pdp->resource_name,
120             pdp->session_id,
121             &(pdp->param_list),
122             pdp->handle,
123             &(pdp->validation_result));
124     ace_popup_validation_shutdown();
125
126     on_done();
127 }
128
129 static int _ace_params_deserializer(ace_param_list_t* ace_param_list,
130                                     Wrt::Popup::BinaryStream *stream)
131 {
132     LogDebug("_ace_params_deserializer");
133
134     if (NULL == ace_param_list || NULL == stream) {
135         LogError("ace_param_list or stream is NULL; return -1");
136         return -1;
137     }
138
139     // deserialize ace_param_list->count;
140     size_t count = 0;
141     DPL::Deserialization::Deserialize(*stream, count);
142     ace_param_list->count = count;
143     LogDebug("count : " << count);
144
145     std::string name;
146     std::string value;
147     if (count == 0) {
148         ace_param_list->items = NULL;
149         return 0;
150     }
151     ace_param_list->items =
152         static_cast <ace_param_t *>(malloc(count * sizeof(ace_param_t)));
153     memset(ace_param_list->items, 0, count * sizeof(ace_param_t));
154
155     for (size_t i = 0; i < count; ++i) {
156         DPL::Deserialization::Deserialize(*stream, name);
157         ace_param_list->items[i].name =
158             strdup(const_cast <char *>(name.c_str()));
159
160         DPL::Deserialization::Deserialize(*stream, value);
161         ace_param_list->items[i].value =
162             strdup(const_cast <char *>(value.c_str()));
163     }
164     return 0;
165 }
166
167 static void _ace_params_finalize(ace_param_list_t* ace_param_list)
168 {
169     if (!ace_param_list || !ace_param_list->items) {
170         LogDebug("List is null, nothing to do");
171         return;
172     }
173     for (size_t i = 0; i < ace_param_list->count; ++i) {
174         free(ace_param_list->items[i].name);
175         free(ace_param_list->items[i].value);
176     }
177     free(ace_param_list->items);
178     ace_param_list->items = NULL;
179     ace_param_list->count = 0;
180 }
181
182 static void show_popup(struct ace_popup_data *pdp)
183 {
184     LogDebug("show_popup()");
185
186     if (NULL == pdp) {
187         LogError("pdp is NULL; return");
188         return;
189     }
190
191     const char *resource_type = static_cast <char *>(pdp->resource_name);
192
193     Evas_Object *win = NULL;
194     Evas_Object *cb_session = NULL;
195     Evas_Object *cb_always = NULL;
196     Evas_Object *box = NULL;
197     Evas_Object *label = NULL;
198     Evas_Object *grant_button = NULL;
199     Evas_Object *deny_button = NULL;
200     pdp->per_session = EINA_FALSE;
201     pdp->always = EINA_FALSE;
202
203     win = elm_win_add(NULL, "The wrt-client popup", ELM_WIN_NOTIFICATION);
204     elm_win_autodel_set(win, EINA_TRUE);
205     elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
206     evas_object_show(win);
207     elm_win_indicator_opacity_set(win, ELM_WIN_INDICATOR_TRANSLUCENT);
208
209     pdp->popup = elm_popup_add(win);
210
211     box = elm_box_add(pdp->popup);
212     evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, 0);
213     evas_object_size_hint_align_set(box, EVAS_HINT_FILL, 0.0);
214
215     label = elm_label_add(pdp->popup);
216     elm_object_style_set(label, "popup_description/default");
217     elm_label_line_wrap_set(label, ELM_WRAP_MIXED);
218     char *buff = NULL;
219     if (-1 ==
220         asprintf(&buff, "Application need an access to %s.<br>Grant or deny?",
221                  resource_type))
222     {
223         LogError("asprintf failed - returned -1");
224         evas_object_del(label);
225         evas_object_del(pdp->popup);
226         evas_object_del(win);
227         return;
228     }
229     elm_object_text_set(label, buff);
230     free(buff);
231     evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, 0.0);
232     evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL);
233     evas_object_show(label);
234     elm_box_pack_end(box, label);
235
236     LogDebug("popup_type == " << pdp->popup_type);
237     if (pdp->popup_type == ACE_SESSION || pdp->popup_type == ACE_BLANKET) {
238         LogDebug("popup_type == ACE_SESSION || ACE_BLANKET");
239         cb_session = elm_check_add(pdp->popup);
240         elm_object_text_set(cb_session, "Remember choice for this session");
241         elm_check_state_pointer_set(cb_session, &(pdp->per_session));
242         evas_object_smart_callback_add(cb_session, "changed", NULL, NULL);
243         evas_object_size_hint_align_set(cb_session,
244                                         EVAS_HINT_FILL,
245                                         EVAS_HINT_FILL);
246         evas_object_size_hint_weight_set(cb_session,
247                                          EVAS_HINT_EXPAND,
248                                          EVAS_HINT_EXPAND);
249         evas_object_show(cb_session);
250         elm_box_pack_end(box, cb_session);
251
252         if (pdp->popup_type == ACE_BLANKET) {
253             LogDebug("popup_type == ACE_BLANKET");
254             cb_always = elm_check_add(pdp->popup);
255             elm_object_text_set(cb_always, "Remember choice forever");
256             elm_check_state_pointer_set(cb_always, &(pdp->always));
257             evas_object_smart_callback_add(cb_always, "changed", NULL, NULL);
258             evas_object_size_hint_align_set(cb_always,
259                                             EVAS_HINT_FILL,
260                                             EVAS_HINT_FILL);
261             evas_object_size_hint_weight_set(cb_always,
262                                              EVAS_HINT_EXPAND,
263                                              EVAS_HINT_EXPAND);
264             evas_object_show(cb_always);
265             elm_box_pack_end(box, cb_always);
266         }
267     }
268
269     elm_object_part_content_set(pdp->popup, "default", box);
270
271     grant_button = elm_button_add(pdp->popup);
272     elm_object_text_set(grant_button, "Grant");
273     elm_object_part_content_set(pdp->popup, "button1", grant_button);
274     evas_object_smart_callback_add(grant_button, "clicked", grant_answer, pdp);
275
276     deny_button = elm_button_add(pdp->popup);
277     elm_object_text_set(deny_button, "Deny");
278     elm_object_part_content_set(pdp->popup, "button2", deny_button);
279     evas_object_smart_callback_add(deny_button, "clicked", deny_answer, pdp);
280
281     evas_object_show(pdp->popup);
282
283     // Showing the popup window
284     evas_object_show(win);
285
286     // Run the efl mainloop
287     elm_run();
288 }
289 } // anonymous
290
291 EAPI_MAIN int
292 elm_main(int argc, char ** argv)
293 {
294     UNHANDLED_EXCEPTION_HANDLER_BEGIN
295     {
296         // int pipe_in and int pipe_out should be passed to Popup via args.
297
298         //  These parameters should be passed to Popup via pipe:
299         //  ace_popup_t             popup_type
300         //  const ace_resource_t    resource_name
301         //  const ace_session_id_t  session_id
302         //  ace_widget_handle_t     handle
303         //  const ace_param_list_t  param_list
304
305         try {
306             DPL::Log::LogSystemSingleton::Instance().SetTag("WRT-POPUP-BIN");
307         } Catch(DPL::Exception) {
308             //cannot run logger
309             return ACE_INTERNAL_ERROR;
310         }
311         LogDebug(
312             "############################ popup binary ################################");
313
314         if (argc < 3) {
315             LogError(
316                 "To few args passed in exec to popup-bin - should be at least 3:");
317             LogError("(binary-name, pipe_in, pipe_out)");
318             LogError("return ACE_INTERNAL_ERROR");
319             return ACE_INTERNAL_ERROR;
320         }
321         LogDebug("Passed args: " << argv[0] << ", " << argv[1] << ", " <<
322                  argv[2]);
323
324         int pipe_in;
325         int pipe_out;
326
327         // Parsing args (pipe_in, pipe_out)
328         if (0 == sscanf(argv[1], "%d", &pipe_in) ) {
329             LogError("Error while parsing pipe_in; return ACE_INTERNAL_ERROR");
330             return ACE_INTERNAL_ERROR;
331         }
332         if (0 == sscanf(argv[2], "%d", &pipe_out) ) {
333             LogError("Error while parsing pipe_out; return ACE_INTERNAL_ERROR");
334             return ACE_INTERNAL_ERROR;
335         }
336         LogDebug("Parsed pipes: IN: " << pipe_in << ", OUT: " << pipe_out);
337
338         int buff_size = 1024;
339         char line[buff_size];
340
341         struct ace_popup_data pd;
342         struct ace_popup_data *pdp = &pd;
343
344         pdp->popup = NULL;
345
346         ssize_t count = 0;
347         time_t time_start;
348         time(&time_start); // now
349         double timeout = 10.0;
350         // try to read parameters from pipe_in
351         // timeout is set for 10 seconds
352         do {
353             count = TEMP_FAILURE_RETRY(read(pipe_in, line, buff_size));
354             if (timeout < difftime(time(NULL), time_start) ) {
355                 LogError("Timeout reached! Exit popup - ACE_INTERNAL_ERROR");
356                 close(pipe_in);
357                 close(pipe_out);
358                 return ACE_INTERNAL_ERROR;
359             }
360         } while (0 == count);
361         if (count < 0) {
362             close(pipe_in);
363             close(pipe_out);
364             LogError("read returned a negative value (" << count << ")");
365             LogError("errno: " << strerror(errno) );
366             LogError("Exit popup - ACE_INTERNAL_ERROR");
367             return ACE_INTERNAL_ERROR;
368         }
369         LogDebug("Read bytes : " << count << " (in " <<
370                  difftime(time_start, time(NULL)) << " seconds)");
371         close(pipe_in); // cleanup
372
373         Wrt::Popup::BinaryStream stream;
374         stream.Write(count, static_cast <void *>(line));
375         int popup_type = ACE_ONESHOT;
376         std::string resource_name_str;
377         std::string session_id_str;
378         int handle = 0;
379
380         LogDebug("------- Deserialization -------");
381         // Deserialization order:
382         // popup_type, resource_name, session_id, handle, param_list
383
384         DPL::Deserialization::Deserialize(stream, popup_type);
385         LogDebug("popup_type_int : " << popup_type);
386         pdp->popup_type = static_cast <ace_popup_t>(popup_type);
387
388         DPL::Deserialization::Deserialize(stream, resource_name_str);
389         LogDebug("resource_name_char : " << resource_name_str.c_str());
390         pdp->resource_name =
391             strdup(const_cast <ace_resource_t>(resource_name_str.c_str()));
392
393         DPL::Deserialization::Deserialize(stream, session_id_str);
394         LogDebug("session_id_char : " << session_id_str.c_str());
395         pdp->session_id =
396             strdup(const_cast <ace_session_id_t>(session_id_str.c_str()));
397
398         DPL::Deserialization::Deserialize(stream, handle);
399         LogDebug("handle_int : " << handle);
400         pdp->handle = static_cast <ace_widget_handle_t>(handle);
401
402         if (_ace_params_deserializer(&(pdp->param_list), &stream)) {
403             return ACE_INTERNAL_ERROR;
404         }
405
406         pdp->per_session = EINA_FALSE;
407         pdp->always = EINA_FALSE;
408         pdp->validation_return = ACE_ACE_UNKNOWN_ERROR;
409
410         show_popup(pdp); // Showing popup
411
412         // sending validation_result to popup-runner
413         Wrt::Popup::BinaryStream stream_out;
414
415         LogDebug("pdp->validation_result : " << pdp->validation_result);
416         int validation_result_int = (int) pdp->validation_result;
417         LogDebug("validation_result_int : " << validation_result_int);
418         DPL::Serialization::Serialize(stream_out, validation_result_int);
419         if (-1 ==
420             TEMP_FAILURE_RETRY(write(pipe_out, stream_out.char_pointer(),
421                                      stream_out.size())))
422         {
423             LogError("Write to pipe failed!");
424             close(pipe_out);
425             return ACE_INTERNAL_ERROR;
426         }
427         close(pipe_out);
428
429         if (pdp->validation_return == ACE_OK) {
430             LogDebug("ACE_OK");
431         } else if (pdp->validation_return == ACE_INVALID_ARGUMENTS) {
432             LogError("ACE_INVALID_ARGUMENTS");
433         } else if (pdp->validation_return == ACE_INTERNAL_ERROR) {
434             LogError("ACE_INTERNAL_ERROR");
435         } else if (pdp->validation_return == ACE_ACE_UNKNOWN_ERROR) {
436             LogError("ACE_ACE_UNKNOWN_ERROR");
437         } else {
438             LogError("Really unknown error!!!");
439         }
440
441         LogDebug(
442             "############################ /popup binary ################################");
443
444         // Shutdown elementary
445         //LogDebug("elm_shutdown()");
446         //elm_shutdown();
447         // This is commented because, it causes that popup exits with 139 code
448         // (Segmentatation violation).
449         // Not calling elm_shutdown() should not have any negative consequences
450         // because this binary ends
451         // in next line, and system should clear the memory.
452
453         _ace_params_finalize(&(pdp->param_list));
454         return pdp->validation_return;
455     }
456     UNHANDLED_EXCEPTION_HANDLER_END
457 }
458 ELM_MAIN()