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