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