Initialize Tizen 2.3
[framework/web/wrt-plugins-common.git] / src_wearable / 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 *box = NULL;
195     Evas_Object *label = NULL;
196     Evas_Object *grant_button = NULL;
197     Evas_Object *deny_button = NULL;
198     pdp->per_session = EINA_FALSE;
199     pdp->always = EINA_FALSE;
200
201     win = elm_win_add(NULL, "The wrt-client popup", ELM_WIN_NOTIFICATION);
202     elm_win_autodel_set(win, EINA_TRUE);
203     elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
204     evas_object_show(win);
205     elm_win_indicator_opacity_set(win, ELM_WIN_INDICATOR_TRANSLUCENT);
206
207     pdp->popup = elm_popup_add(win);
208
209     box = elm_box_add(pdp->popup);
210     evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, 0);
211     evas_object_size_hint_align_set(box, EVAS_HINT_FILL, 0.0);
212
213     label = elm_label_add(pdp->popup);
214     elm_object_style_set(label, "popup_description/default");
215     elm_label_line_wrap_set(label, ELM_WRAP_MIXED);
216     char *buff = NULL;
217     if (-1 ==
218         asprintf(&buff, "Application need an access to %s.<br>Grant or deny?",
219                  resource_type))
220     {
221         LogError("asprintf failed - returned -1");
222         evas_object_del(label);
223         evas_object_del(pdp->popup);
224         evas_object_del(win);
225         return;
226     }
227     elm_object_text_set(label, buff);
228     free(buff);
229     evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, 0.0);
230     evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL);
231     evas_object_show(label);
232     elm_box_pack_end(box, label);
233
234     LogDebug("popup_type == " << pdp->popup_type);
235     if (pdp->popup_type == ACE_SESSION || pdp->popup_type == ACE_BLANKET) {
236         LogDebug("popup_type == ACE_SESSION || ACE_BLANKET");
237         Evas_Object *cb_session = elm_check_add(pdp->popup);
238         elm_object_text_set(cb_session, "Remember choice for this session");
239         elm_check_state_pointer_set(cb_session, &(pdp->per_session));
240         evas_object_smart_callback_add(cb_session, "changed", NULL, NULL);
241         evas_object_size_hint_align_set(cb_session,
242                                         EVAS_HINT_FILL,
243                                         EVAS_HINT_FILL);
244         evas_object_size_hint_weight_set(cb_session,
245                                          EVAS_HINT_EXPAND,
246                                          EVAS_HINT_EXPAND);
247         evas_object_show(cb_session);
248         elm_box_pack_end(box, cb_session);
249
250         if (pdp->popup_type == ACE_BLANKET) {
251             LogDebug("popup_type == ACE_BLANKET");
252             Evas_Object *cb_always = elm_check_add(pdp->popup);
253             elm_object_text_set(cb_always, "Remember choice forever");
254             elm_check_state_pointer_set(cb_always, &(pdp->always));
255             evas_object_smart_callback_add(cb_always, "changed", NULL, NULL);
256             evas_object_size_hint_align_set(cb_always,
257                                             EVAS_HINT_FILL,
258                                             EVAS_HINT_FILL);
259             evas_object_size_hint_weight_set(cb_always,
260                                              EVAS_HINT_EXPAND,
261                                              EVAS_HINT_EXPAND);
262             evas_object_show(cb_always);
263             elm_box_pack_end(box, cb_always);
264         }
265     }
266
267     elm_object_part_content_set(pdp->popup, "default", box);
268
269     grant_button = elm_button_add(pdp->popup);
270     elm_object_style_set(grant_button, "popup");
271     elm_object_text_set(grant_button, "Grant");
272     elm_object_part_content_set(pdp->popup, "button1", grant_button);
273     evas_object_smart_callback_add(grant_button, "clicked", grant_answer, pdp);
274
275     deny_button = elm_button_add(pdp->popup);
276     elm_object_style_set(deny_button, "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         std::stringstream parsing_stream;
327
328         // Parsing args (pipe_in, pipe_out)
329         parsing_stream.str(argv[1]);
330         parsing_stream >> pipe_in;
331         if ( parsing_stream.fail() ) {
332             LogError("Error while parsing pipe_in; return ACE_INTERNAL_ERROR");
333             return ACE_INTERNAL_ERROR;
334         }
335         parsing_stream.clear();
336         parsing_stream.str(argv[2]);
337         parsing_stream >> pipe_out;
338         if ( parsing_stream.fail() ) {
339             LogError("Error while parsing pipe_out; return ACE_INTERNAL_ERROR");
340             return ACE_INTERNAL_ERROR;
341         }
342         parsing_stream.clear();
343         LogDebug("Parsed pipes: IN: " << pipe_in << ", OUT: " << pipe_out);
344
345         int buff_size = 1024;
346         char line[buff_size];
347
348         struct ace_popup_data pd;
349         struct ace_popup_data *pdp = &pd;
350
351         pdp->popup = NULL;
352
353         ssize_t count = 0;
354         time_t time_start;
355         time(&time_start); // now
356         double timeout = 10.0;
357         // try to read parameters from pipe_in
358         // timeout is set for 10 seconds
359         do {
360             count = TEMP_FAILURE_RETRY(read(pipe_in, line, buff_size));
361             if (timeout < difftime(time(NULL), time_start) ) {
362                 LogError("Timeout reached! Exit popup - ACE_INTERNAL_ERROR");
363                 close(pipe_in);
364                 close(pipe_out);
365                 return ACE_INTERNAL_ERROR;
366             }
367         } while (0 == count);
368         if (count < 0) {
369             close(pipe_in);
370             close(pipe_out);
371             LogError("read returned a negative value (" << count << ")");
372             LogError("errno: " << strerror(errno) );
373             LogError("Exit popup - ACE_INTERNAL_ERROR");
374             return ACE_INTERNAL_ERROR;
375         }
376         LogDebug("Read bytes : " << count << " (in " <<
377                  difftime(time_start, time(NULL)) << " seconds)");
378         close(pipe_in); // cleanup
379
380         Wrt::Popup::BinaryStream stream;
381         stream.Write(count, static_cast <void *>(line));
382         int popup_type = ACE_ONESHOT;
383         std::string resource_name_str;
384         std::string session_id_str;
385         int handle = 0;
386
387         LogDebug("------- Deserialization -------");
388         // Deserialization order:
389         // popup_type, resource_name, session_id, handle, param_list
390
391         DPL::Deserialization::Deserialize(stream, popup_type);
392         LogDebug("popup_type_int : " << popup_type);
393         pdp->popup_type = static_cast <ace_popup_t>(popup_type);
394
395         DPL::Deserialization::Deserialize(stream, resource_name_str);
396         LogDebug("resource_name_char : " << resource_name_str.c_str());
397         pdp->resource_name =
398             strdup(const_cast <ace_resource_t>(resource_name_str.c_str()));
399
400         DPL::Deserialization::Deserialize(stream, session_id_str);
401         LogDebug("session_id_char : " << session_id_str.c_str());
402         pdp->session_id =
403             strdup(const_cast <ace_session_id_t>(session_id_str.c_str()));
404
405         DPL::Deserialization::Deserialize(stream, handle);
406         LogDebug("handle_int : " << handle);
407         pdp->handle = static_cast <ace_widget_handle_t>(handle);
408
409         if (_ace_params_deserializer(&(pdp->param_list), &stream)) {
410             return ACE_INTERNAL_ERROR;
411         }
412
413         pdp->per_session = EINA_FALSE;
414         pdp->always = EINA_FALSE;
415         pdp->validation_return = ACE_ACE_UNKNOWN_ERROR;
416
417         show_popup(pdp); // Showing popup
418
419         // sending validation_result to popup-runner
420         Wrt::Popup::BinaryStream stream_out;
421
422         LogDebug("pdp->validation_result : " << pdp->validation_result);
423         int validation_result_int = (int) pdp->validation_result;
424         LogDebug("validation_result_int : " << validation_result_int);
425         DPL::Serialization::Serialize(stream_out, validation_result_int);
426         if (-1 ==
427             TEMP_FAILURE_RETRY(write(pipe_out, stream_out.char_pointer(),
428                                      stream_out.size())))
429         {
430             LogError("Write to pipe failed!");
431             close(pipe_out);
432             return ACE_INTERNAL_ERROR;
433         }
434         close(pipe_out);
435
436         if (pdp->validation_return == ACE_OK) {
437             LogDebug("ACE_OK");
438         } else if (pdp->validation_return == ACE_INVALID_ARGUMENTS) {
439             LogError("ACE_INVALID_ARGUMENTS");
440         } else if (pdp->validation_return == ACE_INTERNAL_ERROR) {
441             LogError("ACE_INTERNAL_ERROR");
442         } else if (pdp->validation_return == ACE_ACE_UNKNOWN_ERROR) {
443             LogError("ACE_ACE_UNKNOWN_ERROR");
444         } else {
445             LogError("Really unknown error!!!");
446         }
447
448         LogDebug(
449             "############################ /popup binary ################################");
450
451         // Shutdown elementary
452         //LogDebug("elm_shutdown()");
453         //elm_shutdown();
454         // This is commented because, it causes that popup exits with 139 code
455         // (Segmentatation violation).
456         // Not calling elm_shutdown() should not have any negative consequences
457         // because this binary ends
458         // in next line, and system should clear the memory.
459
460         _ace_params_finalize(&(pdp->param_list));
461         return pdp->validation_return;
462     }
463     UNHANDLED_EXCEPTION_HANDLER_END
464 }
465 ELM_MAIN()