2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file wrt-injected-bundle.cpp
18 * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
19 * @brief Implementation file for injected bundle
21 #include "wrt-injected-bundle.h"
24 #include <WKBundleInitialize.h>
25 #include <WKBundlePage.h>
26 #include <WKBundleFrame.h>
27 #include <WKURLRequest.h>
32 #include <WKURLResponseTizen.h>
33 #include <WKBundlePagePrivate.h>
34 #include <WKBundlePrivate.h>
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>
54 #include <wrt_plugin_module.h>
55 #include <profiling_util.h>
57 #include <appcore-efl.h>
59 #include <message_support.h>
62 #include <scheme_action_map_type.h>
63 #include <scheme_action_map_data.h>
65 #include <js_overlay_types.h>
66 #include <dispatch_event_support.h>
67 #include <plugins-ipc-message/ipc_message_support.h>
69 #include <sys/resource.h>
70 #include <privilege-control.h>
71 #include <smack_labeling_support.h>
73 // URI localization on WebProcess side
74 #include "injected_bundle_uri_handling.h"
75 #include "injected_bundle_decryption_support.h"
76 #include "injected_bundle_viewmodes_support.h"
79 const char * const SCHEME_HTTP = "http";
80 const char * const SCHEME_HTTPS = "https";
81 const char * const SCHEME_FILE = "file";
82 const char * const SCHEME_FILE_SLASH = "file://";
83 const char * const SCHEME_BOX_SLASH = "box://";
84 const char * const BLANK_PAGE_URL = "about:blank";
85 const char * const HTML_MIME = "text/html";
86 const char * const PHP_MIME = "application/x-php";
87 const std::size_t FILE_BUF_MAX_SIZE = 1024; // bytes
88 const std::size_t PLAIN_CHUNK_SIZE = 1008; // bytes
89 const unsigned int UID_ROOT = 0;
90 const unsigned int DEFAULT_PRIORITY = 0;
91 const char * const PRIVILEGE_APP_TYPE = "wgt";
92 #ifdef CORS_WHITELISTING_ENABLED
93 const char * const warpAllowProtocolsForWildcard[] = { "http", "https" };
97 Bundle::Bundle(WKBundleRef bundle) :
102 m_willRemoveContext(NULL),
103 m_widgetType(WrtDB::APP_TYPE_UNKNOWN),
104 m_securityModelVersion(
105 WrtDB::WidgetSecurityModelVersion::WIDGET_SECURITY_MODEL_V1),
106 m_initialized(false),
107 m_decryptionSupport(new InjectedBundle::DecryptionSupport())
110 LOG_PROFILE_START("Bundle attachToThread");
111 WrtDB::WrtDatabase::attachToThreadRO();
112 LOG_PROFILE_STOP("Bundle attachToThread");
113 } Catch (DPL::DB::SqlConnection::Exception::Base) {
114 LogError("## Db attach was failed! Terminate WebProcess by force. ##");
118 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
125 WrtDB::WrtDatabase::detachFromThread();
127 if (!m_pagesList.empty()) {
128 LogError("There are not closed pages!");
133 void Bundle::didCreatePageCallback(
134 WKBundleRef /*bundle*/,
135 WKBundlePageRef page,
136 const void* clientInfo)
138 LOG_PROFILE_START("didCreatePageCallback");
139 LogDebug("didCreatePageCallback called");
140 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
141 This->didCreatePage(page);
142 LOG_PROFILE_STOP("didCreatePageCallback");
145 void Bundle::didReceiveMessageCallback(
146 WKBundleRef /*bundle*/,
147 WKStringRef messageName,
148 WKTypeRef messageBody,
149 const void *clientInfo)
151 LogDebug("didReceiveMessageCallback called");
152 Bundle* bundle = static_cast<Bundle*>(const_cast<void*>(clientInfo));
153 bundle->didReceiveMessage(messageName, messageBody);
156 void Bundle::willDestroyPageCallback(
157 WKBundleRef /*bundle*/,
158 WKBundlePageRef page,
159 const void* clientInfo)
161 LogDebug("willDestroyPageCallback called");
162 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
163 This->willDestroyPage(page);
166 void Bundle::didCreatePage(WKBundlePageRef page)
170 LogError("## Injected-bundle was not initialized! Terminate WebProcess by force. ##");
174 auto mainFrame = WKBundlePageGetMainFrame(page);
175 auto context = WKBundleFrameGetJavaScriptContext(mainFrame);
176 m_pagesList.push_back(page);
177 m_pageGlobalContext.insertContextForPage(page, context);
178 LogDebug("created Page : " << page << " created JSContext : " << context);
179 m_viewmodesSupport->initialize(page);
181 WKBundlePageResourceLoadClient resourceLoadClient = {
182 kWKBundlePageResourceLoadClientCurrentVersion, /* version */
183 this, /* clientinfo */
184 0, /* didInitiateLoadForResource */
185 willSendRequestForFrameCallback, /* willSendRequestForFrame */
186 0, /* didReceiveResponseForResource */
187 0, /* didReceiveContentLengthForResource */
188 0, /* didFinishLoadForResource */
189 0, /* didFailLoadForResource */
190 0, /* shouldCacheResponse */
191 0, /* shouldUseCredentialStorage */
193 WKBundlePageSetResourceLoadClient(page, &resourceLoadClient);
195 WKBundlePageLoaderClient loaderClient = {
196 kWKBundlePageLoaderClientCurrentVersion,
197 this, /* clientinfo */
198 didStartProvisionalLoadForFrameCallback, /* didStartProvisionalLoadForFrame */
199 0, /* didReceiveServerRedirectForProvisionalLoadForFrame */
200 0, /* didFailProvisionalLoadWithErrorForFrame */
201 didCommitLoadForFrameCallback, /* didCommitLoadForFrame */
202 0, /* didFinishDocumentLoadForFrame */
203 0, /* didFinishLoadForFrame */
204 0, /* didFailLoadWithErrorForFrame */
205 0, /* didSameDocumentNavigationForFrame */
206 0, /* didReceiveTitleForFrame */
207 0, /* didFirstLayoutForFrame */
208 0, /* didFirstVisuallyNonEmptyLayoutForFrame */
209 didRemoveFrameFromHierarchyCallback, /* didRemoveFrameFromHierarchy */
210 0, /* didDisplayInsecureContentForFrame */
211 0, /* didRunInsecureContentForFrame */
212 0, /* didClearWindowObjectForFrame */
213 0, /* didCancelClientRedirectForFrame */
214 0, /* willPerformClientRedirectForFrame */
215 0, /* didHandleOnloadEventsForFrame */
216 0, /* didLayoutForFrame */
217 0, /* didNewFirstVisuallyNonEmptyLayout */
218 0, /* didDetectXSSForFrame */
219 0, /* shouldGoToBackForwardListItem */
220 0, /* globalObjectIsAvailableForFrame */
221 0, /* willDisconnectDOMWindowExtensionFromGlobalObject */
222 0, /* didReconnectDOMWindowExtensionToGlobalObject */
223 0, /* willDestroyGlobalObjectForDOMWindowExtension */
224 0, /* didFinishProgress */
225 0, /* shouldForceUniversalAccessFromLocalURL */
226 0, /* didReceiveIntentForFrame */
227 0, /* registerIntentServiceForFrame */
229 WKBundlePageSetPageLoaderClient(page, &loaderClient);
232 WKBundlePagePolicyClient policyClient = {
233 kWKBundlePagePolicyClientCurrentVersion, /* version */
234 this, /* clientInfo */
235 decidePolicyForNavigationActionCallback, /* decidePolicyForNavigationAction */
236 decidePolicyForNewWindowActionCallback, /* decidePolicyForNavigationAction */
237 decidePolicyForResponseCallback, /* decidePolicyForResponse */
238 0, /* unableToImplementPolicy */
240 WKBundlePageSetPolicyClient(page, &policyClient);
243 void Bundle::willDestroyPage(WKBundlePageRef page)
245 LogDebug("Destroyed page : " << page);
247 auto context = m_pageGlobalContext.getContextForPage(page);
248 m_pagesList.remove(page);
249 m_pageGlobalContext.removeContextForPage(page);
250 m_pageContext[page].erase(context);
251 m_viewmodesSupport->deinitialize(page);
253 PluginModule::unloadFrame(context);
254 PluginModule::stop(context);
257 void Bundle::fixWKMessageArgs(std::string & argScale,
258 std::string & argEncodedBundle,
259 std::string & argTheme)
261 if (argScale != "null" && argScale[0] == '_') {
262 argScale.erase(0, 1);
264 std::stringstream ssScale(argScale);
268 if (argEncodedBundle != "null" && argEncodedBundle[0] == '_') {
269 argEncodedBundle.erase(0, 1);
271 m_encodedBundle = argEncodedBundle;
274 if (argTheme != "null" && argTheme[0] == '_') {
275 argTheme.erase(0, 1);
281 #ifdef CORS_WHITELISTING_ENABLED
282 void Bundle::bypassCORSforWARPAccessList(WrtDB::WidgetDAOReadOnly & dao)
284 // bypassing CORS using origin whitelist
285 WrtDB::WidgetAccessInfoList WAList;
286 dao.getWidgetAccessInfo(WAList);
289 const WrtDB::WidgetAccessInfo & access = *it;
290 WKURLRef url = WKURLCreateWithUTF8CString(DPL::ToUTF8String(access.strIRI).c_str());
292 #ifdef APP_SCHEME_ENABLED
293 std::string source = std::string("app://") + DPL::ToUTF8String(m_widgetTizenId) + "/";
295 std::string source = DPL::ToUTF8String(dao.getFullPath());
298 LogDebug("WARP to WK whitelist position: " << source << " for "
299 << access.strIRI << " subDomains: " << access.bSubDomains);
301 WKStringRef wkSource = WKStringCreateWithUTF8CString(source.c_str());
303 WKStringRef wkProtocol;
304 if(access.strIRI == L"*")
306 //wildcard force to explicitly say which protocol is used
307 // passed wkHost if empty means wildcard -> allow everything but protocol has to be set.
308 for(unsigned i = 0; i < sizeof(warpAllowProtocolsForWildcard) / sizeof(char*); i++)
310 wkHost = WKStringCreateWithUTF8CString("");
311 wkProtocol = WKStringCreateWithUTF8CString(warpAllowProtocolsForWildcard[i]);
312 WKBundleAddOriginAccessWhitelistEntry(m_bundle,
313 wkSource, wkProtocol, wkHost, access.bSubDomains);
318 wkHost = WKURLCopyHostName(url);
319 wkProtocol = WKURLCopyScheme(url);
320 WKBundleAddOriginAccessWhitelistEntry(m_bundle,
321 wkSource, wkProtocol, wkHost, access.bSubDomains);
325 WKRelease(wkProtocol);
331 void Bundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
333 LogDebug("got message type: " << toString(messageName).c_str());
334 if (WKStringIsEqualToUTF8CString(messageName,
335 Message::ToInjectedBundle::START))
337 if (!messageBody || WKStringGetTypeID() != WKGetTypeID(messageBody)) {
338 LogError("Wrong message format received, ignoring");
342 std::string msgString =
343 toString(static_cast<WKStringRef>(messageBody));
344 LogDebug("Got message text: " << msgString);
345 LogDebug("loading Page : " << m_pagesList.back() <<
346 " loading JSContext : " <<
347 m_pageGlobalContext.getContextForPage(m_pagesList.back()));
348 // set information from ui process
349 std::stringstream ssMsg(msgString);
350 std::string argScale;
351 std::string argEncodedBundle;
352 std::string argTheme;
356 m_widgetTizenId = DPL::FromASCIIString(id);
359 ssMsg >> argEncodedBundle;
362 // ** Language tags setting completed **
363 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
364 } else if (WKStringIsEqualToUTF8CString(messageName,
365 Message::ToInjectedBundle::SHUTDOWN))
367 LogDebug("shutdown plugins");
369 if (m_pagesList.empty()) {
370 PluginModule::shutdown();
373 "PluginModule shutdown ignored, there are still alive pages!");
376 else if (WKStringIsEqualToUTF8CString(messageName,
377 Message::ToInjectedBundle::SET_CUSTOM_PROPERTIES))
379 LogDebug("reset custom properties of window objects");
380 // set information from ui process
381 std::string msgString =
382 toString(static_cast<WKStringRef>(messageBody));
384 std::string argScale;
385 std::string argEncodedBundle;
386 std::string argTheme;
388 std::stringstream ssMsg(msgString);
390 ssMsg >> argEncodedBundle;
393 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
395 //apply for each context
396 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
397 for (; it != m_pageGlobalContext.end(); ++it) {
398 PluginModule::setCustomProperties(it->second,
400 m_encodedBundle.c_str(),
403 } else if (WKStringIsEqualToUTF8CString(
405 Message::ToInjectedBundle::DISPATCH_JS_EVENT))
407 LogDebug("dispatch javascript event to created frames");
408 using namespace WrtPlugins::W3C;
410 // set information from ui process
411 std::string text = toString(static_cast<WKStringRef>(messageBody));
413 SoftKeyboardChangeArgs softKeyboardArgs;
415 std::stringstream ss(text);
418 if (eventType == SoftKeyboardChangeCustomEvent)
420 ss >> softKeyboardArgs.state;
421 ss >> softKeyboardArgs.width;
422 ss >> softKeyboardArgs.height;
425 //apply for each context
426 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
428 for (; it != m_pageGlobalContext.end(); ++it)
430 if (eventType == SoftKeyboardChangeCustomEvent)
432 DispatchEventSupport::dispatchSoftKeyboardChangeEvent(it->second,
433 softKeyboardArgs.state,
434 softKeyboardArgs.width,
435 softKeyboardArgs.height);
438 } else if (WKStringIsEqualToUTF8CString(
440 Message::ToInjectedBundle::INIT))
442 LogDebug("initialize");
444 if (!m_initialized) {
445 std::string msgString = toString(static_cast<WKStringRef>(messageBody));
446 m_widgetTizenId = DPL::FromASCIIString(msgString);
447 WrtDB::WidgetDAOReadOnly dao(m_widgetTizenId);
449 // process pool - set app_privilige
450 if (UID_ROOT == getuid()) {
451 using namespace WrtDB::GlobalConfig;
454 std::string tzAppId = DPL::ToUTF8String(dao.getTzAppId());
455 std::string tzPkgId = DPL::ToUTF8String(dao.getTizenPkgId());
456 DPL::OptionalString installedPath = dao.getWidgetInstalledPath();
457 if (installedPath.IsNull()) {
458 appPath = std::string(GetUserInstalledWidgetPath()) + "/" +
459 tzPkgId + GetUserWidgetExecPath() + "/" + tzAppId;
461 appPath = DPL::ToUTF8String(*installedPath) +
462 GetUserWidgetExecPath() + "/" + tzAppId;
465 LogDebug("set_app_smack_label(" << appPath << ")");
466 if (set_app_smack_label(appPath.c_str()) != 0)
468 LogError("set_app_smack_label() failed");
471 LogDebug("set_app_privilege(" << appPath << ")");
472 set_app_privilege(tzPkgId.c_str(), PRIVILEGE_APP_TYPE, appPath.c_str());
475 /* This type of message is received when widget is restarting
476 * (proably in other situation too). Widget restart can be
477 * called after system language change so language tags have to
479 * Do NOT MOVE LanguageTags reset before m_widgetHandle initialization
481 // reset language tags (create new tags based on system locales)
482 LanguageTagsProviderSingleton::Instance().resetLanguageTags();
483 DPL::OptionalString defaultLocale = dao.getDefaultlocale();
484 if (!defaultLocale.IsNull()) {
485 LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
489 LanguageTagsProviderSingleton::Instance().getLanguageTags();
490 LogDebug("Current widget locales (language tags):");
492 LogDebug("Locale: " << *it);
495 m_widgetType = dao.getWidgetType();
496 LogDebug("m_widgetType : " << m_widgetType.getApptypeToString() <<
497 "(m_widgetTizenId:" << m_widgetTizenId << ")");
499 LogDebug("Preload PluginLogicSingleton");
500 PluginModule::init(WrtDB::WidgetDAOReadOnly::getHandle(m_widgetTizenId));
501 LogDebug("Preload PluginLogicSingleton_end");
503 m_securityModelVersion = dao.getSecurityModelVersion();
504 #ifdef CORS_WHITELISTING_ENABLED
505 bypassCORSforWARPAccessList(dao);
507 m_decryptionSupport->initialize(m_widgetTizenId);
508 m_viewmodesSupport.reset(
509 new InjectedBundle::ViewmodesSupport(m_widgetTizenId));
510 m_initialized = true;
512 LogDebug("already initalized");
514 } else if (WKStringIsEqualToUTF8CString(
516 Message::ToInjectedBundle::SET_XWINDOW_HANDLE))
518 std::string msgString =
519 toString(static_cast<WKStringRef>(messageBody));
520 LogDebug("set x window handle [" << msgString << "]");
521 IPCMessageSupport::setXwindowHandle(atoi(msgString.c_str()));
522 } else if (WKStringIsEqualToUTF8CString(
524 Message::ToInjectedBundle::SET_VIEWMODES))
526 std::string msgBody =
527 toString(static_cast<WKStringRef>(messageBody));
528 LogDebug("set viewmode to [" << msgBody << "]");
529 if (msgBody == Message::ToInjectedBundle::SET_VIEWMODES_MSGBODY_EXIT) {
530 m_viewmodesSupport->exitViewmodesAllPages();
532 m_viewmodesSupport->enterViewmodesAllPages(msgBody);
537 WKURLRequestRef Bundle::willSendRequestForFrameCallback(
538 WKBundlePageRef /*page*/,
539 WKBundleFrameRef /*frame*/,
540 uint64_t /*resourceIdentifier*/,
541 WKURLRequestRef request,
542 WKURLResponseRef /*response*/,
543 const void *clientInfo)
545 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
546 WKURLRequestRef ret = This->willSendRequestForFrame(request);
551 void Bundle::didStartProvisionalLoadForFrameCallback(
552 WKBundlePageRef page,
553 WKBundleFrameRef frame,
554 WKTypeRef* /*userData*/,
555 const void *clientInfo)
557 LogDebug("didStartProvisionalLoadForFrameCallback called");
558 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
560 if (This->m_pageGlobalContext.find(page) == This->m_pageGlobalContext.end()) {
563 if (This->m_pageContext.count(page) == 0) {
567 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
569 ContextSet::iterator i = This->m_pageContext[page].find(context);
571 if (i == This->m_pageContext[page].end()) {
572 LogDebug("Initially attached frame");
576 This->m_pageContext[page].erase(i);
577 This->m_willRemoveContext = context;
580 void Bundle::didRemoveFrameFromHierarchyCallback(
581 WKBundlePageRef page,
582 WKBundleFrameRef frame,
583 WKTypeRef* /*userData*/,
584 const void *clientInfo)
586 LogDebug("didRemoveFrameFromHierarchyCallback called");
587 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
589 if (This->m_pageContext.count(page) == 0) {
590 LogDebug("his->m_pageContext.count(page) == 0");
594 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
596 ContextSet::iterator i = This->m_pageContext[page].find(context);
598 if (i == This->m_pageContext[page].end()) {
599 LogWarning("Tried to unload frame which has never been loaded");
603 This->m_pageContext[page].erase(i);
605 PluginModule::unloadFrame(context);
608 void Bundle::didFinishLoadForResourceCallback(
609 WKBundlePageRef /*page*/,
610 WKBundleFrameRef /*frame*/,
611 uint64_t /*resourceIdentifier*/,
612 const void* /*clientInfo*/)
614 LogDebug("didFinishLoadForResourceCallback called");
617 void Bundle::didCommitLoadForFrameCallback(
618 WKBundlePageRef page,
619 WKBundleFrameRef frame,
620 WKTypeRef* /*userData*/,
621 const void *clientInfo)
623 LogInfo("didCommitLoadForFrameCallback called");
624 LOG_PROFILE_START("didCommitLoadForFrameCallback");
625 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
627 WKURLRef url = WKBundleFrameCopyURL(frame);
630 LogInfo("url is NULL");
634 if (This->m_willRemoveContext) {
635 PluginModule::unloadFrame(This->m_willRemoveContext);
636 This->m_willRemoveContext = NULL;
639 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
641 This->m_pageContext[page].insert(context);
643 if (!WKBundleFrameIsMainFrame(frame)) {
644 LogInfo("frame isn't main frame");
646 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
649 This->m_encodedBundle.c_str(),
650 This->m_theme.c_str());
651 PluginModule::loadFrame(context);
655 std::string urlStr = toString(url);
656 if (InjectedBundleURIHandling::processURIForPlugin(urlStr.c_str(),
657 This->m_widgetTizenId))
659 LogDebug("start plugin");
660 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
662 LogDebug("Previous context: " << This->m_pageGlobalContext.getContextForPage(page));
663 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
665 LogDebug("New context: " << context);
666 //note that since we need old context for unloading plugins it must be sotred
667 //custom container take care of increamenting and decrementing references
668 This->m_pageGlobalContext.insertContextForPage(page, context);
669 LOG_PROFILE_START("PluginModule start");
671 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
674 This->m_encodedBundle.c_str(),
675 This->m_theme.c_str() );
676 LOG_PROFILE_STOP("PluginModule start");
678 PluginModule::loadFrame(context);
680 LogDebug("stop plugin");
681 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
683 LogDebug("Previous context: " << This->m_pageGlobalContext.getContextForPage(page));
684 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
686 LogDebug("New context: " << context);
687 This->m_pageGlobalContext.insertContextForPage(page, context);
689 LOG_PROFILE_STOP("didCommitLoadForFrameCallback");
692 WKBundlePagePolicyAction Bundle::decidePolicyForNavigationActionCallback(
693 WKBundlePageRef page,
694 WKBundleFrameRef frame,
695 WKBundleNavigationActionRef navigationAction,
696 WKURLRequestRef request,
698 const void* clientInfo)
700 LogDebug("decidePolicyForNavigationActionCallback called");
702 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
703 return This->decidePolicyForAction(false,
711 WKBundlePagePolicyAction Bundle::decidePolicyForNewWindowActionCallback(
712 WKBundlePageRef page,
713 WKBundleFrameRef frame,
714 WKBundleNavigationActionRef navigationAction,
715 WKURLRequestRef request,
716 WKStringRef /*frameName*/,
718 const void* clientInfo)
720 LogDebug("decidePolicyForNewWindowActionCallback called");
722 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
723 return This->decidePolicyForAction(true,
731 WKBundlePagePolicyAction Bundle::decidePolicyForResponseCallback(
732 WKBundlePageRef /* page */,
733 WKBundleFrameRef /* frame */,
734 WKURLResponseRef response,
735 WKURLRequestRef /* request */,
736 WKTypeRef* /* userData */,
737 const void* /* clientInfo */)
739 LogDebug("decidePolicyForResponseCallback called");
742 WKStringRef contentTypeRef = WKURLResponseEflCopyContentType(response);
744 std::string contentType = toString(contentTypeRef);
745 LogDebug("contentTypeRef : " << contentType);
746 WKRelease(contentTypeRef);
748 if (contentType == HTML_MIME) {
749 LogDebug("Accepting HTML_MIME type");
750 return WKBundlePagePolicyActionUse;
752 if (contentType == PHP_MIME) {
753 LogDebug("Accepting php type");
754 return WKBundlePagePolicyActionUse;
757 return WKBundlePagePolicyActionPassThrough;
760 WKURLRequestRef Bundle::willSendRequestForFrame(WKURLRequestRef request)
762 static bool logEnable = (getenv("WRT_WILL_SEND_REQUEST_LOG_ENABLE") != NULL);
764 WKURLRef wkUrl = WKURLRequestCopyURL(request);
765 WKStringRef wkStr = WKURLCopyString(wkUrl);
767 std::string stdUrl = Bundle::toString(wkStr);
768 std::string localizedUrl;
773 if (logEnable){ LogDebug("willSendRequestForFrame : " << stdUrl); }
775 localizedUrl = InjectedBundleURIHandling::localizeURI(stdUrl, DPL::ToUTF8String(m_widgetTizenId));
776 bool ret = InjectedBundleURIHandling::processURI(localizedUrl, m_widgetTizenId, m_securityModelVersion);
780 LogDebug("Not permitted resource: " << localizedUrl);
784 // log disabled for performance
785 //LogDebug("URI processing result: " << result);
786 std::string scheme = localizedUrl.substr(0, localizedUrl.find_first_of(':'));
788 #ifdef APP_SCHEME_ENABLED
789 if (scheme == SCHEME_FILE)
791 LogError("File schema blocked for: " << stdUrl);
796 // Return value must contain details information of input
797 // WKURLRequestRef. Current webkit2 doesn't support api that
798 // copy WKURLRequestRef or change url only. Before webkit2
799 // support api, callback return original WKURLRequestRef in the
800 // case of external scheme
802 // external scheme also need to send message to UI process for
803 // checking roaming and security
805 if (scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS)
807 if (logEnable){ LogDebug("external scheme return original WKURLRequestRef"); }
814 std::string checkUrl = localizedUrl;
816 if (m_decryptionSupport->isNeedDecryption(checkUrl))
818 std::string decryptString =
819 m_decryptionSupport->decryptResource(checkUrl);
821 if (logEnable){ LogDebug("return value : " << decryptString ); }
824 WKURLCreateWithUTF8CString(decryptString.c_str());
825 WKURLRequestRef req = WKURLRequestCreateWithWKURL(destUrl);
832 WKURLRef newUrl = WKURLCreateWithUTF8CString(localizedUrl.c_str());
833 WKURLRequestRef req = WKURLRequestCreateWithWKURL(newUrl);
836 if (logEnable){ LogDebug("return value : " << localizedUrl); }
841 WKBundlePagePolicyAction Bundle::decidePolicyForAction(
843 WKBundlePageRef /* page */,
844 WKBundleFrameRef frame,
845 WKBundleNavigationActionRef /* navigationAction */,
846 WKURLRequestRef request,
847 WKTypeRef* /* userData */)
849 using namespace ViewModule;
850 using namespace ViewModule::SchemeActionMap;
852 char const * const TIZEN_SCHEME = "tizen";
854 std::string request_uri = toString(request);
856 LogInfo("Uri being checked: " << request_uri);
859 if (request_uri == BLANK_PAGE_URL) {
860 return WKBundlePagePolicyActionUse;
863 // in case of box scheme, unconditionally PassThrough should be returned
864 if (!request_uri.compare(0, 6, SCHEME_BOX_SLASH)) {
865 return WKBundlePagePolicyActionPassThrough;
868 DPL::String dplUrl = DPL::FromUTF8String(request_uri);
870 InjectedBundleURIHandling::processMainResource(dplUrl,
872 m_securityModelVersion);
874 std::string blockedUrl = DPL::ToUTF8String(dplUrl);
875 LogDebug("URI is blocked: " << blockedUrl);
877 // Send information about blocked URI to UIProcess
878 WKStringRef urlStr = WKStringCreateWithUTF8CString(blockedUrl.c_str());
879 WKStringRef blockMessage =
880 WKStringCreateWithUTF8CString(Message::ToUIProcess::BLOCKED_URL);
881 WKBundlePostMessage(m_bundle, blockMessage, urlStr);
883 WKRelease(blockMessage);
884 return WKBundlePagePolicyActionPassThrough;
888 std::string request_scheme = getScheme(request_uri);
891 if (request_scheme == TIZEN_SCHEME) {
892 return WKBundlePagePolicyActionPassThrough;
896 Scheme scheme(request_scheme);
897 LogDebug("Scheme: " << request_scheme);
899 Scheme::Type type = scheme.GetType();
900 if (type < Scheme::FILE || type >= Scheme::COUNT) {
901 LogError("Invalid scheme: " << request_scheme);
902 return WKBundlePagePolicyActionPassThrough;
905 bool mainFrame = WKBundleFrameIsMainFrame(frame);
906 NavigationContext ctx = mainFrame ? TOP_LEVEL : FRAME_LEVEL;
911 LogDebug("Scheme type: " << type);
912 LogDebug("Navigation context: " << ctx);
913 LogDebug("Application type: " << m_widgetType.getApptypeToString());
917 if (m_widgetType == WrtDB::APP_TYPE_TIZENWEBAPP) {
918 action = g_tizenActionMap[type][ctx];
920 LogError("Unsupported application type: " << type);
921 return WKBundlePagePolicyActionPassThrough;
924 LogDebug("Uri action: " << action);
926 if (action != URI_ACTION_WRT) {
927 return WKBundlePagePolicyActionPassThrough;
930 return WKBundlePagePolicyActionUse;
933 std::string Bundle::toString(WKStringRef str)
935 if (WKStringIsEmpty(str))
941 size_t size = WKStringGetMaximumUTF8CStringSize(str);
943 char buffer[size + 1];
944 WKStringGetUTF8CString(str, buffer, sizeof(buffer));
950 std::string Bundle::toString(WKURLRef url)
952 WKStringRef urlStr = WKURLCopyString(url);
953 std::string str = toString(urlStr);
958 std::string Bundle::toString(WKURLRequestRef req)
960 WKURLRef reqUrl = WKURLRequestCopyURL(req);
961 std::string str = toString(reqUrl);
966 std::string Bundle::toString(WKErrorRef err)
968 WKStringRef domErr = WKErrorCopyDomain(err);
969 WKStringRef desc = WKErrorCopyLocalizedDescription(err);
970 std::string str = toString(domErr) + "\n" + toString(desc);
976 std::string Bundle::getScheme(std::string uri)
978 std::size_t found = uri.find(':');
981 if (found != std::string::npos) {
982 str = uri.substr(0, found);
988 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
989 void Bundle::sendWebProcessPid()
991 std::stringstream strPid;
993 WKStringRef pidStr = WKStringCreateWithUTF8CString(strPid.str().c_str());
994 WKStringRef message =
995 WKStringCreateWithUTF8CString(
996 Message::ToUIProcess::SEND_WEBPROCESS_PID);
997 WKBundlePostMessage(m_bundle, message, pidStr);
1006 void WKBundleInitialize(WKBundleRef bundle,
1009 DPL::Log::LogSystemSingleton::Instance().SetTag("WRT-BUNDLE");
1010 LogDebug("Bundle initialized");
1012 DPL::Event::GetMainEventDispatcherInstance().ResetCrossEventCallHandler();
1013 LogDebug("ResetCrossEventCallHandler()");
1015 static Bundle s_bundle(bundle);
1017 WKBundleClient client = {
1018 kWKBundleClientCurrentVersion,
1020 &Bundle::didCreatePageCallback,
1021 &Bundle::willDestroyPageCallback,
1022 0, /* didInitializePageGroup */
1023 &Bundle::didReceiveMessageCallback
1025 WKBundleSetClient(bundle, &client);
1027 // process pool - restore process priority
1028 if (UID_ROOT == getuid())
1030 setpriority(PRIO_PROCESS, 0, DEFAULT_PRIORITY);
1032 IPCMessageSupport::setWKBundleRef(bundle);