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/foreach.h>
43 #include <dpl/assert.h>
44 #include <dpl/wrt-dao-ro/WrtDatabase.h>
45 #include <dpl/localization/localization_utils.h>
46 #include <dpl/string.h>
47 #include <dpl/wrt-dao-ro/global_config.h>
48 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
49 #include <dpl/wrt-dao-ro/common_dao_types.h>
50 #include <dpl/localization/LanguageTagsProvider.h>
51 #include <dpl/event/main_event_dispatcher.h>
53 #include <dpl/log/secure_log.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 SCHEME_HTTP[] = "http";
80 const char SCHEME_HTTPS[] = "https";
81 const char SCHEME_FILE[] = "file";
82 const char SCHEME_FILE_SLASH[] = "file://";
83 const char SCHEME_BOX_SLASH[] = "box://";
84 const char BLANK_PAGE_URL[] = "about:blank";
85 const char SRC_DOC_PAGE_URL[] = "about:srcdoc";
86 const char HTML_MIME[] = "text/html";
87 const char PHP_MIME[] = "application/x-php";
88 const char WRT_WILL_SEND_REQUEST_LOG_ENABLE[] = "WRT_WILL_SEND_REQUEST_LOG_ENABLE";
89 const std::size_t FILE_BUF_MAX_SIZE = 1024; // bytes
90 const std::size_t PLAIN_CHUNK_SIZE = 1008; // bytes
91 const unsigned int UID_ROOT = 0;
92 const unsigned int DEFAULT_PRIORITY = 0;
93 const char PRIVILEGE_APP_TYPE[] = "wgt";
94 #ifdef CORS_WHITELISTING_ENABLED
95 const char * const warpAllowProtocolsForWildcard[] = { "http", "https" };
99 Bundle::Bundle(WKBundleRef bundle) :
104 m_willRemoveContext(NULL),
105 m_securityModelVersion(
106 WrtDB::WidgetSecurityModelVersion::WIDGET_SECURITY_MODEL_V1),
107 m_initialized(false),
108 m_decryptionSupport(new InjectedBundle::DecryptionSupport())
111 LOG_PROFILE_START("Bundle attachToThread");
112 WrtDB::WrtDatabase::attachToThreadRO();
113 LOG_PROFILE_STOP("Bundle attachToThread");
114 } Catch (DPL::DB::SqlConnection::Exception::Base) {
115 _E("## Db attach was failed! Terminate WebProcess by force. ##");
122 WrtDB::WrtDatabase::detachFromThread();
124 if (!m_pagesList.empty()) {
125 _E("There are not closed pages!");
130 void Bundle::didCreatePageCallback(
131 WKBundleRef /*bundle*/,
132 WKBundlePageRef page,
133 const void* clientInfo)
135 LOG_PROFILE_START("didCreatePageCallback");
136 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
137 This->didCreatePage(page);
138 LOG_PROFILE_STOP("didCreatePageCallback");
141 void Bundle::didReceiveMessageCallback(
142 WKBundleRef /*bundle*/,
143 WKStringRef messageName,
144 WKTypeRef messageBody,
145 const void *clientInfo)
147 Bundle* bundle = static_cast<Bundle*>(const_cast<void*>(clientInfo));
148 bundle->didReceiveMessage(messageName, messageBody);
151 void Bundle::willDestroyPageCallback(
152 WKBundleRef /*bundle*/,
153 WKBundlePageRef page,
154 const void* clientInfo)
156 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
157 This->willDestroyPage(page);
160 void Bundle::didCreatePage(WKBundlePageRef page)
164 _E("## Injected-bundle was not initialized! Terminate WebProcess by force. ##");
168 auto mainFrame = WKBundlePageGetMainFrame(page);
169 auto context = WKBundleFrameGetJavaScriptContext(mainFrame);
170 m_pagesList.push_back(page);
171 m_pageGlobalContext.insertContextForPage(page, context);
172 _D("created Page : %p created JSContext : %p", page, context);
173 m_viewmodesSupport->initialize(page);
175 WKBundlePageResourceLoadClient resourceLoadClient = {
176 kWKBundlePageResourceLoadClientCurrentVersion, /* version */
177 this, /* clientinfo */
178 0, /* didInitiateLoadForResource */
179 willSendRequestForFrameCallback, /* willSendRequestForFrame */
180 0, /* didReceiveResponseForResource */
181 0, /* didReceiveContentLengthForResource */
182 0, /* didFinishLoadForResource */
183 0, /* didFailLoadForResource */
184 0, /* shouldCacheResponse */
185 0, /* shouldUseCredentialStorage */
187 WKBundlePageSetResourceLoadClient(page, &resourceLoadClient);
189 WKBundlePageLoaderClient loaderClient = {
190 kWKBundlePageLoaderClientCurrentVersion,
191 this, /* clientinfo */
192 didStartProvisionalLoadForFrameCallback, /* didStartProvisionalLoadForFrame */
193 0, /* didReceiveServerRedirectForProvisionalLoadForFrame */
194 0, /* didFailProvisionalLoadWithErrorForFrame */
195 didCommitLoadForFrameCallback, /* didCommitLoadForFrame */
196 0, /* didFinishDocumentLoadForFrame */
197 0, /* didFinishLoadForFrame */
198 0, /* didFailLoadWithErrorForFrame */
199 0, /* didSameDocumentNavigationForFrame */
200 0, /* didReceiveTitleForFrame */
201 0, /* didFirstLayoutForFrame */
202 0, /* didFirstVisuallyNonEmptyLayoutForFrame */
203 didRemoveFrameFromHierarchyCallback, /* didRemoveFrameFromHierarchy */
204 0, /* didDisplayInsecureContentForFrame */
205 0, /* didRunInsecureContentForFrame */
206 0, /* didClearWindowObjectForFrame */
207 0, /* didCancelClientRedirectForFrame */
208 0, /* willPerformClientRedirectForFrame */
209 0, /* didHandleOnloadEventsForFrame */
210 0, /* didLayoutForFrame */
211 0, /* didNewFirstVisuallyNonEmptyLayout */
212 0, /* didDetectXSSForFrame */
213 0, /* shouldGoToBackForwardListItem */
214 0, /* globalObjectIsAvailableForFrame */
215 0, /* willDisconnectDOMWindowExtensionFromGlobalObject */
216 0, /* didReconnectDOMWindowExtensionToGlobalObject */
217 0, /* willDestroyGlobalObjectForDOMWindowExtension */
218 0, /* didFinishProgress */
219 0, /* shouldForceUniversalAccessFromLocalURL */
220 0, /* didReceiveIntentForFrame */
221 0, /* registerIntentServiceForFrame */
223 WKBundlePageSetPageLoaderClient(page, &loaderClient);
226 WKBundlePagePolicyClient policyClient = {
227 kWKBundlePagePolicyClientCurrentVersion, /* version */
228 this, /* clientInfo */
229 decidePolicyForNavigationActionCallback, /* decidePolicyForNavigationAction */
230 decidePolicyForNewWindowActionCallback, /* decidePolicyForNavigationAction */
231 decidePolicyForResponseCallback, /* decidePolicyForResponse */
232 0, /* unableToImplementPolicy */
234 WKBundlePageSetPolicyClient(page, &policyClient);
237 void Bundle::willDestroyPage(WKBundlePageRef page)
239 _D("Destroyed page : %p", page);
241 auto context = m_pageGlobalContext.getContextForPage(page);
242 m_pagesList.remove(page);
243 m_pageGlobalContext.removeContextForPage(page);
244 m_pageContext[page].erase(context);
245 m_viewmodesSupport->deinitialize(page);
247 PluginModule::unloadFrame(context);
248 PluginModule::stop(context);
251 void Bundle::fixWKMessageArgs(std::string & argScale,
252 std::string & argEncodedBundle,
253 std::string & argTheme)
255 if (argScale != "null" && argScale[0] == '_') {
256 argScale.erase(0, 1);
258 std::stringstream ssScale(argScale);
262 if (argEncodedBundle != "null" && argEncodedBundle[0] == '_') {
263 argEncodedBundle.erase(0, 1);
265 m_encodedBundle = argEncodedBundle;
268 if (argTheme != "null" && argTheme[0] == '_') {
269 argTheme.erase(0, 1);
275 #ifdef CORS_WHITELISTING_ENABLED
276 void Bundle::bypassCORSforWARPAccessList(WrtDB::WidgetDAOReadOnly & dao)
278 // bypassing CORS using origin whitelist
279 WrtDB::WidgetAccessInfoList WAList;
280 dao.getWidgetAccessInfo(WAList);
283 const WrtDB::WidgetAccessInfo & access = *it;
284 WKURLRef url = WKURLCreateWithUTF8CString(DPL::ToUTF8String(access.strIRI).c_str());
286 #ifdef APP_SCHEME_ENABLED
287 std::string source = std::string("app://") + DPL::ToUTF8String(m_widgetTizenId) + "/";
289 std::string source = DPL::ToUTF8String(dao.getFullPath());
292 _D("WARP to WK whitelist position: %s for %s subDomains: %d",
294 DPL::ToUTF8String(access.strIRI).c_str(),
297 WKStringRef wkSource = WKStringCreateWithUTF8CString(source.c_str());
299 WKStringRef wkProtocol;
300 if(access.strIRI == L"*")
302 //wildcard force to explicitly say which protocol is used
303 // passed wkHost if empty means wildcard -> allow everything but protocol has to be set.
304 for(unsigned i = 0; i < sizeof(warpAllowProtocolsForWildcard) / sizeof(char*); i++)
306 wkHost = WKStringCreateWithUTF8CString("");
307 wkProtocol = WKStringCreateWithUTF8CString(warpAllowProtocolsForWildcard[i]);
308 WKBundleAddOriginAccessWhitelistEntry(m_bundle,
309 wkSource, wkProtocol, wkHost, access.bSubDomains);
314 wkHost = WKURLCopyHostName(url);
315 wkProtocol = WKURLCopyScheme(url);
316 WKBundleAddOriginAccessWhitelistEntry(m_bundle,
317 wkSource, wkProtocol, wkHost, access.bSubDomains);
321 WKRelease(wkProtocol);
327 void Bundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
329 _D("message name: %s", toString(messageName).c_str());
330 if (WKStringIsEqualToUTF8CString(messageName,
331 Message::ToInjectedBundle::START))
333 if (!messageBody || WKStringGetTypeID() != WKGetTypeID(messageBody)) {
334 _E("Wrong message format received, ignoring");
338 std::string msgString =
339 toString(static_cast<WKStringRef>(messageBody));
340 _D("message body: %s", msgString.c_str());
341 // set information from ui process
342 std::stringstream ssMsg(msgString);
343 std::string argScale;
344 std::string argEncodedBundle;
345 std::string argTheme;
349 m_widgetTizenId = DPL::FromASCIIString(id);
352 ssMsg >> argEncodedBundle;
355 // ** Language tags setting completed **
356 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
357 } else if (WKStringIsEqualToUTF8CString(messageName,
358 Message::ToInjectedBundle::SHUTDOWN))
360 if (m_pagesList.empty()) {
361 _D("shutdown plugins");
362 PluginModule::shutdown();
364 _D("PluginModule shutdown ignored, there are still alive pages!");
367 else if (WKStringIsEqualToUTF8CString(messageName,
368 Message::ToInjectedBundle::SET_CUSTOM_PROPERTIES))
370 // set information from ui process
371 std::string msgString =
372 toString(static_cast<WKStringRef>(messageBody));
373 _D("message body: %s", msgString.c_str());
374 std::string argScale;
375 std::string argEncodedBundle;
376 std::string argTheme;
378 std::stringstream ssMsg(msgString);
380 ssMsg >> argEncodedBundle;
383 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
385 //apply for each context
386 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
387 for (; it != m_pageGlobalContext.end(); ++it) {
388 PluginModule::setCustomProperties(it->second,
390 m_encodedBundle.c_str(),
393 } else if (WKStringIsEqualToUTF8CString(
395 Message::ToInjectedBundle::DISPATCH_JS_EVENT))
397 _D("dispatch javascript event to created frames");
398 using namespace WrtPlugins::W3C;
400 // set information from ui process
401 std::string text = toString(static_cast<WKStringRef>(messageBody));
403 SoftKeyboardChangeArgs softKeyboardArgs;
405 std::stringstream ss(text);
408 if (eventType == SoftKeyboardChangeCustomEvent)
410 ss >> softKeyboardArgs.state;
411 ss >> softKeyboardArgs.width;
412 ss >> softKeyboardArgs.height;
415 //apply for each context
416 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
418 for (; it != m_pageGlobalContext.end(); ++it)
420 if (eventType == SoftKeyboardChangeCustomEvent)
422 DispatchEventSupport::dispatchSoftKeyboardChangeEvent(it->second,
423 softKeyboardArgs.state,
424 softKeyboardArgs.width,
425 softKeyboardArgs.height);
428 } else if (WKStringIsEqualToUTF8CString(
430 Message::ToInjectedBundle::INIT))
432 if (!m_initialized) {
434 std::string msgString = toString(static_cast<WKStringRef>(messageBody));
435 m_widgetTizenId = DPL::FromASCIIString(msgString);
436 WrtDB::WidgetDAOReadOnly dao(m_widgetTizenId);
438 // process pool - set app_privilige
439 if (UID_ROOT == getuid()) {
440 using namespace WrtDB::GlobalConfig;
443 std::string tzAppId = DPL::ToUTF8String(dao.getTzAppId());
444 std::string tzPkgId = DPL::ToUTF8String(dao.getTizenPkgId());
445 DPL::OptionalString installedPath = dao.getWidgetInstalledPath();
446 if (installedPath.IsNull()) {
447 appPath = std::string(GetUserInstalledWidgetPath()) + "/" +
448 tzPkgId + GetUserWidgetExecPath() + "/" + tzAppId;
450 appPath = DPL::ToUTF8String(*installedPath) +
451 GetUserWidgetExecPath() + "/" + tzAppId;
454 _D("set_app_smack_label(%s)", appPath.c_str());
455 if (set_app_smack_label(appPath.c_str()) != 0) {
456 _E("set_app_smack_label() failed");
459 _D("perm_app_set_privilege(%s)", appPath.c_str());
460 perm_app_set_privilege(tzPkgId.c_str(), PRIVILEGE_APP_TYPE, appPath.c_str());
463 /* This type of message is received when widget is restarting
464 * (proably in other situation too). Widget restart can be
465 * called after system language change so language tags have to
467 * Do NOT MOVE LanguageTags reset before m_widgetHandle initialization
469 // reset language tags (create new tags based on system locales)
470 LanguageTagsProviderSingleton::Instance().resetLanguageTags();
471 DPL::OptionalString defaultLocale = dao.getDefaultlocale();
472 if (!defaultLocale.IsNull()) {
473 LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
477 LanguageTagsProviderSingleton::Instance().getLanguageTags();
478 _D("Current widget locales (language tags):");
480 _D("Locale: %s", DPL::ToUTF8String(*it).c_str());
483 _D("Preload PluginLogicSingleton");
484 PluginModule::init(WrtDB::WidgetDAOReadOnly::getHandle(m_widgetTizenId));
485 _D("Preload PluginLogicSingleton_end");
487 m_securityModelVersion = dao.getSecurityModelVersion();
488 #ifdef CORS_WHITELISTING_ENABLED
489 bypassCORSforWARPAccessList(dao);
491 m_decryptionSupport->initialize(m_widgetTizenId);
492 m_viewmodesSupport.reset(
493 new InjectedBundle::ViewmodesSupport(m_widgetTizenId));
494 m_initialized = true;
496 _D("already initalized");
498 } else if (WKStringIsEqualToUTF8CString(
500 Message::ToInjectedBundle::SET_XWINDOW_HANDLE))
502 std::string msgString =
503 toString(static_cast<WKStringRef>(messageBody));
504 #if 0 // sub mode disable
505 _D("set x window handle [%s]", msgString.c_str());
506 IPCMessageSupport::setXwindowHandle(atoi(msgString.c_str()));
508 _D("sub mode is disabled, set x window handle [NULL]");
511 } else if (WKStringIsEqualToUTF8CString(
513 Message::ToInjectedBundle::SET_VIEWMODES))
515 std::string msgBody =
516 toString(static_cast<WKStringRef>(messageBody));
517 _D("set viewmode to [%s]", msgBody.c_str());
518 if (msgBody == Message::ToInjectedBundle::SET_VIEWMODES_MSGBODY_EXIT) {
519 m_viewmodesSupport->exitViewmodesAllPages();
521 m_viewmodesSupport->enterViewmodesAllPages(msgBody);
524 else if (WKStringIsEqualToUTF8CString(messageName, IPCMessageSupport::REPLY_ASYNC))
526 using namespace IPCMessageSupport;
528 std::string msgBody = toString(static_cast<WKStringRef>(messageBody));
530 if (msgBody.find_first_of('_') != std::string::npos) {
531 std::string strHandle = msgBody.substr(0, msgBody.find_first_of('_'));
532 std::string strBody = msgBody.substr(msgBody.find_first_of('_')+1);
534 _D("handle: %s, , Body: %s", strHandle.c_str(), strBody.c_str());
536 int handle = atoi(strHandle.c_str());
538 AsyncConnectionPtr connection = AsyncConnectionManager::instance().getConnection(handle);
541 if (connection->replyCallback) {
542 _D("connection->replyCallback()");
543 (connection->replyCallback)(handle, connection->data, strBody.c_str());
546 AsyncConnectionManager::instance().removeConnection(handle);
548 _D("Connection is not available. Ignored.");
554 WKURLRequestRef Bundle::willSendRequestForFrameCallback(
555 WKBundlePageRef /*page*/,
556 WKBundleFrameRef /*frame*/,
557 uint64_t /*resourceIdentifier*/,
558 WKURLRequestRef request,
559 WKURLResponseRef /*response*/,
560 const void *clientInfo)
562 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
563 WKURLRequestRef ret = This->willSendRequestForFrame(request);
568 void Bundle::didStartProvisionalLoadForFrameCallback(
569 WKBundlePageRef page,
570 WKBundleFrameRef frame,
571 WKTypeRef* /*userData*/,
572 const void *clientInfo)
575 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
577 if (This->m_pageGlobalContext.find(page) == This->m_pageGlobalContext.end()) {
580 if (This->m_pageContext.count(page) == 0) {
584 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
586 ContextSet::iterator i = This->m_pageContext[page].find(context);
588 if (i == This->m_pageContext[page].end()) {
589 _D("Initially attached frame");
593 This->m_pageContext[page].erase(i);
594 This->m_willRemoveContext = context;
597 void Bundle::didRemoveFrameFromHierarchyCallback(
598 WKBundlePageRef page,
599 WKBundleFrameRef frame,
600 WKTypeRef* /*userData*/,
601 const void *clientInfo)
604 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
606 if (This->m_pageContext.count(page) == 0) {
607 _D("his->m_pageContext.count(page) == 0");
611 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
613 ContextSet::iterator i = This->m_pageContext[page].find(context);
615 if (i == This->m_pageContext[page].end()) {
616 _W("Tried to unload frame which has never been loaded");
620 This->m_pageContext[page].erase(i);
622 PluginModule::unloadFrame(context);
625 void Bundle::didFinishLoadForResourceCallback(
626 WKBundlePageRef /*page*/,
627 WKBundleFrameRef /*frame*/,
628 uint64_t /*resourceIdentifier*/,
629 const void* /*clientInfo*/)
634 void Bundle::didCommitLoadForFrameCallback(
635 WKBundlePageRef page,
636 WKBundleFrameRef frame,
637 WKTypeRef* /*userData*/,
638 const void *clientInfo)
641 LOG_PROFILE_START("didCommitLoadForFrameCallback");
642 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
644 WKURLRef url = WKBundleFrameCopyURL(frame);
651 if (This->m_willRemoveContext) {
652 PluginModule::unloadFrame(This->m_willRemoveContext);
653 This->m_willRemoveContext = NULL;
656 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
658 This->m_pageContext[page].insert(context);
660 if (!WKBundleFrameIsMainFrame(frame)) {
661 _D("frame isn't main frame");
663 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
666 This->m_encodedBundle.c_str(),
667 This->m_theme.c_str());
668 PluginModule::loadFrame(context);
672 std::string urlStr = toString(url);
674 if (InjectedBundleURIHandling::processURIForPlugin(urlStr.c_str())) {
676 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
678 _D("Previous context: %p", This->m_pageGlobalContext.getContextForPage(page));
679 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
681 _D("New context: %p", context);
682 //note that since we need old context for unloading plugins it must be sotred
683 //custom container take care of increamenting and decrementing references
684 This->m_pageGlobalContext.insertContextForPage(page, context);
685 LOG_PROFILE_START("PluginModule start");
687 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
690 This->m_encodedBundle.c_str(),
691 This->m_theme.c_str() );
692 LOG_PROFILE_STOP("PluginModule start");
694 PluginModule::loadFrame(context);
697 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
699 _D("Previous context: %p", This->m_pageGlobalContext.getContextForPage(page));
700 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
702 _D("New context: %p", context);
703 This->m_pageGlobalContext.insertContextForPage(page, context);
705 LOG_PROFILE_STOP("didCommitLoadForFrameCallback");
708 WKBundlePagePolicyAction Bundle::decidePolicyForNavigationActionCallback(
709 WKBundlePageRef page,
710 WKBundleFrameRef frame,
711 WKBundleNavigationActionRef navigationAction,
712 WKURLRequestRef request,
714 const void* clientInfo)
717 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
718 return This->decidePolicyForAction(false,
726 WKBundlePagePolicyAction Bundle::decidePolicyForNewWindowActionCallback(
727 WKBundlePageRef page,
728 WKBundleFrameRef frame,
729 WKBundleNavigationActionRef navigationAction,
730 WKURLRequestRef request,
731 WKStringRef /*frameName*/,
733 const void* clientInfo)
736 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
737 return This->decidePolicyForAction(true,
745 WKBundlePagePolicyAction Bundle::decidePolicyForResponseCallback(
746 WKBundlePageRef /* page */,
747 WKBundleFrameRef /* frame */,
748 WKURLResponseRef response,
749 WKURLRequestRef /* request */,
750 WKTypeRef* /* userData */,
751 const void* /* clientInfo */)
755 WKStringRef contentTypeRef = WKURLResponseEflCopyContentType(response);
757 std::string contentType = toString(contentTypeRef);
758 _D("contentTypeRef : %s", contentType.c_str());
759 WKRelease(contentTypeRef);
761 if (contentType == HTML_MIME) {
762 _D("Accepting HTML_MIME type");
763 return WKBundlePagePolicyActionUse;
765 if (contentType == PHP_MIME) {
766 _D("Accepting php type");
767 return WKBundlePagePolicyActionUse;
770 return WKBundlePagePolicyActionPassThrough;
773 WKURLRequestRef Bundle::willSendRequestForFrame(WKURLRequestRef request)
775 static bool logEnable = (getenv(WRT_WILL_SEND_REQUEST_LOG_ENABLE) != NULL);
777 WKURLRef wkUrl = WKURLRequestCopyURL(request);
778 WKStringRef wkStr = WKURLCopyString(wkUrl);
780 std::string stdUrl = Bundle::toString(wkStr);
781 std::string localizedUrl;
786 if (logEnable){ _D("willSendRequestForFrame : %s", stdUrl.c_str()); }
788 std::string scheme = stdUrl.substr(0, stdUrl.find_first_of(':'));
790 #ifdef APP_SCHEME_ENABLED
791 if (scheme == SCHEME_FILE) {
792 _E("File schema blocked for: %s", stdUrl.c_str());
797 // "about:blank"/"about:srcdoc" uri doesn't need uri processing.
798 if (stdUrl == BLANK_PAGE_URL || stdUrl == SRC_DOC_PAGE_URL) {
803 localizedUrl = InjectedBundleURIHandling::localizeURI(stdUrl, DPL::ToUTF8String(m_widgetTizenId));
804 bool ret = InjectedBundleURIHandling::processURI(localizedUrl, m_widgetTizenId, m_securityModelVersion);
807 _D("Not permitted resource: %s", localizedUrl.c_str());
811 // log disabled for performance
812 //LogDebug("URI processing result: " << result);
813 scheme = localizedUrl.substr(0, localizedUrl.find_first_of(':'));
815 // Return value must contain details information of input
816 // WKURLRequestRef. Current webkit2 doesn't support api that
817 // copy WKURLRequestRef or change url only. Before webkit2
818 // support api, callback return original WKURLRequestRef in the
819 // case of external scheme
821 // external scheme also need to send message to UI process for
822 // checking roaming and security
824 if (scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS) {
825 if (logEnable){ _D("external scheme return original WKURLRequestRef"); }
830 std::string checkUrl = localizedUrl;
832 if (m_decryptionSupport->isNeedDecryption(checkUrl)) {
833 std::string decryptString =
834 m_decryptionSupport->decryptResource(checkUrl);
836 if (logEnable){ _D("return value : %s", decryptString.c_str()); }
839 WKURLCreateWithUTF8CString(decryptString.c_str());
840 WKURLRequestRef req = WKURLRequestCreateWithWKURL(destUrl);
847 WKURLRef newUrl = WKURLCreateWithUTF8CString(localizedUrl.c_str());
848 WKURLRequestRef req = WKURLRequestCreateWithWKURL(newUrl);
851 if (logEnable){ _D("return value : %s", localizedUrl.c_str()); }
856 WKBundlePagePolicyAction Bundle::decidePolicyForAction(
858 WKBundlePageRef /* page */,
859 WKBundleFrameRef frame,
860 WKBundleNavigationActionRef /* navigationAction */,
861 WKURLRequestRef request,
862 WKTypeRef* /* userData */)
864 using namespace ViewModule;
865 using namespace ViewModule::SchemeActionMap;
867 char const * const TIZEN_SCHEME = "tizen";
869 std::string request_uri = toString(request);
871 _D("request uri : %s", request_uri.c_str());
874 if (request_uri == BLANK_PAGE_URL) {
875 return WKBundlePagePolicyActionUse;
878 // in case of box scheme, unconditionally PassThrough should be returned
879 if (!request_uri.compare(0, 6, SCHEME_BOX_SLASH)) {
880 return WKBundlePagePolicyActionPassThrough;
883 DPL::String dplUrl = DPL::FromUTF8String(request_uri);
885 InjectedBundleURIHandling::processMainResource(dplUrl,
887 m_securityModelVersion);
889 std::string blockedUrl = DPL::ToUTF8String(dplUrl);
890 _D("URI is blocked: %s", blockedUrl.c_str());
892 // Send information about blocked URI to UIProcess
893 WKStringRef urlStr = WKStringCreateWithUTF8CString(blockedUrl.c_str());
894 WKStringRef blockMessage =
895 WKStringCreateWithUTF8CString(Message::ToUIProcess::BLOCKED_URL);
896 WKBundlePostMessage(m_bundle, blockMessage, urlStr);
898 WKRelease(blockMessage);
899 return WKBundlePagePolicyActionPassThrough;
903 std::string request_scheme = getScheme(request_uri);
906 if (request_scheme == TIZEN_SCHEME) {
907 return WKBundlePagePolicyActionPassThrough;
911 Scheme scheme(request_scheme);
912 Scheme::Type type = scheme.GetType();
913 if (type < Scheme::FILE || type >= Scheme::COUNT) {
914 _D("Unknown scheme : %s", request_scheme.c_str());
915 return WKBundlePagePolicyActionPassThrough;
918 bool mainFrame = WKBundleFrameIsMainFrame(frame);
919 NavigationContext ctx = mainFrame ? TOP_LEVEL : FRAME_LEVEL;
924 UriAction action = g_tizenActionMap[type][ctx];
925 _D("Scheme type: %d, Navigation context: %d, Action: %d",
930 if (action != URI_ACTION_WRT) {
931 return WKBundlePagePolicyActionPassThrough;
934 return WKBundlePagePolicyActionUse;
937 std::string Bundle::toString(WKStringRef str)
939 if (WKStringIsEmpty(str)) {
942 size_t size = WKStringGetMaximumUTF8CStringSize(str);
944 char buffer[size + 1];
945 WKStringGetUTF8CString(str, buffer, sizeof(buffer));
951 std::string Bundle::toString(WKURLRef url)
953 WKStringRef urlStr = WKURLCopyString(url);
954 std::string str = toString(urlStr);
959 std::string Bundle::toString(WKURLRequestRef req)
961 WKURLRef reqUrl = WKURLRequestCopyURL(req);
962 std::string str = toString(reqUrl);
967 std::string Bundle::toString(WKErrorRef err)
969 WKStringRef domErr = WKErrorCopyDomain(err);
970 WKStringRef desc = WKErrorCopyLocalizedDescription(err);
971 std::string str = toString(domErr) + "\n" + toString(desc);
977 std::string Bundle::getScheme(std::string uri)
979 std::size_t found = uri.find(':');
982 if (found != std::string::npos) {
983 str = uri.substr(0, found);
992 void WKBundleInitialize(WKBundleRef bundle,
995 _D("Bundle initialized");
997 DPL::Event::GetMainEventDispatcherInstance().ResetCrossEventCallHandler();
998 _D("ResetCrossEventCallHandler()");
1000 static Bundle s_bundle(bundle);
1002 WKBundleClient client = {
1003 kWKBundleClientCurrentVersion,
1005 &Bundle::didCreatePageCallback,
1006 &Bundle::willDestroyPageCallback,
1007 0, /* didInitializePageGroup */
1008 &Bundle::didReceiveMessageCallback
1010 WKBundleSetClient(bundle, &client);
1012 // process pool - restore process priority
1013 if (UID_ROOT == getuid()) {
1014 setpriority(PRIO_PROCESS, 0, DEFAULT_PRIORITY);
1016 IPCMessageSupport::setWKBundleRef(bundle);