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>
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 "injected_bundle_uri_handling.h"
83 void InitWebAppInfo(const char* appId, const char* rootPath);
87 const char * const uriBlockedMessageName = "uri_blocked_msg";
88 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
89 const char * const webProcessPidMessageName = "web_process_pid_msg";
91 const char * const SCHEME_HTTP = "http";
92 const char * const SCHEME_HTTPS = "https";
93 const char * const SCHEME_FILE = "file";
94 const char * const SCHEME_FILE_SLASH = "file://";
95 const char * const SCHEME_BOX_SLASH = "box://";
96 const char * const DATA_STRING = "data:";
97 const char * const BASE64_STRING = ";base64,";
98 const char * const BLANK_PAGE_URL = "about:blank";
99 const char * const HTML_MIME = "text/html";
100 const char * const PHP_MIME = "application/x-php";
101 const char * const VIEWMODE_TYPE_FULLSCREEN = "fullscreen";
102 const char * const VIEWMODE_TYPE_MAXIMIZED = "maximized";
103 const std::size_t FILE_BUF_MAX_SIZE = 1024; // bytes
104 const std::size_t PLAIN_CHUNK_SIZE = 1008; // bytes
105 const unsigned int UID_ROOT = 0;
106 const unsigned int DEFAULT_PRIORITY = 0;
107 const char * const PRIVILEGE_APP_TYPE = "wgt";
108 #ifdef CORS_WHITELISTING_ENABLED
109 const char * const warpAllowProtocolsForWildcard[] = { "http", "https" };
112 static bool m_initWebApp = false;
114 Tizen::Base::ByteBuffer *DecryptChunkByTrustZone(
115 Tizen::Base::ByteBuffer *appInfo,
116 const unsigned char *inBuffer,
119 using namespace Tizen::Base;
123 pAppId = (char*)calloc(appInfo->GetRemaining()+1, 1);
124 memcpy(pAppId, appInfo->GetPointer(), appInfo->GetRemaining());
126 InitWebAppInfo(pAppId, "");
131 Tizen::Security::Crypto::_TrustZoneService* pInstance;
132 pInstance = Tizen::Security::Crypto::_TrustZoneService::GetInstance();
135 pBuf.Construct(inBufSize);
136 const byte *pByte = reinterpret_cast<const byte*>(inBuffer);
138 if (pBuf.SetArray(pByte, 0, inBufSize) != E_SUCCESS) {
139 LogDebug("Couldnot set pBuf");
145 return pInstance->_TrustZoneService::DecryptN(*appInfo, pBuf);
150 Bundle::Bundle(WKBundleRef bundle) :
155 m_willRemoveContext(NULL),
157 m_widgetType(WrtDB::APP_TYPE_UNKNOWN),
158 m_securityModelVersion(
159 WrtDB::WidgetSecurityModelVersion::WIDGET_SECURITY_MODEL_V1),
162 LOG_PROFILE_START("Bundle attachToThread");
163 WrtDB::WrtDatabase::attachToThreadRO();
164 LOG_PROFILE_STOP("Bundle attachToThread");
165 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
172 WrtDB::WrtDatabase::detachFromThread();
174 if (!m_pagesList.empty()) {
175 LogError("There are not closed pages!");
180 void Bundle::didCreatePageCallback(
181 WKBundleRef /*bundle*/,
182 WKBundlePageRef page,
183 const void* clientInfo)
185 LOG_PROFILE_START("didCreatePageCallback");
186 LogDebug("didCreatePageCallback called");
187 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
188 This->didCreatePage(page);
189 LOG_PROFILE_STOP("didCreatePageCallback");
192 void Bundle::didReceiveMessageCallback(
193 WKBundleRef /*bundle*/,
194 WKStringRef messageName,
195 WKTypeRef messageBody,
196 const void *clientInfo)
198 LogDebug("didReceiveMessageCallback called");
199 Bundle* bundle = static_cast<Bundle*>(const_cast<void*>(clientInfo));
200 bundle->didReceiveMessage(messageName, messageBody);
203 void Bundle::willDestroyPageCallback(
204 WKBundleRef /*bundle*/,
205 WKBundlePageRef page,
206 const void* clientInfo)
208 LogDebug("willDestroyPageCallback called");
209 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
210 This->willDestroyPage(page);
213 void Bundle::didCreatePage(WKBundlePageRef page)
215 auto mainFrame = WKBundlePageGetMainFrame(page);
216 auto context = WKBundleFrameGetJavaScriptContext(mainFrame);
217 m_pagesList.push_back(page);
218 m_pageGlobalContext.insertContextForPage(page, context);
219 LogDebug("created Page : " << page << " created JSContext : " << context);
221 WKBundlePageResourceLoadClient resourceLoadClient = {
222 kWKBundlePageResourceLoadClientCurrentVersion, /* version */
223 this, /* clientinfo */
224 0, /* didInitiateLoadForResource */
225 willSendRequestForFrameCallback, /* willSendRequestForFrame */
226 0, /* didReceiveResponseForResource */
227 0, /* didReceiveContentLengthForResource */
228 didFinishLoadForResourceCallback, /* didFinishLoadForResource */
229 0, /* didFailLoadForResource */
230 0, /* shouldCacheResponse */
231 0, /* shouldUseCredentialStorage */
233 WKBundlePageSetResourceLoadClient(page, &resourceLoadClient);
235 WKBundlePageLoaderClient loaderClient = {
236 kWKBundlePageLoaderClientCurrentVersion,
237 this, /* clientinfo */
238 didStartProvisionalLoadForFrameCallback, /* didStartProvisionalLoadForFrame */
239 0, /* didReceiveServerRedirectForProvisionalLoadForFrame */
240 0, /* didFailProvisionalLoadWithErrorForFrame */
241 didCommitLoadForFrameCallback, /* didCommitLoadForFrame */
242 0, /* didFinishDocumentLoadForFrame */
243 0, /* didFinishLoadForFrame */
244 0, /* didFailLoadWithErrorForFrame */
245 0, /* didSameDocumentNavigationForFrame */
246 0, /* didReceiveTitleForFrame */
247 0, /* didFirstLayoutForFrame */
248 0, /* didFirstVisuallyNonEmptyLayoutForFrame */
249 didRemoveFrameFromHierarchyCallback, /* didRemoveFrameFromHierarchy */
250 0, /* didDisplayInsecureContentForFrame */
251 0, /* didRunInsecureContentForFrame */
252 0, /* didClearWindowObjectForFrame */
253 0, /* didCancelClientRedirectForFrame */
254 0, /* willPerformClientRedirectForFrame */
255 0, /* didHandleOnloadEventsForFrame */
256 0, /* didLayoutForFrame */
257 0, /* didNewFirstVisuallyNonEmptyLayout */
258 0, /* didDetectXSSForFrame */
259 0, /* shouldGoToBackForwardListItem */
260 0, /* globalObjectIsAvailableForFrame */
261 0, /* willDisconnectDOMWindowExtensionFromGlobalObject */
262 0, /* didReconnectDOMWindowExtensionToGlobalObject */
263 0, /* willDestroyGlobalObjectForDOMWindowExtension */
264 0, /* didFinishProgress */
265 0, /* shouldForceUniversalAccessFromLocalURL */
266 0, /* didReceiveIntentForFrame */
267 0, /* registerIntentServiceForFrame */
269 WKBundlePageSetPageLoaderClient(page, &loaderClient);
272 WKBundlePagePolicyClient policyClient = {
273 kWKBundlePagePolicyClientCurrentVersion, /* version */
274 this, /* clientInfo */
275 decidePolicyForNavigationActionCallback, /* decidePolicyForNavigationAction */
276 decidePolicyForNewWindowActionCallback, /* decidePolicyForNavigationAction */
277 decidePolicyForResponseCallback, /* decidePolicyForResponse */
278 0, /* unableToImplementPolicy */
280 WKBundlePageSetPolicyClient(page, &policyClient);
283 void Bundle::willDestroyPage(WKBundlePageRef page)
285 LogDebug("Destroyed page : " << page);
287 auto context = m_pageGlobalContext.getContextForPage(page);
288 m_pagesList.remove(page);
289 m_pageGlobalContext.removeContextForPage(page);
290 m_pageContext[page].erase(context);
292 PluginModule::unloadFrame(context);
293 PluginModule::stop(context);
296 void Bundle::fixWKMessageArgs(std::string & argScale,
297 std::string & argEncodedBundle,
298 std::string & argTheme)
300 if (argScale != "null" && argScale[0] == '_') {
301 argScale.erase(0, 1);
303 std::stringstream ssScale(argScale);
307 if (argEncodedBundle != "null" && argEncodedBundle[0] == '_') {
308 argEncodedBundle.erase(0, 1);
310 m_encodedBundle = argEncodedBundle;
313 if (argTheme != "null" && argTheme[0] == '_') {
314 argTheme.erase(0, 1);
320 #ifdef CORS_WHITELISTING_ENABLED
321 void Bundle::bypassCORSforWARPAccessList(WrtDB::WidgetDAOReadOnly & dao)
323 // bypassing CORS using origin whitelist
324 WrtDB::WidgetAccessInfoList WAList;
325 dao.getWidgetAccessInfo(WAList);
328 const WrtDB::WidgetAccessInfo & access = *it;
329 WKURLRef url = WKURLCreateWithUTF8CString(DPL::ToUTF8String(access.strIRI).c_str());
331 #ifdef APP_SCHEME_ENABLED
332 std::string source = std::string("app://") + DPL::ToUTF8String(m_widgetTizenId) + "/";
334 std::string source = DPL::ToUTF8String(dao.getFullPath());
337 LogDebug("WARP to WK whitelist position: " << source << " for "
338 << access.strIRI << " subDomains: " << access.bSubDomains);
340 WKStringRef wkSource = WKStringCreateWithUTF8CString(source.c_str());
342 WKStringRef wkProtocol;
343 if(access.strIRI == L"*")
345 //wildcard force to explicitly say which protocol is used
346 // passed wkHost if empty means wildcard -> allow everything but protocol has to be set.
347 for(unsigned i = 0; i < sizeof(warpAllowProtocolsForWildcard) / sizeof(char*); i++)
349 wkHost = WKStringCreateWithUTF8CString("");
350 wkProtocol = WKStringCreateWithUTF8CString(warpAllowProtocolsForWildcard[i]);
351 WKBundleAddOriginAccessWhitelistEntry(m_bundle,
352 wkSource, wkProtocol, wkHost, access.bSubDomains);
357 wkHost = WKURLCopyHostName(url);
358 wkProtocol = WKURLCopyScheme(url);
359 WKBundleAddOriginAccessWhitelistEntry(m_bundle,
360 wkSource, wkProtocol, wkHost, access.bSubDomains);
364 WKRelease(wkProtocol);
370 void Bundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
372 LogDebug("got message type: " << toString(messageName).c_str());
373 if (WKStringIsEqualToUTF8CString(messageName,
374 BundleMessages::START))
376 if (!messageBody || WKStringGetTypeID() != WKGetTypeID(messageBody)) {
377 LogError("Wrong message format received, ignoring");
381 auto msgString = toString(static_cast<WKStringRef>(messageBody));
382 LogDebug("Got message text: " << msgString);
383 LogDebug("loading Page : " << m_pagesList.back() <<
384 " loading JSContext : " <<
385 m_pageGlobalContext.getContextForPage(m_pagesList.back()));
386 // set information from ui process
387 std::stringstream ssMsg(msgString);
388 std::string argScale;
389 std::string argEncodedBundle;
390 std::string argTheme;
394 m_widgetTizenId = DPL::FromASCIIString(id);
397 ssMsg >> argEncodedBundle;
399 ssMsg >> m_encrypted;
400 LogWarning("m_encrypted : " << m_encrypted);
402 // ** Language tags setting completed **
403 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
404 } else if (WKStringIsEqualToUTF8CString(messageName,
405 BundleMessages::SHUTDOWN))
407 LogDebug("shutdown plugins");
409 if (m_pagesList.empty()) {
410 PluginModule::shutdown();
413 "PluginModule shutdown ignored, there are still alive pages!");
416 else if (WKStringIsEqualToUTF8CString(messageName,
417 BundleMessages::SET_CUSTOM_PROPERTIES))
419 LogDebug("reset custom properties of window objects");
420 // set information from ui process
421 auto msgString = toString(static_cast<WKStringRef>(messageBody));
423 std::string argScale;
424 std::string argEncodedBundle;
425 std::string argTheme;
427 std::stringstream ssMsg(msgString);
429 ssMsg >> argEncodedBundle;
432 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
434 //apply for each context
435 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
436 for (; it != m_pageGlobalContext.end(); ++it) {
437 PluginModule::setCustomProperties(it->second,
439 m_encodedBundle.c_str(),
442 } else if (WKStringIsEqualToUTF8CString(
444 BundleMessages::DISPATCH_JAVASCRIPT_EVENT))
446 LogDebug("dispatch javascript event to created frames");
447 // set information from ui process
448 auto text = toString(static_cast<WKStringRef>(messageBody));
451 std::stringstream ss(text);
454 using namespace WrtPlugins::W3C;
455 // set arguments to be sent to js handler of this custom event
456 if (eventType == SoftKeyboardChangeCustomEvent) {
457 args = new SoftKeyboardChangeArgs;
458 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->state;
459 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->width;
460 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->height;
463 //apply for each context
464 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
465 for (; it != m_pageGlobalContext.end(); ++it) {
466 PluginModule::dispatchJavaScriptEvent(
468 static_cast<WrtPlugins::W3C::CustomEventType>(eventType),
473 delete static_cast<SoftKeyboardChangeArgs *>(args);
475 } else if (WKStringIsEqualToUTF8CString(
477 BundleMessages::INIT))
479 LogDebug("initializing plugins");
483 auto msgString = toString(static_cast<WKStringRef>(messageBody));
485 m_widgetTizenId = DPL::FromASCIIString(msgString);
487 WrtDB::WidgetDAOReadOnly dao(m_widgetTizenId);
489 // process pool - set app_privilige
490 if (UID_ROOT == getuid())
492 using namespace WrtDB::GlobalConfig;
495 std::string tzAppId = DPL::ToUTF8String(dao.getTzAppId());
496 std::string tzPkgId = DPL::ToUTF8String(dao.getTizenPkgId());
497 DPL::OptionalString installedPath = dao.getWidgetInstalledPath();
498 if (installedPath.IsNull()) {
499 appPath = std::string(GetUserInstalledWidgetPath()) + "/" +
500 tzPkgId + GetUserWidgetExecPath() + "/" + tzAppId;
502 appPath = DPL::ToUTF8String(*installedPath) +
503 GetUserWidgetExecPath() + "/" + tzAppId;
506 LogDebug("set_app_privilege(" << appPath << ")");
507 set_app_privilege(tzPkgId.c_str(), PRIVILEGE_APP_TYPE, appPath.c_str());
510 /* This type of message is received when widget is restarting
511 * (proably in other situation too). Widget restart can be
512 * called after system language change so language tags have to
514 * Do NOT MOVE LanguageTags reset before m_widgetHandle initialization
516 // reset language tags (create new tags based on system locales)
517 LanguageTagsProviderSingleton::Instance().resetLanguageTags();
518 DPL::OptionalString defaultLocale = dao.getDefaultlocale();
519 if (!defaultLocale.IsNull()) {
520 LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
524 LanguageTagsProviderSingleton::Instance().getLanguageTags();
525 LogDebug("Current widget locales (language tags):");
527 LogDebug("Locale: " << *it);
530 m_widgetType = dao.getWidgetType();
531 LogDebug("m_widgetType : " << m_widgetType.getApptypeToString() <<
532 "(m_widgetTizenId:" << m_widgetTizenId << ")");
534 LogDebug("Preload PluginLogicSingleton");
535 PluginModule::init(WrtDB::WidgetDAOReadOnly::getHandle(m_widgetTizenId));
536 LogDebug("Preload PluginLogicSingleton_end");
538 m_securityModelVersion = dao.getSecurityModelVersion();
539 #ifdef CORS_WHITELISTING_ENABLED
540 bypassCORSforWARPAccessList(dao);
542 m_initialized = true;
546 LogDebug("already initalized");
551 WKURLRequestRef Bundle::willSendRequestForFrameCallback(
552 WKBundlePageRef /*page*/,
553 WKBundleFrameRef /*frame*/,
554 uint64_t /*resourceIdentifier*/,
555 WKURLRequestRef request,
556 WKURLResponseRef /*response*/,
557 const void *clientInfo)
559 LogDebug("willSendRequestForFrameCallback called");
560 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
561 return This->willSendRequestForFrame(request);
564 void Bundle::didStartProvisionalLoadForFrameCallback(
565 WKBundlePageRef page,
566 WKBundleFrameRef frame,
567 WKTypeRef* /*userData*/,
568 const void *clientInfo)
570 LogDebug("didStartProvisionalLoadForFrameCallback called");
571 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
574 WrtDB::WidgetDAOReadOnly dao(This->m_widgetTizenId);
575 WrtDB::WindowModeList modeList = dao.getWindowModes();
576 FOREACH(it, modeList) {
577 std::string viewMode = DPL::ToUTF8String(*it);
578 if (viewMode == VIEWMODE_TYPE_FULLSCREEN
579 || viewMode == VIEWMODE_TYPE_MAXIMIZED)
581 WKBundlePageSetViewMode(
583 WKStringCreateWithUTF8CString(viewMode.c_str()));
588 if (This->m_pageGlobalContext.find(page) == This->m_pageGlobalContext.end()) {
591 if (This->m_pageContext.count(page) == 0) {
595 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
597 ContextSet::iterator i = This->m_pageContext[page].find(context);
599 if (i == This->m_pageContext[page].end()) {
600 LogDebug("Initially attached frame");
604 This->m_pageContext[page].erase(i);
605 This->m_willRemoveContext = context;
608 void Bundle::didRemoveFrameFromHierarchyCallback(
609 WKBundlePageRef page,
610 WKBundleFrameRef frame,
611 WKTypeRef* /*userData*/,
612 const void *clientInfo)
614 LogDebug("didRemoveFrameFromHierarchyCallback called");
615 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
617 if (This->m_pageContext.count(page) == 0) {
618 LogDebug("his->m_pageContext.count(page) == 0");
622 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
624 ContextSet::iterator i = This->m_pageContext[page].find(context);
626 if (i == This->m_pageContext[page].end()) {
627 LogWarning("Tried to unload frame which has never been loaded");
631 This->m_pageContext[page].erase(i);
633 PluginModule::unloadFrame(context);
636 void Bundle::didFinishLoadForResourceCallback(
637 WKBundlePageRef /*page*/,
638 WKBundleFrameRef /*frame*/,
639 uint64_t /*resourceIdentifier*/,
640 const void* /*clientInfo*/)
642 LogDebug("didFinishLoadForResourceCallback called");
645 void Bundle::didCommitLoadForFrameCallback(
646 WKBundlePageRef page,
647 WKBundleFrameRef frame,
648 WKTypeRef* /*userData*/,
649 const void *clientInfo)
651 LogInfo("didCommitLoadForFrameCallback called");
652 LOG_PROFILE_START("didCommitLoadForFrameCallback");
653 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
655 WKURLRef url = WKBundleFrameCopyURL(frame);
658 LogInfo("url is NULL");
662 if (This->m_willRemoveContext) {
663 PluginModule::unloadFrame(This->m_willRemoveContext);
664 This->m_willRemoveContext = NULL;
667 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
669 This->m_pageContext[page].insert(context);
671 if (!WKBundleFrameIsMainFrame(frame)) {
672 LogInfo("frame isn't main frame");
674 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
677 This->m_encodedBundle.c_str(),
678 This->m_theme.c_str());
679 PluginModule::loadFrame(context);
683 std::string urlStr = toString(url);
684 if (InjectedBundleURIHandling::processURIForPlugin(urlStr.c_str())) {
685 LogDebug("start plugin");
686 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
688 LogDebug("Previous context: " << This->m_pageGlobalContext.getContextForPage(page));
689 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
691 LogDebug("New context: " << context);
692 //note that since we need old context for unloading plugins it must be sotred
693 //custom container take care of increamenting and decrementing references
694 This->m_pageGlobalContext.insertContextForPage(page, context);
695 LOG_PROFILE_START("PluginModule start");
697 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
700 This->m_encodedBundle.c_str(),
701 This->m_theme.c_str() );
702 LOG_PROFILE_STOP("PluginModule start");
704 PluginModule::loadFrame(context);
706 LogDebug("stop plugin");
707 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
709 LogDebug("Previous context: " << This->m_pageGlobalContext.getContextForPage(page));
710 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
712 LogDebug("New context: " << context);
713 This->m_pageGlobalContext.insertContextForPage(page, context);
715 LOG_PROFILE_STOP("didCommitLoadForFrameCallback");
718 WKBundlePagePolicyAction Bundle::decidePolicyForNavigationActionCallback(
719 WKBundlePageRef page,
720 WKBundleFrameRef frame,
721 WKBundleNavigationActionRef navigationAction,
722 WKURLRequestRef request,
724 const void* clientInfo)
726 LogDebug("decidePolicyForNavigationActionCallback called");
728 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
729 return This->decidePolicyForAction(false,
737 WKBundlePagePolicyAction Bundle::decidePolicyForNewWindowActionCallback(
738 WKBundlePageRef page,
739 WKBundleFrameRef frame,
740 WKBundleNavigationActionRef navigationAction,
741 WKURLRequestRef request,
742 WKStringRef /*frameName*/,
744 const void* clientInfo)
746 LogDebug("decidePolicyForNewWindowActionCallback called");
748 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
749 return This->decidePolicyForAction(true,
757 WKBundlePagePolicyAction Bundle::decidePolicyForResponseCallback(
758 WKBundlePageRef /* page */,
759 WKBundleFrameRef /* frame */,
760 WKURLResponseRef response,
761 WKURLRequestRef /* request */,
762 WKTypeRef* /* userData */,
763 const void* /* clientInfo */)
765 LogDebug("decidePolicyForResponseCallback called");
768 WKStringRef contentTypeRef = WKURLResponseEflCopyContentType(response);
770 std::string contentType = toString(contentTypeRef);
771 LogDebug("contentTypeRef : " << contentType);
772 WKRelease(contentTypeRef);
774 if (contentType == HTML_MIME) {
775 LogDebug("Accepting HTML_MIME type");
776 return WKBundlePagePolicyActionUse;
778 if (contentType == PHP_MIME) {
779 LogDebug("Accepting php type");
780 return WKBundlePagePolicyActionUse;
783 return WKBundlePagePolicyActionPassThrough;
786 WKURLRequestRef Bundle::willSendRequestForFrame(WKURLRequestRef request)
788 LogDebug("willSendReq got " << toString(request).c_str());
789 WKURLRef url = WKURLRequestCopyURL(request);
790 WKStringRef urlStr = WKURLCopyString(url);
792 DPL::String dplurl = DPL::FromUTF8String(toString(urlStr));
795 DPL::Optional<DPL::String> localizedUrl =
796 InjectedBundleURIHandling::localizeURI(dplurl, m_widgetTizenId);
798 InjectedBundleURIHandling::processURI(*localizedUrl,
800 m_securityModelVersion);
803 LogDebug("Not permitted resource: " << *localizedUrl);
807 LogDebug("URI processing result: " << *localizedUrl);
808 std::string tmpUrlStr = DPL::ToUTF8String(*localizedUrl);
809 WKURLRef tmpUrl = WKURLCreateWithUTF8CString(tmpUrlStr.c_str());
810 std::string scheme = toString(WKURLCopyScheme(url)); //scheme of original request
813 #ifdef APP_SCHEME_ENABLED
814 if(scheme == SCHEME_FILE) {
815 LogError("File schema blocked for: " << dplurl);
820 // Return value must contain details information of input
821 // WKURLRequestRef. Current webkit2 doesn't support api that
822 // copy WKURLRequestRef or change url only. Before webkit2
823 // support api, callback return original WKURLRequestRef in the
824 // case of external scheme
826 // external scheme also need to send message to UI process for
827 // checking roaming and security
828 if (scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS) {
829 LogDebug("external scheme return original WKURLRequestRef");
834 std::string checkUrl = toString(tmpUrl);
838 if (isEncryptedResource(checkUrl, getFileSize)) {
839 std::string decryptString = DecryptResource(checkUrl,
841 if (!decryptString.empty()) {
842 std::string destString = DATA_STRING;
844 std::string mimeString =
846 MimeTypeUtils::identifyFileMimeType(
847 DPL::FromUTF8String(checkUrl)));
849 destString += mimeString;
850 destString += BASE64_STRING;
852 decryptString.insert(0, destString);
855 WKURLCreateWithUTF8CString(decryptString.c_str());
857 WKURLRequestRef req = WKURLRequestCreateWithWKURL(
860 LogDebug("return value " << decryptString << "]]");
865 WKURLRequestRef req = WKURLRequestCreateWithWKURL(tmpUrl);
867 LogDebug("return value " << toString(req).c_str());
872 WKBundlePagePolicyAction Bundle::decidePolicyForAction(
874 WKBundlePageRef /* page */,
875 WKBundleFrameRef frame,
876 WKBundleNavigationActionRef /* navigationAction */,
877 WKURLRequestRef request,
878 WKTypeRef* /* userData */)
880 using namespace ViewModule;
881 using namespace ViewModule::SchemeActionMap;
883 char const * const TIZEN_SCHEME = "tizen";
885 std::string request_uri = toString(request);
887 LogInfo("Uri being checked: " << request_uri);
890 if (request_uri == BLANK_PAGE_URL) {
891 return WKBundlePagePolicyActionUse;
894 // in case of box scheme, unconditionally PassThrough should be returned
895 if (!request_uri.compare(0, 6, SCHEME_BOX_SLASH)) {
896 return WKBundlePagePolicyActionPassThrough;
899 DPL::String dplUrl = DPL::FromUTF8String(request_uri);
901 InjectedBundleURIHandling::processMainResource(dplUrl,
903 m_securityModelVersion);
905 std::string blockedUrl = DPL::ToUTF8String(dplUrl);
906 LogDebug("URI is blocked: " << blockedUrl);
908 // Send information about blocked URI to UIProcess
909 WKStringRef urlStr = WKStringCreateWithUTF8CString(blockedUrl.c_str());
910 WKTypeRef retVal = NULL;
911 WKStringRef blockMessage = WKStringCreateWithUTF8CString(uriBlockedMessageName);
912 WKBundlePostSynchronousMessage(m_bundle, blockMessage, urlStr, &retVal);
915 WKRelease(blockMessage);
916 return WKBundlePagePolicyActionPassThrough;
920 std::string request_scheme = getScheme(request_uri);
923 if (request_scheme == TIZEN_SCHEME) {
924 return WKBundlePagePolicyActionPassThrough;
928 Scheme scheme(request_scheme);
929 LogDebug("Scheme: " << request_scheme);
931 Scheme::Type type = scheme.GetType();
932 if (type < Scheme::FILE || type >= Scheme::COUNT) {
933 LogError("Invalid scheme: " << request_scheme);
934 return WKBundlePagePolicyActionPassThrough;
937 bool mainFrame = WKBundleFrameIsMainFrame(frame);
938 NavigationContext ctx = mainFrame ? TOP_LEVEL : FRAME_LEVEL;
943 LogDebug("Scheme type: " << type);
944 LogDebug("Navigation context: " << ctx);
945 LogDebug("Application type: " << m_widgetType.getApptypeToString());
949 if (m_widgetType == WrtDB::APP_TYPE_TIZENWEBAPP) {
950 action = g_tizenActionMap[type][ctx];
952 LogError("Unsupported application type: " << type);
953 return WKBundlePagePolicyActionPassThrough;
956 LogDebug("Uri action: " << action);
958 if (action != URI_ACTION_WRT) {
959 return WKBundlePagePolicyActionPassThrough;
962 return WKBundlePagePolicyActionUse;
965 std::string Bundle::toString(WKStringRef str)
967 if (WKStringIsEmpty(str)) {
968 return std::string();
970 size_t size = WKStringGetMaximumUTF8CStringSize(str);
971 char buffer[size + 1];
972 WKStringGetUTF8CString(str, buffer, size + 1);
976 std::string Bundle::toString(WKURLRef url)
978 WKStringRef urlStr = WKURLCopyString(url);
979 std::string str = toString(urlStr);
984 std::string Bundle::toString(WKURLRequestRef req)
986 WKURLRef reqUrl = WKURLRequestCopyURL(req);
987 std::string str = toString(reqUrl);
992 std::string Bundle::toString(WKErrorRef err)
994 WKStringRef domErr = WKErrorCopyDomain(err);
995 WKStringRef desc = WKErrorCopyLocalizedDescription(err);
996 std::string str = toString(domErr) + "\n" + toString(desc);
1002 std::string Bundle::getScheme(std::string uri)
1004 std::size_t found = uri.find(':');
1007 if (found != std::string::npos) {
1008 str = uri.substr(0, found);
1014 bool Bundle::isEncryptedResource(std::string Url, int &size)
1016 if (m_encryptedFiles.empty()) {
1017 WrtDB::WidgetDAOReadOnly(m_widgetTizenId).
1018 getEncryptedFileList(m_encryptedFiles);
1021 std::set<WrtDB::EncryptedFileInfo>::iterator it;
1022 WrtDB::EncryptedFileInfo info;
1023 std::string filePath;
1025 if (0 != strncmp(Url.c_str(), SCHEME_FILE_SLASH, strlen(SCHEME_FILE_SLASH))) {
1029 filePath = Url.substr(strlen(SCHEME_FILE_SLASH));
1030 info.fileName = DPL::FromUTF8String(filePath);
1032 if (m_encryptedFiles.end() != (it = m_encryptedFiles.find(info)))
1034 LogDebug(" info file name : " << it->fileName);
1035 LogDebug(" info file size : " << it->fileSize);
1036 size = it->fileSize;
1042 std::string Bundle::DecryptResource(std::string resource, int size)
1044 std::string filePath;
1046 size_t pos = resource.find_first_not_of(SCHEME_FILE_SLASH);
1047 if (std::string::npos != pos) {
1048 filePath = resource.substr(pos - 1);
1052 if (0 == stat(filePath.c_str(), &buf)) {
1053 const std::size_t fileSize = buf.st_size;
1054 std::unique_ptr<unsigned char[]> inChunk;
1056 FILE* fp = fopen(filePath.c_str(), "rb");
1058 LogDebug("Couldnot open file : " << filePath);
1059 return std::string();
1062 std::unique_ptr<unsigned char[]> DecryptedString(new unsigned
1064 std::string pkgid(DPL::ToUTF8String(m_widgetTizenId));
1066 using namespace Tizen::Base;
1067 const byte *b_pkgid = reinterpret_cast<const byte*>(pkgid.c_str());
1069 appInfo.Construct(pkgid.length());
1070 if (appInfo.SetArray(b_pkgid, 0, pkgid.length()) != E_SUCCESS) {
1071 LogDebug("Couldnot set appInfo");
1073 return std::string();
1079 unsigned char getDecSize[4];
1080 memset(getDecSize, 0x00, sizeof(getDecSize));
1082 size_t readSize = fread(getDecSize, sizeof(unsigned char),
1083 sizeof(getDecSize), fp);
1084 if (0 != readSize) {
1085 int readBufSize = 0;
1086 std::istringstream(std::string((char*)getDecSize)) >> readBufSize;
1087 inChunk.reset(new unsigned char[readBufSize]);
1089 size_t decReadSize = fread(inChunk.get(), sizeof(unsigned char),
1091 if (0 != decReadSize) {
1092 ByteBuffer *getBuffer =
1093 DecryptChunkByTrustZone(&appInfo, inChunk.get(),
1095 memcpy(DecryptedString.get() + writeCount,
1096 getBuffer->GetPointer(), getBuffer->GetRemaining());
1097 writeCount += getBuffer->GetRemaining();
1102 } while( 0 == std::feof(fp));
1105 memset(DecryptedString.get() + size, '\n', fileSize - size);
1106 LogDebug("resource need to encoding base64");
1110 b64 = BIO_new(BIO_f_base64());
1111 bmem = BIO_new(BIO_s_mem());
1112 b64 = BIO_push(b64, bmem);
1113 BIO_write(b64, DecryptedString.get(), fileSize);
1115 BIO_get_mem_ptr(b64, &bptr);
1117 std::string base64Enc((char *)bptr->data, bptr->length - 1);
1122 return std::string();
1125 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
1126 void Bundle::sendWebProcessPid()
1128 std::stringstream strPid;
1130 WKStringRef pidStr = WKStringCreateWithUTF8CString(strPid.str().c_str());
1131 WKTypeRef retVal = NULL;
1132 WKStringRef message = WKStringCreateWithUTF8CString(webProcessPidMessageName);
1133 WKBundlePostSynchronousMessage(m_bundle, message, pidStr, &retVal);
1143 void WKBundleInitialize(WKBundleRef bundle,
1146 DPL::Log::LogSystemSingleton::Instance().SetTag("WRT-BUNDLE");
1147 LogDebug("Bundle initialized");
1149 DPL::Event::GetMainEventDispatcherInstance().ResetCrossEventCallHandler();
1150 LogDebug("ResetCrossEventCallHandler()");
1152 static Bundle s_bundle(bundle);
1154 WKBundleClient client = {
1155 kWKBundleClientCurrentVersion,
1157 &Bundle::didCreatePageCallback,
1158 &Bundle::willDestroyPageCallback,
1159 0, /* didInitializePageGroup */
1160 &Bundle::didReceiveMessageCallback
1162 WKBundleSetClient(bundle, &client);
1164 // process pool - restore process priority
1165 if (UID_ROOT == getuid())
1167 setpriority(PRIO_PROCESS, 0, DEFAULT_PRIORITY);