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