[Engine] Support custom js event regarding state change of softkeyboard(ime)
[platform/framework/web/wrt.git] / src / view / webkit / bundles / wrt-wk2-bundle.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    wrt-wk2-bundle.cpp
18  * @author  Lukasz Wrzosek (l.wrzosek@samsung.com)
19  * @brief   Implementation file for view logic for Webkit2
20  */
21 #include "wrt-wk2-bundle.h"
22
23 #include <WKBundle.h>
24 #include <WKBundleInitialize.h>
25 #include <WKBundlePage.h>
26 #include <WKBundleFrame.h>
27 #include <WKURLRequest.h>
28 #include <WKString.h>
29 #include <WKType.h>
30 #include <WKURL.h>
31 #include <WKError.h>
32 #include <WKURLResponseEfl.h>
33
34 #include <string>
35 #include <cstdio>
36 #include <sstream>
37 #include <sys/stat.h>
38 #include <set>
39 #include <openssl/sha.h>
40 #include <openssl/hmac.h>
41 #include <openssl/evp.h>
42 #include <openssl/bio.h>
43 #include <openssl/buffer.h>
44
45 #include <dpl/log/log.h>
46 #include <dpl/foreach.h>
47 #include <dpl/assert.h>
48 #include <dpl/wrt-dao-ro/WrtDatabase.h>
49 #include <dpl/localization/localization_utils.h>
50 #include <dpl/string.h>
51 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
52 #include <dpl/utils/mime_type_utils.h>
53 #include <dpl/localization/LanguageTagsProvider.h>
54
55 #include <wrt_plugin_module.h>
56 #include <profiling_util.h>
57
58 #include <vconf.h>
59 #include <appcore-efl.h>
60
61 #include "messages_names.h"
62
63 #include <scheme.h>
64 #include <scheme_action_map_type.h>
65 #include <scheme_action_map_data.h>
66
67 #include <js_overlay_types.h>
68
69 // URI localization on WebProcess side
70 #include "bundle_uri_handling.h"
71
72 namespace {
73 const char * const uriChangedMessageName = "uri_changed_msg";
74 const char * const URICHANGE_PLUGIN_STOP_ONLY = "plugin_stop_only";
75 const char * const URICHANGE_PLUGIN_RESTART = "plugin_restart";
76 const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
77 const char * const URICHANGE_BLOCKED_URL = "null";
78 const char * const SCHEME_HTTP = "http";
79 const char * const SCHEME_HTTPS = "https";
80 const char * const SCHEME_FILE = "file://";
81 const char * const DATA_STRING = "data:";
82 const char * const BASE64_STRING = ";base64,";
83 }
84
85 Bundle::Bundle(WKBundleRef bundle) :
86     m_bundle(bundle),
87     m_widgetHandle(-1),
88     m_scale(0),
89     m_encodedBundle(""),
90     m_theme(""),
91     m_encrypted(false),
92     m_resDec(NULL),
93     m_widgetType(WrtDB::APP_TYPE_UNKNOWN)
94 {
95     LOG_PROFILE_START("Bundle attachToThread");
96     WrtDB::WrtDatabase::attachToThreadRO();
97     m_uriChangedMessage = WKStringCreateWithUTF8CString(uriChangedMessageName);
98     LOG_PROFILE_STOP("Bundle attachToThread");
99 }
100
101 Bundle::~Bundle()
102 {
103     WrtDB::WrtDatabase::detachFromThread();
104
105     if (!m_pagesList.empty())
106     {
107         LogError("There are not closed pages!");
108     }
109
110     WKRelease(m_uriChangedMessage);
111     WKRelease(m_bundle);
112 }
113
114 void Bundle::didCreatePageCallback(
115         WKBundleRef /*bundle*/,
116         WKBundlePageRef page,
117         const void* clientInfo)
118 {
119     LOG_PROFILE_START("didCreatePageCallback");
120     LogDebug("didCreatePageCallback called");
121     Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
122     This->didCreatePage(page);
123     LOG_PROFILE_STOP("didCreatePageCallback");
124 }
125
126 void Bundle::didReceiveMessageCallback(
127         WKBundleRef /*bundle*/,
128         WKStringRef messageName,
129         WKTypeRef messageBody,
130         const void *clientInfo)
131 {
132     LogDebug("didReceiveMessageCallback called");
133     Bundle* bundle = static_cast<Bundle*>(const_cast<void*>(clientInfo));
134     bundle->didReceiveMessage(messageName, messageBody);
135 }
136
137 void Bundle::willDestroyPageCallback(
138         WKBundleRef /*bundle*/,
139         WKBundlePageRef page,
140         const void* clientInfo)
141 {
142     LogDebug("willDestroyPageCallback called");
143     Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
144     This->willDestroyPage(page);
145 }
146
147 void Bundle::didCreatePage(WKBundlePageRef page)
148 {
149     auto mainFrame = WKBundlePageGetMainFrame(page);
150     auto context = WKBundleFrameGetJavaScriptContext(mainFrame);
151     m_pagesList.push_back(page);
152     m_pageGlobalContext[page] = context;
153     LogDebug("created Page : " << page << " created JSContext : " << context);
154
155     WKBundlePageResourceLoadClient resourceLoadClient =  {
156         kWKBundlePageResourceLoadClientCurrentVersion,  /* version */
157         this, /* clientinfo */
158         0, /* didInitiateLoadForResource */
159         willSendRequestForFrameCallback, /* willSendRequestForFrame */
160         0, /* didReceiveResponseForResource */
161         0, /* didReceiveContentLengthForResource */
162         didFinishLoadForResourceCallback, /* didFinishLoadForResource */
163         0, /* didFailLoadForResource */
164         0, /* shouldCacheResponse */
165         0, /* shouldUseCredentialStorage */
166     };
167     WKBundlePageSetResourceLoadClient(page, &resourceLoadClient);
168
169     WKBundlePageLoaderClient loaderClient = {
170         kWKBundlePageLoaderClientCurrentVersion,
171         this, /* clientinfo */
172         didStartProvisionalLoadForFrameCallback, /* didStartProvisionalLoadForFrame */
173         0, /* didReceiveServerRedirectForProvisionalLoadForFrame */
174         0, /* didFailProvisionalLoadWithErrorForFrame */
175         didCommitLoadForFrameCallback, /* didCommitLoadForFrame */
176         0, /* didFinishDocumentLoadForFrame */
177         0, /* didFinishLoadForFrame */
178         0, /* didFailLoadWithErrorForFrame */
179         0, /* didSameDocumentNavigationForFrame */
180         0, /* didReceiveTitleForFrame */
181         0, /* didFirstLayoutForFrame */
182         0, /* didFirstVisuallyNonEmptyLayoutForFrame */
183         didRemoveFrameFromHierarchyCallback, /* didRemoveFrameFromHierarchy */
184         0, /* didDisplayInsecureContentForFrame */
185         0, /* didRunInsecureContentForFrame */
186         0, /* didClearWindowObjectForFrame */
187         0, /* didCancelClientRedirectForFrame */
188         0, /* willPerformClientRedirectForFrame */
189         0, /* didHandleOnloadEventsForFrame */
190         0, /* didLayoutForFrame */
191         0, /* didNewFirstVisuallyNonEmptyLayout */
192         0, /* didDetectXSSForFrame */
193         0, /* shouldGoToBackForwardListItem */
194         0, /* globalObjectIsAvailableForFrame */
195         0, /* willDisconnectDOMWindowExtensionFromGlobalObject */
196         0, /* didReconnectDOMWindowExtensionToGlobalObject */
197         0, /* willDestroyGlobalObjectForDOMWindowExtension */
198         0, /* didFinishProgress */
199         0, /* shouldForceUniversalAccessFromLocalURL */
200         0, /* didReceiveIntentForFrame */
201         0, /* registerIntentServiceForFrame */
202     };
203     WKBundlePageSetPageLoaderClient(page, &loaderClient);
204
205
206     WKBundlePagePolicyClient policyClient = {
207         kWKBundlePagePolicyClientCurrentVersion,        /* version */
208         this,                                           /* clientInfo */
209         pageDecidePolicyForNavigationActionCallback,    /* decidePolicyForNavigationAction */
210         0,                                              /* decidePolicyForNewWindowAction */
211         pageDecidePolicyForResponseCallback,            /* decidePolicyForResponse */
212         0,                                              /* unableToImplementPolicy */
213     };
214     WKBundlePageSetPolicyClient(page, &policyClient);
215
216 };
217
218 void Bundle::willDestroyPage(WKBundlePageRef page)
219 {
220     LogDebug("Destroyed page : " << page);
221
222     auto context = m_pageGlobalContext[page];
223     m_pagesList.remove(page);
224     m_pageGlobalContext.erase(page);
225     m_pageContext.erase(page);
226
227     PluginModule::stop(context);
228 }
229
230 void Bundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
231 {
232     LogDebug("got message type: " << toString(messageName).c_str());
233     if (WKStringIsEqualToUTF8CString(messageName,
234                                      BundleMessages::START))
235     {
236         if (!messageBody || WKStringGetTypeID() != WKGetTypeID(messageBody)) {
237             LogError("Wrong message format received, ignoring");
238             return;
239         }
240
241         auto msgString = toString(static_cast<WKStringRef>(messageBody));
242         LogDebug("Got message text: " << msgString);
243         LogDebug("loading Page : " << m_pagesList.back() <<
244                  " loading JSContext : " <<
245                  m_pageGlobalContext[m_pagesList.back()]);
246         // set information from ui process
247         std::stringstream ssMsg(msgString);
248         std::string argScale;
249         std::string argEncodedBundle;
250         std::string argTheme;
251
252         ssMsg >> m_widgetHandle;
253
254         ssMsg >> argScale;
255         ssMsg >> argEncodedBundle;
256         ssMsg >> argTheme;
257         ssMsg >> m_encrypted;
258
259         WrtDB::WidgetDAOReadOnly dao(m_widgetHandle);
260         /* This type of message is received when widget is restarting
261          * (proably in other situation too). Widget restart can be
262          * called after system language change so language tags have to
263          * be recreated here.
264          * Do NOT MOVE LanguageTags reset before m_widgetHandle initialization
265          */
266         // reset language tags (create new tags based on system locales)
267         LanguageTagsProviderSingleton::Instance().resetLanguageTags();
268         DPL::OptionalString defaultLocale = dao.getDefaultlocale();
269         LanguageTags tags = LanguageTagsProviderSingleton::Instance().getLanguageTags();
270         // check if default widget language exists in language's list
271         if (!!defaultLocale &&
272             std::find(tags.begin(), tags.end(), *defaultLocale) == tags.end())
273         {
274             if (tags.size() < 2) {
275                 tags.push_front(*defaultLocale);
276             } else {
277                 LanguageTags::iterator placeToInsert = tags.end();
278                 --placeToInsert;
279                 if (*placeToInsert != L"") { ++placeToInsert; }
280                 tags.insert(placeToInsert, *defaultLocale);
281             }
282         }
283         LogDebug("Current widget locales (language tags):");
284         FOREACH(it, tags) {
285             LogDebug("Locale: " << *it);
286         }
287         LanguageTagsProviderSingleton::Instance().setLanguageTags(tags);
288         // ** Language tags setting completed **
289
290         if (argScale != "null" && argScale[0] == '_')
291         {
292             argScale.erase(0, 1);
293
294             std::stringstream ssScale(argScale);
295             ssScale >> m_scale;
296         }
297
298         if (argEncodedBundle != "null" && argEncodedBundle[0] == '_')
299         {
300             argEncodedBundle.erase(0, 1);
301
302             m_encodedBundle = argEncodedBundle;
303         }
304
305         if (argTheme != "null" && argTheme[0] == '_')
306         {
307             argTheme.erase(0, 1);
308
309             m_theme = argTheme;
310         }
311
312         m_widgetType = dao.getWidgetType();
313         LogDebug("m_widgetType : " << m_widgetType.getApptypeToString() <<
314                  "(m_widgetHandle:" << m_widgetHandle << ")");
315     }
316     else if (WKStringIsEqualToUTF8CString(messageName,
317                                           BundleMessages::SHUTDOWN))
318     {
319         LogDebug("shutdown plugins");
320         if (m_pagesList.empty())
321         {
322             PluginModule::shutdown();
323         }
324         else
325         {
326             LogInfo("PluginModule shutdown ignored, there are still alive pages!");
327         }
328     }
329     else if (WKStringIsEqualToUTF8CString(messageName,
330                                           BundleMessages::SET_CUSTOM_PROPERTIES))
331     {
332         LogDebug("reset custom properties of window objects");
333         // set information from ui process
334         auto msgString = toString(static_cast<WKStringRef>(messageBody));
335
336         std::string argScale;
337         std::string argEncodedBundle;
338         std::string argTheme;
339
340         std::stringstream ssMsg(msgString);
341         ssMsg >> argScale;
342         ssMsg >> argEncodedBundle;
343         ssMsg >> argTheme;
344
345         if(argScale != "null" && argScale[0] == '_')
346         {
347             argScale.erase(0, 1);
348
349             std::stringstream ssScale(argScale);
350             ssScale >> m_scale;
351         }
352
353         if(argEncodedBundle != "null" && argEncodedBundle[0] == '_')
354         {
355             argEncodedBundle.erase(0, 1);
356
357             m_encodedBundle = argEncodedBundle;
358         }
359
360         if(argTheme != "null" && argTheme[0] == '_')
361         {
362             argTheme.erase(0, 1);
363
364             m_theme = argTheme;
365         }
366
367         //apply for each context
368         PageGlobalContext::iterator it = m_pageGlobalContext.begin();
369         for (; it != m_pageGlobalContext.end(); ++it)
370         {
371             PluginModule::setCustomProperties(it->second,
372                                               m_scale,
373                                               m_encodedBundle.c_str(),
374                                               m_theme.c_str());
375         }
376     }
377     else if (WKStringIsEqualToUTF8CString(
378                  messageName,
379                  BundleMessages::DISPATCH_JAVASCRIPT_EVENT))
380     {
381         LogDebug("dispatch javascript event to created frames");
382         // set information from ui process
383         auto text = toString(static_cast<WKStringRef>(messageBody));
384         int eventType;
385         void *args = NULL;
386         std::stringstream ss(text);
387         ss >> eventType;
388
389         using namespace WrtPlugins::W3C;
390         // set arguments to be sent to js handler of this custom event
391         if (eventType == SoftKeyboardChangeCustomEvent) {
392             args = new SoftKeyboardChangeArgs;
393             ss >> static_cast<SoftKeyboardChangeArgs *>(args)->state;
394             ss >> static_cast<SoftKeyboardChangeArgs *>(args)->width;
395             ss >> static_cast<SoftKeyboardChangeArgs *>(args)->height;
396         }
397
398         //apply for each context
399         PageGlobalContext::iterator it = m_pageGlobalContext.begin();
400         for (; it != m_pageGlobalContext.end(); ++it)
401         {
402             PluginModule::dispatchJavaScriptEvent(
403                     it->second,
404                     static_cast<WrtPlugins::W3C::CustomEventType>(eventType),
405                     args);
406         }
407
408         if (args) {
409             delete args;
410         }
411     }
412 }
413
414 WKURLRequestRef Bundle::willSendRequestForFrameCallback(
415         WKBundlePageRef /*page*/,
416         WKBundleFrameRef /*frame*/,
417         uint64_t /*resourceIdentifier*/,
418         WKURLRequestRef request,
419         WKURLResponseRef /*response*/,
420         const void *clientInfo)
421 {
422     LogDebug("willSendRequestForFrameCallback called");
423     Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
424     return This->willSendRequestForFrame(request);
425 }
426
427 void Bundle::didStartProvisionalLoadForFrameCallback(
428         WKBundlePageRef page,
429         WKBundleFrameRef frame,
430         WKTypeRef* /*userData*/,
431         const void *clientInfo)
432 {
433     LogDebug("didStartProvisionalLoadForFrameCallback called");
434     Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
435
436     if (This->m_pageGlobalContext.count(page) == 0)
437     {
438         return;
439     }
440     if (This->m_pageContext.count(page) == 0)
441     {
442         return;
443     }
444
445     JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
446
447     ContextSet::iterator i = This->m_pageContext[page].find(context);
448
449     if (i == This->m_pageContext[page].end())
450     {
451         LogDebug("Initially attached frame");
452         return;
453     }
454
455     This->m_pageContext[page].erase(i);
456
457     PluginModule::unloadFrame(context);
458 }
459
460 void Bundle::didRemoveFrameFromHierarchyCallback(
461         WKBundlePageRef page,
462         WKBundleFrameRef frame,
463         WKTypeRef* /*userData*/,
464         const void *clientInfo)
465 {
466     LogDebug("didFinishLoadForResourceCallback called");
467     Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
468
469     if (This->m_pageGlobalContext.count(page) == 0)
470     {
471         return;
472     }
473     if (This->m_pageContext.count(page) == 0)
474     {
475         return;
476     }
477
478     JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
479
480     ContextSet::iterator i = This->m_pageContext[page].find(context);
481
482     if (i == This->m_pageContext[page].end())
483     {
484         LogWarning("Tried to unload frame which has never been loaded");
485         return;
486     }
487
488     This->m_pageContext[page].erase(i);
489
490     PluginModule::unloadFrame(context);
491 }
492
493 void Bundle::didFinishLoadForResourceCallback(
494         WKBundlePageRef /*page*/,
495         WKBundleFrameRef frame,
496         uint64_t /*resourceIdentifier*/,
497         const void* clientInfo)
498 {
499     LogDebug("didFinishLoadForResourceCallback called");
500     Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
501
502     WKURLRef url = WKBundleFrameCopyURL(frame);
503     WKTypeRef retVal = NULL;
504
505     // If url is NULL, this url has been already blocked by willsend
506     // So current page should be moved to previous page
507     if (url == NULL)
508     {
509         if (WKBundleFrameIsMainFrame(frame))
510         {
511             LogInfo("url is NULL. Go back to previous view");
512             WKStringRef blockedURL =
513                 WKStringCreateWithUTF8CString(URICHANGE_BLOCKED_URL);
514             WKBundlePostSynchronousMessage(This->m_bundle,
515                                         This->m_uriChangedMessage,
516                                         blockedURL,
517                                         &retVal);
518         }
519         else
520         {
521             LogInfo("Blocked uri in IFrame.");
522         }
523         return;
524     }
525     WKRelease(url);
526 }
527
528 void Bundle::didCommitLoadForFrameCallback(
529         WKBundlePageRef page,
530         WKBundleFrameRef frame,
531         WKTypeRef* /*userData*/,
532         const void *clientInfo)
533 {
534     LogInfo("didCommitLoadForFrameCallback called");
535     LOG_PROFILE_START("didCommitLoadForFrameCallback");
536     Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
537
538     WKURLRef url = WKBundleFrameCopyURL(frame);
539     WKTypeRef retVal = NULL;
540
541     if (url == NULL) {
542         LogInfo("url is NULL");
543         return;
544     }
545
546     JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
547
548     This->m_pageContext[page].insert(context);
549
550     if (!WKBundleFrameIsMainFrame(frame))
551     {
552         LogInfo("frame isn't main frame");
553         PluginModule::start(This->m_widgetHandle,
554                             context,
555                             This->m_scale,
556                             This->m_encodedBundle.c_str(),
557                             This->m_theme.c_str());
558         PluginModule::loadFrame(context);
559         return;
560     }
561
562     std::string scheme = getScheme(toString(url));
563     std::string result = URICHANGE_PLUGIN_RESTART;
564
565     if (scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS)
566     {
567         WKStringRef urlStr = WKURLCopyString(url);
568         WKBundlePostSynchronousMessage(This->m_bundle,
569                                        This->m_uriChangedMessage,
570                                        urlStr,
571                                        &retVal);
572         WKRelease(url);
573         WKRelease(urlStr);
574
575         result = toString(static_cast<WKStringRef>(retVal));
576     }
577     LogInfo("result from UI process : " << result);
578
579     if (result == URICHANGE_PLUGIN_STOP_ONLY)
580     {
581         PluginModule::stop(context);
582     }
583     else if (result == URICHANGE_PLUGIN_RESTART)
584     {
585         PluginModule::stop(context);
586         This->m_pageGlobalContext[page] = context;
587         LOG_PROFILE_START("PluginModule start");
588         PluginModule::start(This->m_widgetHandle,
589                             context,
590                             This->m_scale,
591                             This->m_encodedBundle.c_str(),
592                             This->m_theme.c_str() );
593         LOG_PROFILE_STOP("PluginModule start");
594
595         PluginModule::loadFrame(context);
596     }
597     LOG_PROFILE_STOP("didCommitLoadForFrameCallback");
598 }
599
600 WKBundlePagePolicyAction Bundle::pageDecidePolicyForNavigationActionCallback(
601         WKBundlePageRef             page,
602         WKBundleFrameRef            frame,
603         WKBundleNavigationActionRef navigationAction,
604         WKURLRequestRef             request,
605         WKTypeRef*                  userData,
606         const void*                 clientInfo)
607 {
608     LogDebug("pageDecidePolicyForNavigationActionCallback called");
609
610     Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
611
612     return This->pageDecidePolicyForNavigationAction(page,
613                                                      frame,
614                                                      navigationAction,
615                                                      request,
616                                                      userData);
617 }
618
619 WKBundlePagePolicyAction Bundle::pageDecidePolicyForResponseCallback(
620         WKBundlePageRef     /* page */,
621         WKBundleFrameRef    /* frame */,
622         WKURLResponseRef    response,
623         WKURLRequestRef     /* request */,
624         WKTypeRef*          /* userData */,
625         const void*         /* clientInfo */)
626 {
627     LogDebug("pageDecidePolicyForResponseCallback called");
628
629     char const * const HTML_MIME = "text/html";
630
631     Assert(response);
632     WKStringRef contentTypeRef = WKURLResponseEflCopyContentType(response);
633
634     std::string contentType = toString(contentTypeRef);
635     LogDebug("contentTypeRef : " << contentType);
636     WKRelease(contentTypeRef);
637
638     if (contentType == HTML_MIME)
639     {
640         LogDebug("Accepting HTML_MIME type");
641
642         return WKBundlePagePolicyActionUse;
643     }
644
645     return WKBundlePagePolicyActionPassThrough;
646 }
647
648 WKURLRequestRef Bundle::willSendRequestForFrame(WKURLRequestRef request)
649 {
650     LogDebug("willSendReq got " << toString(request).c_str());
651     WKURLRef url = WKURLRequestCopyURL(request);
652     WKStringRef urlStr = WKURLCopyString(url);
653
654     bool is_xhr = true; // Webkit should inform if it's XHR
655     DPL::String dplurl = DPL::FromUTF8String(toString(urlStr));
656     WKRelease(urlStr);
657     DPL::Optional<DPL::String> newurl = BundleURIHandling::processURI(dplurl,
658             is_xhr, m_widgetHandle, m_bundle);
659
660     if (newurl.IsNull()) {
661         LogDebug("URI is blocked");
662         WKRelease(url);
663         return NULL;
664     } else {
665         LogDebug("URI processing result: " << *newurl );
666         std::string tmpUrlStr = DPL::ToUTF8String(*newurl);
667         if (tmpUrlStr.empty()) {
668             LogDebug("uri is blocked");
669             WKRelease(url);
670             return NULL;
671         }
672
673         WKURLRef tmpUrl = WKURLCreateWithUTF8CString(tmpUrlStr.c_str());
674         std::string scheme = toString(WKURLCopyScheme(url));
675         WKRelease(url);
676         // Return value must contain details information of input
677         // WKURLRequestRef. Current webkit2 doesn't support api that
678         // copy WKURLRequestRef or change url only. Before webkit2
679         // support api, callback return original WKURLRequestRef in the
680         // case of external scheme
681
682         // external scheme also need to send message to UI process for
683         // checking roaming and security
684         if (scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS) {
685             LogDebug("external scheme return original WKURLRequestRef");
686             WKRelease(tmpUrl);
687             WKRetain(request);
688             return request;
689         } else {
690             std::string checkUrl = toString(tmpUrl);
691             int getFileSize;
692
693             if(m_encrypted) {
694                 if(isEncryptedResource(checkUrl, getFileSize)) {
695                     std::string decryptString = DecryptResource(checkUrl,
696                             getFileSize);
697                     if (!decryptString.empty()) {
698                         std::string destString = DATA_STRING;
699
700                         std::string mimeString =
701                             DPL::ToUTF8String(MimeTypeUtils::identifyFileMimeType(
702                                         DPL::FromUTF8String(checkUrl)));
703
704                         destString += mimeString;
705                         destString += BASE64_STRING;
706
707                         decryptString.insert(0, destString);
708
709                         WKURLRef destUrl =
710                             WKURLCreateWithUTF8CString(decryptString.c_str());
711
712                         WKURLRequestRef req = WKURLRequestCreateWithWKURL(destUrl);
713                         WKRelease(destUrl);
714                         LogDebug("return value " << decryptString << "]]");
715                         return req;
716                     }
717                 }
718             }
719             WKURLRequestRef req = WKURLRequestCreateWithWKURL(tmpUrl);
720             WKRelease(tmpUrl);
721             LogDebug("return value " << toString(req).c_str());
722             return req;
723         }
724     }
725 }
726
727 WKBundlePagePolicyAction Bundle::pageDecidePolicyForNavigationAction(
728        WKBundlePageRef             /* page */,
729        WKBundleFrameRef            frame,
730        WKBundleNavigationActionRef /* navigationAction */,
731        WKURLRequestRef             request,
732        WKTypeRef*                  /* userData */)
733 {
734     using namespace ViewModule;
735     using namespace ViewModule::SchemeActionMap;
736
737     char const * const TIZEN_SCHEME = "tizen";
738
739     std::string request_uri = toString(request);
740
741     LogInfo("Uri being checked: " << request_uri);
742
743     // get scheme string
744     std::string request_scheme = getScheme(request_uri);
745
746     // is tizen schem?
747     if ( request_scheme == TIZEN_SCHEME )
748     {
749         return WKBundlePagePolicyActionPassThrough;
750     }
751
752     // scheme action
753     Scheme scheme(request_scheme);
754     LogDebug("Scheme: " << request_scheme);
755
756     Scheme::Type type = scheme.GetType();
757     if (type < Scheme::FILE || type >= Scheme::COUNT) {
758         LogError("Invalid scheme: " << request_scheme);
759         return WKBundlePagePolicyActionPassThrough;
760     }
761
762     bool mainFrame = WKBundleFrameIsMainFrame(frame);
763     NavigationContext ctx = mainFrame ? TOP_LEVEL : FRAME_LEVEL;
764
765     LogDebug("Scheme type: " << type);
766     LogDebug("Navigation context: " << ctx);
767     LogDebug("Application type: " << m_widgetType.getApptypeToString());
768
769     UriAction action;
770
771     if (m_widgetType == WrtDB::APP_TYPE_WAC20)
772     {
773         action = g_wacActionMap[type][ctx];
774     }
775     else if (m_widgetType == WrtDB::APP_TYPE_TIZENWEBAPP)
776     {
777         action = g_tizenActionMap[type][ctx];
778     }
779     else
780     {
781         LogError("Unsupported application type: " << type);
782         return WKBundlePagePolicyActionPassThrough;
783     }
784
785     LogDebug("Uri action: " << action);
786
787     if (action == URI_ACTION_WRT)
788     {
789         return WKBundlePagePolicyActionUse;
790     }
791
792     return WKBundlePagePolicyActionPassThrough;
793
794 }
795
796 std::string Bundle::toString(WKStringRef str)
797 {
798     if (WKStringIsEmpty(str)) {
799         return std::string();
800     }
801     size_t size = WKStringGetMaximumUTF8CStringSize(str);
802     char buffer[size + 1];
803     WKStringGetUTF8CString(str, buffer, size + 1);
804     return buffer;
805 }
806
807 std::string Bundle::toString(WKURLRef url)
808 {
809     WKStringRef urlStr = WKURLCopyString(url);
810     std::string str = toString(urlStr);
811     WKRelease(urlStr);
812     return str;
813 }
814
815 std::string Bundle::toString(WKURLRequestRef req)
816 {
817     WKURLRef reqUrl = WKURLRequestCopyURL(req);
818     std::string str = toString(reqUrl);
819     WKRelease(reqUrl);
820     return str;
821 }
822
823 std::string Bundle::toString(WKErrorRef err)
824 {
825     WKStringRef domErr = WKErrorCopyDomain(err);
826     WKStringRef desc = WKErrorCopyLocalizedDescription(err);
827     std::string str = toString(domErr) + "\n" + toString(desc);
828     WKRelease(domErr);
829     WKRelease(desc);
830     return str;
831 }
832
833 std::string Bundle::getScheme(std::string uri)
834 {
835     std::size_t found = uri.find(':');
836     std::string str;
837
838     if (found != std::string::npos)
839     {
840         str = uri.substr(0, found);
841     }
842
843     return str;
844 }
845
846 bool Bundle::isEncryptedResource(std::string Url, int &size)
847 {
848     std::string filePath;
849
850     size_t pos = Url.find_first_not_of(SCHEME_FILE);
851     if ( std::string::npos != pos) {
852         filePath = Url.substr(pos-1);
853     }
854
855     if (m_encryptedFiles.empty()) {
856         WrtDB::WidgetDAOReadOnly(m_widgetHandle).
857             getEncryptedFileList(m_encryptedFiles);
858     }
859
860     WrtDB::EncryptedFileInfo info;
861     std::set<WrtDB::EncryptedFileInfo>::iterator it;
862     info.fileName = DPL::FromUTF8String(filePath);
863
864     if ((0 == strncmp(Url.c_str(), SCHEME_FILE, strlen(SCHEME_FILE))) &&
865             (m_encryptedFiles.end() != (it =
866              m_encryptedFiles.find(info)))) {
867         LogDebug(" info file name : " << it->fileName);
868         LogDebug(" info file size : " << it->fileSize);
869         size = it->fileSize;
870         return true;
871     }
872     return false;
873 }
874
875 std::string Bundle::DecryptResource(std::string resource, int size)
876 {
877     std::string filePath;
878
879     size_t pos = resource.find_first_not_of(SCHEME_FILE);
880     if ( std::string::npos != pos) {
881         filePath = resource.substr(pos-1);
882     }
883
884     struct stat buf;
885     if (0 == stat(filePath.c_str(), &buf)) {
886         if (NULL == m_resDec) {
887             using namespace WrtDB;
888             DPL::Optional<DPL::String> pkgName =
889                 WidgetDAOReadOnly(m_widgetHandle).getPkgname();
890             m_resDec = new
891                 WRTDecryptor::ResourceDecryptor(DPL::ToUTF8String(*pkgName));
892             WrtDB::WidgetDAOReadOnly(m_widgetHandle).
893                 getEncryptedFileList(m_encryptedFiles);
894         }
895         size_t bufSize = buf.st_size;
896         unsigned char contents[bufSize];
897         memset(contents, 0, bufSize);
898
899         FILE* fp = fopen(filePath.c_str(), "rb");
900         if ( NULL == fp) {
901             LogDebug("Couldnot open file : " << filePath);
902             return std::string();
903         }
904
905         size_t ret = fread(contents, sizeof(unsigned char), buf.st_size, fp);
906         if (ret <  static_cast<size_t>(buf.st_size) ){
907             LogDebug("Couldnot read file : " << filePath);
908             fclose(fp);
909             return std::string();
910         }
911
912         fclose(fp);
913
914         LogDebug("resource is encrypted. decrypting....");
915         unsigned char outDecBuf[bufSize];
916         memset(outDecBuf, 0, bufSize);
917         m_resDec->GetDecryptedChunk(contents, outDecBuf, bufSize);
918         memset(outDecBuf+size, '\n', bufSize - size);
919
920         LogDebug("resource need to encoding base64");
921         BIO *bmem, *b64;
922         BUF_MEM *bptr;
923
924         b64 = BIO_new(BIO_f_base64());
925         bmem = BIO_new(BIO_s_mem());
926         b64 = BIO_push(b64, bmem);
927         BIO_write(b64, outDecBuf, bufSize);
928         BIO_flush(b64);
929         BIO_get_mem_ptr(b64, &bptr);
930
931         std::string base64Enc((char *)bptr->data, bptr->length-1);
932         BIO_free_all(b64);
933
934         return base64Enc;
935     }
936     return std::string();
937 }
938
939
940 extern "C"
941 {
942     WK_EXPORT
943     void WKBundleInitialize(WKBundleRef bundle,
944                             WKTypeRef)
945     {
946         DPL::Log::LogSystemSingleton::Instance().SetTag("WRT-BUNDLE");
947         LogDebug("Bundle initialized");
948
949         static Bundle s_bundle = Bundle(bundle);
950
951         WKBundleClient client = {
952             kWKBundleClientCurrentVersion,
953             &s_bundle,
954             &Bundle::didCreatePageCallback,
955             &Bundle::willDestroyPageCallback,
956             0, /* didInitializePageGroup */
957             &Bundle::didReceiveMessageCallback
958         };
959         WKBundleSetClient(bundle, &client);
960 }
961 }