Merge "fix: use EINA_* booleans instread of TRUE/FALSE" into tizen
[platform/framework/web/wrt.git] / src / view / webkit / view_logic_authentication_challenge_support.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    view_logic_authentication_challenge_support.cpp
18  * @author  Jihoon Chung (jihoon.chung@samsung.com)
19  */
20
21 #include "view_logic_authentication_challenge_support.h"
22
23 #include <string>
24 #include <dpl/log/log.h>
25 #include <dpl/assert.h>
26 #include <Elementary.h>
27 #include <EWebKit2.h>
28
29 namespace ViewModule {
30 namespace {
31
32 const char* const EVAS_SMART_CALLBACK_CLICKED = "clicked";
33 const char* const EVAS_SMART_CALLBACK_CHANGED = "changed";
34 const char* const EVAS_SMART_CALLBACK_PREEDIT_CHANGED = "preedit,changed";
35 const char* const EVAS_SMART_CALLBACK_FOCUSED = "focused";
36 const char* const EVAS_SMART_CALLBACK_UNFOCUSED = "unfocused";
37 const char* const ELM_SIGNAL_ERASER_CLICKED = "elm,eraser,clicked";
38 const char* const ELM_SIGNAL_STATE_GUIDETEXT_HIDE = "elm,state,guidetext,hide";
39 const char* const ELM_SIGNAL_STATE_ERASER_SHOW = "elm,state,eraser,show";
40 const char* const ELM_SIGNAL_STATE_HIDE_SHOW = "elm,state,eraser,hide";
41 const char* const ELM_SWALLOW_CONTENT = "elm.swallow.content";
42 const char* const ELM_SWALLOW_LABEL = "elm.swallow.label";
43 const char* const ELM_SWALLOW_IDFIELD = "elm.swallow.idfield";
44 const char* const ELM_SWALLOW_PASSWDFIELD = "elm.swallow.passwdfield";
45
46 const char* const GROUP_NAME_AUTHENTICATION_CHALLENGE_POPUP =
47     "authChallengePopup";
48 const char* const THEME_EDITFIELD = "editfield";
49 const char* const THEME_DEFAULT = "default";
50
51 const char* const STYLE_POPUP_BUTTON_DEFAULT = "popup_button/default";
52 const char* const STYLE_DEFAULT_EDITFIELD =
53     "DEFAULT='font_size=34 color=#808080 ellipsis=1'";
54
55 const char* const PART_IDFIELD_TEXT = "idfield_text";
56 const char* const PART_PASSWORDFIELD_TEXT = "passwdfield_text";
57 const char* const PART_BUTTON1 = "button1";
58 const char* const PART_BUTTON2 = "button2";
59
60 const char* const ELM = "elm";
61 const char* const TITLE_TEXT = "title,text";
62 const char* const LAYOUT = "layout";
63 const char* const ERASER = "eraser";
64 const char* const WIDGET_NAME_POPUP = "elm_popup";
65 const char* const WIDGET_NAME_NAVIFRAME = "elm_naviframe";
66
67 const char* const AUTHENTICATION_CHALLENGE_TITLE_TEXT =
68     "Authentication Requested";
69 const char* const AUTHENTICATION_CHALLENGE_BODY_PRETEXT =
70     "A username and password are being requested by ";
71 const char* const AUTHENTICATION_CHALLENGE_BODY_MIDDLETEXT =
72     ". The site says: ";
73
74 const char* const TEXT_DOUBLE_QUOTATION_MARKS = " \"";
75 const char* const TEXT_ID_FIELD = " User Name: ";
76 const char* const TEXT_PASSWORD_FIELD = " Password: ";
77 const char* const TEXT_OK = "Ok";
78 const char* const TEXT_CANCEL = "Cancel";
79
80 struct authenticationData {
81     Ewk_Auth_Challenge* m_authChallenge;
82     std::string m_bodyText;
83     Evas_Object* m_navi;
84     Evas_Object* m_idLayout;
85     Evas_Object* m_passLayout;
86 };
87
88 // function declare
89 void askUserInformation(authenticationData* authData);
90 Evas_Object* createEditLayout(Evas_Object* parent, bool isPasswordEdit = false);
91
92 // edit callback
93 static void editChangedCallback(void* data, Evas_Object* obj, void* eventInfo);
94 static void editFocusedCallback(void* data, Evas_Object* obj, void* eventInfo);
95 static void editUnfocusedCallback(void* data,
96                                   Evas_Object* obj,
97                                   void* eventInfo);
98 static void eraserClickedCallback(void* data,
99                                   Evas_Object* obj,
100                                   const char* emission,
101                                   const char* source);
102
103 // button callback
104 Evas_Object* getEvasObjectByWidgetName(Evas_Object* obj, const char* name);
105 void buttonCallback(void* data, Evas_Object* obj, void* eventInfo);
106
107 void askUserInformation(authenticationData* authData)
108 {
109     Assert(authData);
110     Evas_Object* popup = elm_popup_add(authData->m_navi);
111     evas_object_size_hint_weight_set(popup,
112                                      EVAS_HINT_EXPAND,
113                                      EVAS_HINT_EXPAND);
114     evas_object_size_hint_align_set(popup, EVAS_HINT_FILL, EVAS_HINT_FILL);
115     elm_object_part_text_set(popup,
116                              TITLE_TEXT,
117                              AUTHENTICATION_CHALLENGE_TITLE_TEXT);
118
119     Evas_Object* label = elm_label_add(popup);
120     evas_object_size_hint_weight_set(label,
121                                      EVAS_HINT_EXPAND,
122                                      EVAS_HINT_EXPAND);
123     elm_label_line_wrap_set(label , ELM_WRAP_WORD);
124     elm_object_text_set(label, authData->m_bodyText.c_str());
125
126     authData->m_idLayout = createEditLayout(popup);
127     authData->m_passLayout = createEditLayout(popup, true);
128
129     Evas_Object* popupLayout = elm_layout_add(popup);
130     elm_layout_file_set(popupLayout,
131                         WRT_EDJ_PATH,
132                         GROUP_NAME_AUTHENTICATION_CHALLENGE_POPUP);
133     evas_object_size_hint_weight_set(popupLayout,
134                                      EVAS_HINT_EXPAND,
135                                      EVAS_HINT_EXPAND);
136     /* FIXME : The text should be translated. */
137     edje_object_part_text_set(elm_layout_edje_get(popupLayout),
138                               PART_IDFIELD_TEXT,
139                               TEXT_ID_FIELD);
140     edje_object_part_text_set(elm_layout_edje_get(popupLayout),
141                               PART_PASSWORDFIELD_TEXT,
142                               TEXT_PASSWORD_FIELD);
143
144     elm_object_part_content_set(popupLayout, ELM_SWALLOW_LABEL, label);
145     elm_object_part_content_set(popupLayout,
146                                 ELM_SWALLOW_IDFIELD,
147                                 authData->m_idLayout);
148     elm_object_part_content_set(popupLayout,
149                                 ELM_SWALLOW_PASSWDFIELD,
150                                 authData->m_passLayout);
151     elm_object_content_set(popup, popupLayout);
152
153     Evas_Object* lButton = elm_button_add(popup);
154     elm_object_text_set(lButton, TEXT_OK);
155     elm_object_style_set(lButton, STYLE_POPUP_BUTTON_DEFAULT);
156     elm_object_part_content_set(popup, PART_BUTTON1, lButton);
157     evas_object_smart_callback_add(lButton,
158                                    EVAS_SMART_CALLBACK_CLICKED,
159                                    buttonCallback,
160                                    static_cast<void *>(authData));
161
162     Evas_Object* rButton= elm_button_add(popup);
163     elm_object_text_set(rButton, TEXT_CANCEL);
164     elm_object_style_set(rButton, STYLE_POPUP_BUTTON_DEFAULT);
165     elm_object_part_content_set(popup, PART_BUTTON2, rButton);
166     evas_object_smart_callback_add(rButton,
167                                    EVAS_SMART_CALLBACK_CLICKED,
168                                    buttonCallback,
169                                    static_cast<void *>(authData));
170
171     evas_object_show(popup);
172 }
173
174 Evas_Object* createEditLayout(Evas_Object* parent, bool isPasswordEdit)
175 {
176     Evas_Object* layout = elm_layout_add(parent);
177     elm_layout_theme_set(layout, LAYOUT, THEME_EDITFIELD, THEME_DEFAULT);
178     Evas_Object* entry = elm_entry_add(layout);
179     elm_object_part_content_set(layout, ELM_SWALLOW_CONTENT, entry);
180     elm_object_signal_emit(layout, ELM_SIGNAL_STATE_GUIDETEXT_HIDE, ELM);
181     evas_object_data_set(layout, ERASER, reinterpret_cast<void *>(EINA_TRUE));
182
183     evas_object_smart_callback_add(entry,
184                                    EVAS_SMART_CALLBACK_CHANGED,
185                                    editChangedCallback,
186                                    layout);
187     evas_object_smart_callback_add(entry,
188                                    EVAS_SMART_CALLBACK_PREEDIT_CHANGED,
189                                    editChangedCallback,
190                                    layout);
191     evas_object_smart_callback_add(entry,
192                                    EVAS_SMART_CALLBACK_FOCUSED,
193                                    editFocusedCallback,
194                                    layout);
195     evas_object_smart_callback_add(entry,
196                                    EVAS_SMART_CALLBACK_UNFOCUSED,
197                                    editUnfocusedCallback,
198                                    layout);
199     elm_object_signal_callback_add(layout,
200                                    ELM_SIGNAL_ERASER_CLICKED,
201                                    ELM,
202                                    eraserClickedCallback,
203                                    entry);
204
205     if (isPasswordEdit) {
206         elm_entry_password_set(entry, EINA_TRUE);
207     } else {
208         elm_entry_autocapital_type_set(entry, ELM_AUTOCAPITAL_TYPE_NONE);
209         evas_object_data_set(layout, ERASER, reinterpret_cast<void *>(EINA_TRUE));
210         elm_object_signal_emit(layout, ELM_SIGNAL_STATE_ERASER_SHOW, ELM);
211     }
212     elm_entry_text_style_user_push(
213         entry,
214         STYLE_DEFAULT_EDITFIELD);
215     return layout;
216 }
217
218 void editChangedCallback(void* data, Evas_Object* obj, void* /*eventInfo*/)
219 {
220     Assert(data);
221     Evas_Object* layout = static_cast<Evas_Object *>(data);
222
223     Assert(obj);
224     if (elm_object_focus_get(obj)) {
225         if (elm_entry_is_empty(obj)) {
226             elm_object_signal_emit(layout, ELM_SIGNAL_STATE_HIDE_SHOW, ELM);
227         } else {
228             elm_object_signal_emit(layout, ELM_SIGNAL_STATE_ERASER_SHOW, ELM);
229         }
230     }
231 }
232
233 void editFocusedCallback(void* data, Evas_Object* obj, void* /*eventInfo*/)
234 {
235     Assert(data);
236     Evas_Object* layout = static_cast<Evas_Object *>(data);
237
238     Assert(obj);
239     if (!elm_entry_is_empty(obj)) {
240         elm_object_signal_emit(layout, ELM_SIGNAL_STATE_ERASER_SHOW, ELM);
241     }
242 }
243 void editUnfocusedCallback(void* data,
244                                   Evas_Object* /*obj*/,
245                                   void* /*eventInfo*/)
246 {
247     Assert(data);
248     Evas_Object* layout = static_cast<Evas_Object *>(data);
249     elm_object_signal_emit(layout, ELM_SIGNAL_STATE_HIDE_SHOW, ELM);
250 }
251
252 void eraserClickedCallback(void* data,
253                            Evas_Object* /*obj*/,
254                            const char* /*emission*/,
255                            const char* /*source*/)
256 {
257     Assert(data);
258     Evas_Object* entry = static_cast<Evas_Object *>(data);
259     elm_entry_entry_set(entry, "");
260 }
261
262 Evas_Object* getEvasObjectByWidgetName(Evas_Object* obj, const char* name)
263 {
264     Assert(obj);
265     Evas_Object* current = elm_object_parent_widget_get(obj);
266     while (strcmp(elm_object_widget_type_get(current), name)) {
267         current = elm_object_parent_widget_get(current);
268         if (!current) {
269             return NULL;
270         }
271     }
272     return current;
273 }
274
275 void buttonCallback(void* data, Evas_Object* obj, void* /*eventInfo*/)
276 {
277     LogDebug("popupCallback");
278     Assert(data);
279     authenticationData* authData = static_cast<authenticationData *>(data);
280
281     Assert(obj);
282     Evas_Object* popup = getEvasObjectByWidgetName(obj, WIDGET_NAME_POPUP);
283
284     bool allow = !strcmp(TEXT_OK, elm_object_text_get(obj));
285     if (allow) {
286         const char* id =
287             elm_entry_entry_get(
288                 elm_object_part_content_get(authData->m_idLayout,
289                                             ELM_SWALLOW_CONTENT));
290         const char* pw =
291             elm_entry_entry_get(
292                 elm_object_part_content_get(authData->m_passLayout,
293                                             ELM_SWALLOW_CONTENT));
294         LogDebug("id = [" << id << "], password = [" << pw << "]");
295         ewk_auth_challenge_credential_use(authData->m_authChallenge,
296                                           const_cast<char *>(id),
297                                           const_cast<char *>(pw));
298     } else {
299         ewk_auth_challenge_credential_cancel(authData->m_authChallenge);
300     }
301
302     evas_object_hide(popup);
303     evas_object_del(popup);
304     delete authData;
305 }
306 } // namespace
307
308 void AuthenticationChallengeSupport::authenticationChallengeRequest(
309     Evas_Object* webview,
310     std::string url,
311     void* data)
312 {
313     LogDebug("authenticationChallengeRequest called");
314     authenticationData* authData = new authenticationData();
315     Assert(webview);
316     authData->m_navi = getEvasObjectByWidgetName(webview,
317                                                  WIDGET_NAME_NAVIFRAME);
318
319     Assert(data);
320     authData->m_authChallenge = static_cast<Ewk_Auth_Challenge*>(data);
321
322     // create body text
323     // TODO : The text should be translated
324     const char* authRealm =
325         ewk_auth_challenge_realm_get(authData->m_authChallenge);
326     if (authRealm != NULL) {
327         authData->m_bodyText =
328             std::string(AUTHENTICATION_CHALLENGE_BODY_PRETEXT) +
329             std::string(url) +
330             std::string(AUTHENTICATION_CHALLENGE_BODY_MIDDLETEXT) +
331             std::string(TEXT_DOUBLE_QUOTATION_MARKS) +
332             std::string(authRealm) +
333             std::string(TEXT_DOUBLE_QUOTATION_MARKS);
334     }
335     ewk_auth_challenge_suspend(authData->m_authChallenge);
336
337     // ask to user
338     askUserInformation(authData);
339 }
340 } // namespace ViewModule