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-wk2-bundle.cpp
18 * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
19 * @brief Implementation file for view logic for Webkit2
21 #include "wrt-wk2-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>
41 #include <openssl/sha.h>
42 #include <openssl/hmac.h>
43 #include <openssl/evp.h>
44 #include <openssl/bio.h>
45 #include <openssl/buffer.h>
47 #include <dpl/log/log.h>
48 #include <dpl/foreach.h>
49 #include <dpl/assert.h>
50 #include <dpl/wrt-dao-ro/WrtDatabase.h>
51 #include <dpl/localization/localization_utils.h>
52 #include <dpl/string.h>
53 #include <dpl/wrt-dao-ro/global_config.h>
54 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
55 #include <dpl/wrt-dao-ro/common_dao_types.h>
56 #include <dpl/utils/mime_type_utils.h>
57 #include <dpl/localization/LanguageTagsProvider.h>
58 #include <dpl/event/main_event_dispatcher.h>
59 #include <FBaseByteBuffer.h>
60 #include <security/FSecCrypto_TrustZoneService.h>
62 #include <wrt_plugin_module.h>
63 #include <profiling_util.h>
66 #include <appcore-efl.h>
68 #include "messages_names.h"
71 #include <scheme_action_map_type.h>
72 #include <scheme_action_map_data.h>
74 #include <js_overlay_types.h>
77 #include <sys/resource.h>
78 #include <privilege-control.h>
80 // URI localization on WebProcess side
81 #include "bundle_uri_handling.h"
83 void InitWebAppInfo(const char* appId, const char* rootPath);
87 const char * const uriChangedMessageName = "uri_changed_msg";
88 const char * const uriBlockedMessageName = "uri_blocked_msg";
89 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
90 const char * const webProcessPidMessageName = "web_process_pid_msg";
92 const char * const URICHANGE_PLUGIN_STOP_ONLY = "plugin_stop_only";
93 const char * const URICHANGE_PLUGIN_RESTART = "plugin_restart";
94 const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
95 const char * const URICHANGE_BLOCKED_URL = "null";
96 const char * const SCHEME_HTTP = "http";
97 const char * const SCHEME_HTTPS = "https";
98 const char * const SCHEME_FILE = "file";
99 const char * const SCHEME_FILE_SLASH = "file://";
100 const char * const SCHEME_BOX_SLASH = "box://";
101 const char * const DATA_STRING = "data:";
102 const char * const BASE64_STRING = ";base64,";
103 const char * const BLANK_PAGE_URL = "about:blank";
104 const char * const HTML_MIME = "text/html";
105 const char * const PHP_MIME = "application/x-php";
106 const char * const VIEWMODE_TYPE_FULLSCREEN = "fullscreen";
107 const char * const VIEWMODE_TYPE_MAXIMIZED = "maximized";
108 const std::size_t FILE_BUF_MAX_SIZE = 1024; // bytes
109 const std::size_t PLAIN_CHUNK_SIZE = 1008; // bytes
110 const unsigned int UID_ROOT = 0;
111 const unsigned int DEFAULT_PRIORITY = 0;
112 const char * const PRIVILEGE_APP_TYPE = "wgt";
113 #ifdef CORS_WHITELISTING_ENABLED
114 const char * const warpAllowProtocolsForWildcard[] = { "http", "https" };
117 static bool m_initWebApp = false;
119 Tizen::Base::ByteBuffer *DecryptChunkByTrustZone(
120 Tizen::Base::ByteBuffer *appInfo,
121 const unsigned char *inBuffer,
124 using namespace Tizen::Base;
128 pAppId = (char*)calloc(appInfo->GetRemaining()+1, 1);
129 memcpy(pAppId, appInfo->GetPointer(), appInfo->GetRemaining());
131 InitWebAppInfo(pAppId, "");
136 Tizen::Security::Crypto::_TrustZoneService* pInstance;
137 pInstance = Tizen::Security::Crypto::_TrustZoneService::GetInstance();
140 pBuf.Construct(inBufSize);
141 const byte *pByte = reinterpret_cast<const byte*>(inBuffer);
143 if (pBuf.SetArray(pByte, 0, inBufSize) != E_SUCCESS) {
144 LogDebug("Couldnot set pBuf");
150 return pInstance->_TrustZoneService::DecryptN(*appInfo, pBuf);
155 Bundle::Bundle(WKBundleRef bundle) :
160 m_willRemoveContext(NULL),
162 m_widgetType(WrtDB::APP_TYPE_UNKNOWN),
163 m_securityModelVersion(
164 WrtDB::WidgetSecurityModelVersion::WIDGET_SECURITY_MODEL_V1),
167 LOG_PROFILE_START("Bundle attachToThread");
168 WrtDB::WrtDatabase::attachToThreadRO();
169 m_uriChangedMessage = WKStringCreateWithUTF8CString(uriChangedMessageName);
170 LOG_PROFILE_STOP("Bundle attachToThread");
171 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
178 WrtDB::WrtDatabase::detachFromThread();
180 if (!m_pagesList.empty()) {
181 LogError("There are not closed pages!");
184 WKRelease(m_uriChangedMessage);
188 void Bundle::didCreatePageCallback(
189 WKBundleRef /*bundle*/,
190 WKBundlePageRef page,
191 const void* clientInfo)
193 LOG_PROFILE_START("didCreatePageCallback");
194 LogDebug("didCreatePageCallback called");
195 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
196 This->didCreatePage(page);
197 LOG_PROFILE_STOP("didCreatePageCallback");
200 void Bundle::didReceiveMessageCallback(
201 WKBundleRef /*bundle*/,
202 WKStringRef messageName,
203 WKTypeRef messageBody,
204 const void *clientInfo)
206 LogDebug("didReceiveMessageCallback called");
207 Bundle* bundle = static_cast<Bundle*>(const_cast<void*>(clientInfo));
208 bundle->didReceiveMessage(messageName, messageBody);
211 void Bundle::willDestroyPageCallback(
212 WKBundleRef /*bundle*/,
213 WKBundlePageRef page,
214 const void* clientInfo)
216 LogDebug("willDestroyPageCallback called");
217 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
218 This->willDestroyPage(page);
221 void Bundle::didCreatePage(WKBundlePageRef page)
223 auto mainFrame = WKBundlePageGetMainFrame(page);
224 auto context = WKBundleFrameGetJavaScriptContext(mainFrame);
225 m_pagesList.push_back(page);
226 m_pageGlobalContext.insertContextForPage(page, context);
227 LogDebug("created Page : " << page << " created JSContext : " << context);
229 WKBundlePageResourceLoadClient resourceLoadClient = {
230 kWKBundlePageResourceLoadClientCurrentVersion, /* version */
231 this, /* clientinfo */
232 0, /* didInitiateLoadForResource */
233 willSendRequestForFrameCallback, /* willSendRequestForFrame */
234 0, /* didReceiveResponseForResource */
235 0, /* didReceiveContentLengthForResource */
236 didFinishLoadForResourceCallback, /* didFinishLoadForResource */
237 0, /* didFailLoadForResource */
238 0, /* shouldCacheResponse */
239 0, /* shouldUseCredentialStorage */
241 WKBundlePageSetResourceLoadClient(page, &resourceLoadClient);
243 WKBundlePageLoaderClient loaderClient = {
244 kWKBundlePageLoaderClientCurrentVersion,
245 this, /* clientinfo */
246 didStartProvisionalLoadForFrameCallback, /* didStartProvisionalLoadForFrame */
247 0, /* didReceiveServerRedirectForProvisionalLoadForFrame */
248 0, /* didFailProvisionalLoadWithErrorForFrame */
249 didCommitLoadForFrameCallback, /* didCommitLoadForFrame */
250 0, /* didFinishDocumentLoadForFrame */
251 0, /* didFinishLoadForFrame */
252 0, /* didFailLoadWithErrorForFrame */
253 0, /* didSameDocumentNavigationForFrame */
254 0, /* didReceiveTitleForFrame */
255 0, /* didFirstLayoutForFrame */
256 0, /* didFirstVisuallyNonEmptyLayoutForFrame */
257 didRemoveFrameFromHierarchyCallback, /* didRemoveFrameFromHierarchy */
258 0, /* didDisplayInsecureContentForFrame */
259 0, /* didRunInsecureContentForFrame */
260 0, /* didClearWindowObjectForFrame */
261 0, /* didCancelClientRedirectForFrame */
262 0, /* willPerformClientRedirectForFrame */
263 0, /* didHandleOnloadEventsForFrame */
264 0, /* didLayoutForFrame */
265 0, /* didNewFirstVisuallyNonEmptyLayout */
266 0, /* didDetectXSSForFrame */
267 0, /* shouldGoToBackForwardListItem */
268 0, /* globalObjectIsAvailableForFrame */
269 0, /* willDisconnectDOMWindowExtensionFromGlobalObject */
270 0, /* didReconnectDOMWindowExtensionToGlobalObject */
271 0, /* willDestroyGlobalObjectForDOMWindowExtension */
272 0, /* didFinishProgress */
273 0, /* shouldForceUniversalAccessFromLocalURL */
274 0, /* didReceiveIntentForFrame */
275 0, /* registerIntentServiceForFrame */
277 WKBundlePageSetPageLoaderClient(page, &loaderClient);
280 WKBundlePagePolicyClient policyClient = {
281 kWKBundlePagePolicyClientCurrentVersion, /* version */
282 this, /* clientInfo */
283 decidePolicyForNavigationActionCallback, /* decidePolicyForNavigationAction */
284 decidePolicyForNewWindowActionCallback, /* decidePolicyForNavigationAction */
285 decidePolicyForResponseCallback, /* decidePolicyForResponse */
286 0, /* unableToImplementPolicy */
288 WKBundlePageSetPolicyClient(page, &policyClient);
291 void Bundle::willDestroyPage(WKBundlePageRef page)
293 LogDebug("Destroyed page : " << page);
295 auto context = m_pageGlobalContext.getContextForPage(page);
296 m_pagesList.remove(page);
297 m_pageGlobalContext.removeContextForPage(page);
298 m_pageContext[page].erase(context);
300 PluginModule::unloadFrame(context);
301 PluginModule::stop(context);
304 void Bundle::fixWKMessageArgs(std::string & argScale,
305 std::string & argEncodedBundle,
306 std::string & argTheme)
308 if (argScale != "null" && argScale[0] == '_') {
309 argScale.erase(0, 1);
311 std::stringstream ssScale(argScale);
315 if (argEncodedBundle != "null" && argEncodedBundle[0] == '_') {
316 argEncodedBundle.erase(0, 1);
318 m_encodedBundle = argEncodedBundle;
321 if (argTheme != "null" && argTheme[0] == '_') {
322 argTheme.erase(0, 1);
328 #ifdef CORS_WHITELISTING_ENABLED
329 void Bundle::bypassCORSforWARPAccessList(WrtDB::WidgetDAOReadOnly & dao)
331 // bypassing CORS using origin whitelist
332 WrtDB::WidgetAccessInfoList WAList;
333 dao.getWidgetAccessInfo(WAList);
336 const WrtDB::WidgetAccessInfo & access = *it;
337 WKURLRef url = WKURLCreateWithUTF8CString(DPL::ToUTF8String(access.strIRI).c_str());
339 #ifdef APP_SCHEME_ENABLED
340 std::string source = std::string("app://") + DPL::ToUTF8String(m_widgetTizenId) + "/";
342 std::string source = DPL::ToUTF8String(dao.getFullPath());
345 LogDebug("WARP to WK whitelist position: " << source << " for "
346 << access.strIRI << " subDomains: " << access.bSubDomains);
348 WKStringRef wkSource = WKStringCreateWithUTF8CString(source.c_str());
350 WKStringRef wkProtocol;
351 if(access.strIRI == L"*")
353 //wildcard force to explicitly say which protocol is used
354 // passed wkHost if empty means wildcard -> allow everything but protocol has to be set.
355 for(unsigned i = 0; i < sizeof(warpAllowProtocolsForWildcard) / sizeof(char*); i++)
357 wkHost = WKStringCreateWithUTF8CString("");
358 wkProtocol = WKStringCreateWithUTF8CString(warpAllowProtocolsForWildcard[i]);
359 WKBundleAddOriginAccessWhitelistEntry(m_bundle,
360 wkSource, wkProtocol, wkHost, access.bSubDomains);
365 wkHost = WKURLCopyHostName(url);
366 wkProtocol = WKURLCopyScheme(url);
367 WKBundleAddOriginAccessWhitelistEntry(m_bundle,
368 wkSource, wkProtocol, wkHost, access.bSubDomains);
372 WKRelease(wkProtocol);
378 void Bundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
380 LogDebug("got message type: " << toString(messageName).c_str());
381 if (WKStringIsEqualToUTF8CString(messageName,
382 BundleMessages::START))
384 if (!messageBody || WKStringGetTypeID() != WKGetTypeID(messageBody)) {
385 LogError("Wrong message format received, ignoring");
389 auto msgString = toString(static_cast<WKStringRef>(messageBody));
390 LogDebug("Got message text: " << msgString);
391 LogDebug("loading Page : " << m_pagesList.back() <<
392 " loading JSContext : " <<
393 m_pageGlobalContext.getContextForPage(m_pagesList.back()));
394 // set information from ui process
395 std::stringstream ssMsg(msgString);
396 std::string argScale;
397 std::string argEncodedBundle;
398 std::string argTheme;
402 m_widgetTizenId = DPL::FromASCIIString(id);
405 ssMsg >> argEncodedBundle;
407 ssMsg >> m_encrypted;
408 LogWarning("m_encrypted : " << m_encrypted);
410 // ** Language tags setting completed **
411 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
412 } else if (WKStringIsEqualToUTF8CString(messageName,
413 BundleMessages::SHUTDOWN))
415 LogDebug("shutdown plugins");
417 if (m_pagesList.empty()) {
418 PluginModule::shutdown();
421 "PluginModule shutdown ignored, there are still alive pages!");
424 else if (WKStringIsEqualToUTF8CString(messageName,
425 BundleMessages::SET_CUSTOM_PROPERTIES))
427 LogDebug("reset custom properties of window objects");
428 // set information from ui process
429 auto msgString = toString(static_cast<WKStringRef>(messageBody));
431 std::string argScale;
432 std::string argEncodedBundle;
433 std::string argTheme;
435 std::stringstream ssMsg(msgString);
437 ssMsg >> argEncodedBundle;
440 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
442 //apply for each context
443 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
444 for (; it != m_pageGlobalContext.end(); ++it) {
445 PluginModule::setCustomProperties(it->second,
447 m_encodedBundle.c_str(),
450 } else if (WKStringIsEqualToUTF8CString(
452 BundleMessages::DISPATCH_JAVASCRIPT_EVENT))
454 LogDebug("dispatch javascript event to created frames");
455 // set information from ui process
456 auto text = toString(static_cast<WKStringRef>(messageBody));
459 std::stringstream ss(text);
462 using namespace WrtPlugins::W3C;
463 // set arguments to be sent to js handler of this custom event
464 if (eventType == SoftKeyboardChangeCustomEvent) {
465 args = new SoftKeyboardChangeArgs;
466 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->state;
467 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->width;
468 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->height;
471 //apply for each context
472 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
473 for (; it != m_pageGlobalContext.end(); ++it) {
474 PluginModule::dispatchJavaScriptEvent(
476 static_cast<WrtPlugins::W3C::CustomEventType>(eventType),
481 delete static_cast<SoftKeyboardChangeArgs *>(args);
483 } else if (WKStringIsEqualToUTF8CString(
485 BundleMessages::INIT))
487 LogDebug("initializing plugins");
491 auto msgString = toString(static_cast<WKStringRef>(messageBody));
493 m_widgetTizenId = DPL::FromASCIIString(msgString);
495 WrtDB::WidgetDAOReadOnly dao(m_widgetTizenId);
497 // process pool - set app_privilige
498 if (UID_ROOT == getuid())
500 using namespace WrtDB::GlobalConfig;
503 std::string tzAppId = DPL::ToUTF8String(dao.getTzAppId());
504 std::string tzPkgId = DPL::ToUTF8String(dao.getTizenPkgId());
505 DPL::OptionalString installedPath = dao.getWidgetInstalledPath();
506 if (installedPath.IsNull()) {
507 appPath = std::string(GetUserInstalledWidgetPath()) + "/" +
508 tzPkgId + GetUserWidgetExecPath() + "/" + tzAppId;
510 appPath = DPL::ToUTF8String(*installedPath) +
511 GetUserWidgetExecPath() + "/" + tzAppId;
514 LogDebug("set_app_privilege(" << appPath << ")");
515 set_app_privilege(tzPkgId.c_str(), PRIVILEGE_APP_TYPE, appPath.c_str());
518 /* This type of message is received when widget is restarting
519 * (proably in other situation too). Widget restart can be
520 * called after system language change so language tags have to
522 * Do NOT MOVE LanguageTags reset before m_widgetHandle initialization
524 // reset language tags (create new tags based on system locales)
525 LanguageTagsProviderSingleton::Instance().resetLanguageTags();
526 DPL::OptionalString defaultLocale = dao.getDefaultlocale();
527 if (!defaultLocale.IsNull()) {
528 LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
532 LanguageTagsProviderSingleton::Instance().getLanguageTags();
533 LogDebug("Current widget locales (language tags):");
535 LogDebug("Locale: " << *it);
538 m_widgetType = dao.getWidgetType();
539 LogDebug("m_widgetType : " << m_widgetType.getApptypeToString() <<
540 "(m_widgetTizenId:" << m_widgetTizenId << ")");
542 LogDebug("Preload PluginLogicSingleton");
543 PluginModule::init(WrtDB::WidgetDAOReadOnly::getHandle(m_widgetTizenId));
544 LogDebug("Preload PluginLogicSingleton_end");
546 m_securityModelVersion = dao.getSecurityModelVersion();
547 #ifdef CORS_WHITELISTING_ENABLED
548 bypassCORSforWARPAccessList(dao);
550 m_initialized = true;
554 LogDebug("already initalized");
559 WKURLRequestRef Bundle::willSendRequestForFrameCallback(
560 WKBundlePageRef /*page*/,
561 WKBundleFrameRef /*frame*/,
562 uint64_t /*resourceIdentifier*/,
563 WKURLRequestRef request,
564 WKURLResponseRef /*response*/,
565 const void *clientInfo)
567 LogDebug("willSendRequestForFrameCallback called");
568 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
569 return This->willSendRequestForFrame(request);
572 void Bundle::didStartProvisionalLoadForFrameCallback(
573 WKBundlePageRef page,
574 WKBundleFrameRef frame,
575 WKTypeRef* /*userData*/,
576 const void *clientInfo)
578 LogDebug("didStartProvisionalLoadForFrameCallback called");
579 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
582 WrtDB::WidgetDAOReadOnly dao(This->m_widgetTizenId);
583 WrtDB::WindowModeList modeList = dao.getWindowModes();
584 FOREACH(it, modeList) {
585 std::string viewMode = DPL::ToUTF8String(*it);
586 if (viewMode == VIEWMODE_TYPE_FULLSCREEN
587 || viewMode == VIEWMODE_TYPE_MAXIMIZED)
589 WKBundlePageSetViewMode(
591 WKStringCreateWithUTF8CString(viewMode.c_str()));
596 if (This->m_pageGlobalContext.find(page) == This->m_pageGlobalContext.end()) {
599 if (This->m_pageContext.count(page) == 0) {
603 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
605 ContextSet::iterator i = This->m_pageContext[page].find(context);
607 if (i == This->m_pageContext[page].end()) {
608 LogDebug("Initially attached frame");
612 This->m_pageContext[page].erase(i);
613 This->m_willRemoveContext = context;
616 void Bundle::didRemoveFrameFromHierarchyCallback(
617 WKBundlePageRef page,
618 WKBundleFrameRef frame,
619 WKTypeRef* /*userData*/,
620 const void *clientInfo)
622 LogDebug("didRemoveFrameFromHierarchyCallback called");
623 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
625 if (This->m_pageContext.count(page) == 0) {
626 LogDebug("his->m_pageContext.count(page) == 0");
630 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
632 ContextSet::iterator i = This->m_pageContext[page].find(context);
634 if (i == This->m_pageContext[page].end()) {
635 LogWarning("Tried to unload frame which has never been loaded");
639 This->m_pageContext[page].erase(i);
641 PluginModule::unloadFrame(context);
644 void Bundle::didFinishLoadForResourceCallback(
645 WKBundlePageRef /*page*/,
646 WKBundleFrameRef /*frame*/,
647 uint64_t /*resourceIdentifier*/,
648 const void* /*clientInfo*/)
650 LogDebug("didFinishLoadForResourceCallback called");
653 void Bundle::didCommitLoadForFrameCallback(
654 WKBundlePageRef page,
655 WKBundleFrameRef frame,
656 WKTypeRef* /*userData*/,
657 const void *clientInfo)
659 LogInfo("didCommitLoadForFrameCallback called");
660 LOG_PROFILE_START("didCommitLoadForFrameCallback");
661 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
663 WKURLRef url = WKBundleFrameCopyURL(frame);
664 WKTypeRef retVal = NULL;
667 LogInfo("url is NULL");
671 if (This->m_willRemoveContext) {
672 PluginModule::unloadFrame(This->m_willRemoveContext);
673 This->m_willRemoveContext = NULL;
676 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
678 This->m_pageContext[page].insert(context);
680 if (!WKBundleFrameIsMainFrame(frame)) {
681 LogInfo("frame isn't main frame");
683 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
686 This->m_encodedBundle.c_str(),
687 This->m_theme.c_str());
688 PluginModule::loadFrame(context);
692 std::string scheme = getScheme(toString(url));
693 std::string result = URICHANGE_PLUGIN_RESTART;
695 if (scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS) {
696 WKStringRef urlStr = WKURLCopyString(url);
697 WKBundlePostSynchronousMessage(This->m_bundle,
698 This->m_uriChangedMessage,
704 result = toString(static_cast<WKStringRef>(retVal));
706 LogInfo("result from UI process : " << result);
708 if (result == URICHANGE_PLUGIN_STOP_ONLY) {
709 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
711 LogDebug("Previous context: " << This->m_pageGlobalContext.getContextForPage(page));
712 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
714 LogDebug("New context: " << context);
715 This->m_pageGlobalContext.insertContextForPage(page, context);
716 } else if (result == URICHANGE_PLUGIN_RESTART) {
717 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
719 LogDebug("Previous context: " << This->m_pageGlobalContext.getContextForPage(page));
720 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
722 LogDebug("New context: " << context);
723 //note that since we need old context for unloading plugins it must be sotred
724 //custom container take care of increamenting and decrementing references
725 This->m_pageGlobalContext.insertContextForPage(page, context);
726 LOG_PROFILE_START("PluginModule start");
728 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
731 This->m_encodedBundle.c_str(),
732 This->m_theme.c_str() );
733 LOG_PROFILE_STOP("PluginModule start");
735 PluginModule::loadFrame(context);
737 LOG_PROFILE_STOP("didCommitLoadForFrameCallback");
740 WKBundlePagePolicyAction Bundle::decidePolicyForNavigationActionCallback(
741 WKBundlePageRef page,
742 WKBundleFrameRef frame,
743 WKBundleNavigationActionRef navigationAction,
744 WKURLRequestRef request,
746 const void* clientInfo)
748 LogDebug("decidePolicyForNavigationActionCallback called");
750 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
751 return This->decidePolicyForAction(false,
759 WKBundlePagePolicyAction Bundle::decidePolicyForNewWindowActionCallback(
760 WKBundlePageRef page,
761 WKBundleFrameRef frame,
762 WKBundleNavigationActionRef navigationAction,
763 WKURLRequestRef request,
764 WKStringRef /*frameName*/,
766 const void* clientInfo)
768 LogDebug("decidePolicyForNewWindowActionCallback called");
770 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
771 return This->decidePolicyForAction(true,
779 WKBundlePagePolicyAction Bundle::decidePolicyForResponseCallback(
780 WKBundlePageRef /* page */,
781 WKBundleFrameRef /* frame */,
782 WKURLResponseRef response,
783 WKURLRequestRef /* request */,
784 WKTypeRef* /* userData */,
785 const void* /* clientInfo */)
787 LogDebug("decidePolicyForResponseCallback called");
790 WKStringRef contentTypeRef = WKURLResponseEflCopyContentType(response);
792 std::string contentType = toString(contentTypeRef);
793 LogDebug("contentTypeRef : " << contentType);
794 WKRelease(contentTypeRef);
796 if (contentType == HTML_MIME) {
797 LogDebug("Accepting HTML_MIME type");
798 return WKBundlePagePolicyActionUse;
800 if (contentType == PHP_MIME) {
801 LogDebug("Accepting php type");
802 return WKBundlePagePolicyActionUse;
805 return WKBundlePagePolicyActionPassThrough;
808 WKURLRequestRef Bundle::willSendRequestForFrame(WKURLRequestRef request)
810 LogDebug("willSendReq got " << toString(request).c_str());
811 WKURLRef url = WKURLRequestCopyURL(request);
812 WKStringRef urlStr = WKURLCopyString(url);
814 DPL::String dplurl = DPL::FromUTF8String(toString(urlStr));
817 DPL::Optional<DPL::String> localizedUrl =
818 BundleURIHandling::localizeURI(dplurl, m_widgetTizenId);
820 BundleURIHandling::processURI(*localizedUrl,
822 m_securityModelVersion);
825 LogDebug("Not permitted resource: " << *localizedUrl);
829 LogDebug("URI processing result: " << *localizedUrl);
830 std::string tmpUrlStr = DPL::ToUTF8String(*localizedUrl);
831 WKURLRef tmpUrl = WKURLCreateWithUTF8CString(tmpUrlStr.c_str());
832 std::string scheme = toString(WKURLCopyScheme(url)); //scheme of original request
835 #ifdef APP_SCHEME_ENABLED
836 if(scheme == SCHEME_FILE) {
837 LogError("File schema blocked for: " << dplurl);
842 // Return value must contain details information of input
843 // WKURLRequestRef. Current webkit2 doesn't support api that
844 // copy WKURLRequestRef or change url only. Before webkit2
845 // support api, callback return original WKURLRequestRef in the
846 // case of external scheme
848 // external scheme also need to send message to UI process for
849 // checking roaming and security
850 if (scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS) {
851 LogDebug("external scheme return original WKURLRequestRef");
856 std::string checkUrl = toString(tmpUrl);
860 if (isEncryptedResource(checkUrl, getFileSize)) {
861 std::string decryptString = DecryptResource(checkUrl,
863 if (!decryptString.empty()) {
864 std::string destString = DATA_STRING;
866 std::string mimeString =
868 MimeTypeUtils::identifyFileMimeType(
869 DPL::FromUTF8String(checkUrl)));
871 destString += mimeString;
872 destString += BASE64_STRING;
874 decryptString.insert(0, destString);
877 WKURLCreateWithUTF8CString(decryptString.c_str());
879 WKURLRequestRef req = WKURLRequestCreateWithWKURL(
882 LogDebug("return value " << decryptString << "]]");
887 WKURLRequestRef req = WKURLRequestCreateWithWKURL(tmpUrl);
889 LogDebug("return value " << toString(req).c_str());
894 WKBundlePagePolicyAction Bundle::decidePolicyForAction(
896 WKBundlePageRef /* page */,
897 WKBundleFrameRef frame,
898 WKBundleNavigationActionRef /* navigationAction */,
899 WKURLRequestRef request,
900 WKTypeRef* /* userData */)
902 using namespace ViewModule;
903 using namespace ViewModule::SchemeActionMap;
905 char const * const TIZEN_SCHEME = "tizen";
907 std::string request_uri = toString(request);
909 LogInfo("Uri being checked: " << request_uri);
912 if (request_uri == BLANK_PAGE_URL) {
913 return WKBundlePagePolicyActionUse;
916 // in case of box scheme, unconditionally PassThrough should be returned
917 if (!request_uri.compare(0, 6, SCHEME_BOX_SLASH)) {
918 return WKBundlePagePolicyActionPassThrough;
921 DPL::String dplUrl = DPL::FromUTF8String(request_uri);
923 BundleURIHandling::processMainResource(dplUrl,
925 m_securityModelVersion);
927 std::string blockedUrl = DPL::ToUTF8String(dplUrl);
928 LogDebug("URI is blocked: " << blockedUrl);
930 // Send information about blocked URI to UIProcess
931 WKStringRef urlStr = WKStringCreateWithUTF8CString(blockedUrl.c_str());
932 WKTypeRef retVal = NULL;
933 WKStringRef blockMessage = WKStringCreateWithUTF8CString(uriBlockedMessageName);
934 WKBundlePostSynchronousMessage(m_bundle, blockMessage, urlStr, &retVal);
937 WKRelease(blockMessage);
938 return WKBundlePagePolicyActionPassThrough;
942 std::string request_scheme = getScheme(request_uri);
945 if (request_scheme == TIZEN_SCHEME) {
946 return WKBundlePagePolicyActionPassThrough;
950 Scheme scheme(request_scheme);
951 LogDebug("Scheme: " << request_scheme);
953 Scheme::Type type = scheme.GetType();
954 if (type < Scheme::FILE || type >= Scheme::COUNT) {
955 LogError("Invalid scheme: " << request_scheme);
956 return WKBundlePagePolicyActionPassThrough;
959 bool mainFrame = WKBundleFrameIsMainFrame(frame);
960 NavigationContext ctx = mainFrame ? TOP_LEVEL : FRAME_LEVEL;
965 LogDebug("Scheme type: " << type);
966 LogDebug("Navigation context: " << ctx);
967 LogDebug("Application type: " << m_widgetType.getApptypeToString());
971 if (m_widgetType == WrtDB::APP_TYPE_TIZENWEBAPP) {
972 action = g_tizenActionMap[type][ctx];
974 LogError("Unsupported application type: " << type);
975 return WKBundlePagePolicyActionPassThrough;
978 LogDebug("Uri action: " << action);
980 if (action != URI_ACTION_WRT) {
981 return WKBundlePagePolicyActionPassThrough;
984 return WKBundlePagePolicyActionUse;
987 std::string Bundle::toString(WKStringRef str)
989 if (WKStringIsEmpty(str)) {
990 return std::string();
992 size_t size = WKStringGetMaximumUTF8CStringSize(str);
993 char buffer[size + 1];
994 WKStringGetUTF8CString(str, buffer, size + 1);
998 std::string Bundle::toString(WKURLRef url)
1000 WKStringRef urlStr = WKURLCopyString(url);
1001 std::string str = toString(urlStr);
1006 std::string Bundle::toString(WKURLRequestRef req)
1008 WKURLRef reqUrl = WKURLRequestCopyURL(req);
1009 std::string str = toString(reqUrl);
1014 std::string Bundle::toString(WKErrorRef err)
1016 WKStringRef domErr = WKErrorCopyDomain(err);
1017 WKStringRef desc = WKErrorCopyLocalizedDescription(err);
1018 std::string str = toString(domErr) + "\n" + toString(desc);
1024 std::string Bundle::getScheme(std::string uri)
1026 std::size_t found = uri.find(':');
1029 if (found != std::string::npos) {
1030 str = uri.substr(0, found);
1036 bool Bundle::isEncryptedResource(std::string Url, int &size)
1038 if (m_encryptedFiles.empty()) {
1039 WrtDB::WidgetDAOReadOnly(m_widgetTizenId).
1040 getEncryptedFileList(m_encryptedFiles);
1043 std::set<WrtDB::EncryptedFileInfo>::iterator it;
1044 WrtDB::EncryptedFileInfo info;
1045 std::string filePath;
1047 if (0 != strncmp(Url.c_str(), SCHEME_FILE_SLASH, strlen(SCHEME_FILE_SLASH))) {
1051 filePath = Url.substr(strlen(SCHEME_FILE_SLASH));
1052 info.fileName = DPL::FromUTF8String(filePath);
1054 if (m_encryptedFiles.end() != (it = m_encryptedFiles.find(info)))
1056 LogDebug(" info file name : " << it->fileName);
1057 LogDebug(" info file size : " << it->fileSize);
1058 size = it->fileSize;
1064 std::string Bundle::DecryptResource(std::string resource, int size)
1066 std::string filePath;
1068 size_t pos = resource.find_first_not_of(SCHEME_FILE_SLASH);
1069 if (std::string::npos != pos) {
1070 filePath = resource.substr(pos - 1);
1074 if (0 == stat(filePath.c_str(), &buf)) {
1075 const std::size_t fileSize = buf.st_size;
1076 std::unique_ptr<unsigned char[]> inChunk;
1078 FILE* fp = fopen(filePath.c_str(), "rb");
1080 LogDebug("Couldnot open file : " << filePath);
1081 return std::string();
1084 std::unique_ptr<unsigned char[]> DecryptedString(new unsigned
1086 std::string pkgid(DPL::ToUTF8String(m_widgetTizenId));
1088 using namespace Tizen::Base;
1089 const byte *b_pkgid = reinterpret_cast<const byte*>(pkgid.c_str());
1091 appInfo.Construct(pkgid.length());
1092 if (appInfo.SetArray(b_pkgid, 0, pkgid.length()) != E_SUCCESS) {
1093 LogDebug("Couldnot set appInfo");
1095 return std::string();
1101 unsigned char getDecSize[4];
1102 memset(getDecSize, 0x00, sizeof(getDecSize));
1104 size_t readSize = fread(getDecSize, sizeof(unsigned char),
1105 sizeof(getDecSize), fp);
1106 if (0 != readSize) {
1107 int readBufSize = 0;
1108 std::istringstream(std::string((char*)getDecSize)) >> readBufSize;
1109 inChunk.reset(new unsigned char[readBufSize]);
1111 size_t decReadSize = fread(inChunk.get(), sizeof(unsigned char),
1113 if (0 != decReadSize) {
1114 ByteBuffer *getBuffer =
1115 DecryptChunkByTrustZone(&appInfo, inChunk.get(),
1117 memcpy(DecryptedString.get() + writeCount,
1118 getBuffer->GetPointer(), getBuffer->GetRemaining());
1119 writeCount += getBuffer->GetRemaining();
1124 } while( 0 == std::feof(fp));
1127 memset(DecryptedString.get() + size, '\n', fileSize - size);
1128 LogDebug("resource need to encoding base64");
1132 b64 = BIO_new(BIO_f_base64());
1133 bmem = BIO_new(BIO_s_mem());
1134 b64 = BIO_push(b64, bmem);
1135 BIO_write(b64, DecryptedString.get(), fileSize);
1137 BIO_get_mem_ptr(b64, &bptr);
1139 std::string base64Enc((char *)bptr->data, bptr->length - 1);
1144 return std::string();
1147 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
1148 void Bundle::sendWebProcessPid()
1150 std::stringstream strPid;
1152 WKStringRef pidStr = WKStringCreateWithUTF8CString(strPid.str().c_str());
1153 WKTypeRef retVal = NULL;
1154 WKStringRef message = WKStringCreateWithUTF8CString(webProcessPidMessageName);
1155 WKBundlePostSynchronousMessage(m_bundle, message, pidStr, &retVal);
1165 void WKBundleInitialize(WKBundleRef bundle,
1168 DPL::Log::LogSystemSingleton::Instance().SetTag("WRT-BUNDLE");
1169 LogDebug("Bundle initialized");
1171 DPL::Event::GetMainEventDispatcherInstance().ResetCrossEventCallHandler();
1172 LogDebug("ResetCrossEventCallHandler()");
1174 static Bundle s_bundle(bundle);
1176 WKBundleClient client = {
1177 kWKBundleClientCurrentVersion,
1179 &Bundle::didCreatePageCallback,
1180 &Bundle::willDestroyPageCallback,
1181 0, /* didInitializePageGroup */
1182 &Bundle::didReceiveMessageCallback
1184 WKBundleSetClient(bundle, &client);
1186 // process pool - restore process priority
1187 if (UID_ROOT == getuid())
1189 setpriority(PRIO_PROCESS, 0, DEFAULT_PRIORITY);