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>
60 #include <FBaseByteBuffer.h>
61 #include <security/FSecCrypto_TrustZoneService.h>
64 #include <wrt_plugin_module.h>
65 #include <profiling_util.h>
68 #include <appcore-efl.h>
70 #include "messages_names.h"
73 #include <scheme_action_map_type.h>
74 #include <scheme_action_map_data.h>
76 #include <js_overlay_types.h>
79 #include <sys/resource.h>
80 #include <privilege-control.h>
82 // URI localization on WebProcess side
83 #include "injected_bundle_uri_handling.h"
85 void InitWebAppInfo(const char* appId, const char* rootPath);
89 const char * const uriBlockedMessageName = "uri_blocked_msg";
90 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
91 const char * const webProcessPidMessageName = "web_process_pid_msg";
93 const char * const SCHEME_HTTP = "http";
94 const char * const SCHEME_HTTPS = "https";
95 const char * const SCHEME_FILE = "file";
96 const char * const SCHEME_FILE_SLASH = "file://";
97 const char * const SCHEME_BOX_SLASH = "box://";
98 const char * const DATA_STRING = "data:";
99 const char * const BASE64_STRING = ";base64,";
100 const char * const BLANK_PAGE_URL = "about:blank";
101 const char * const HTML_MIME = "text/html";
102 const char * const PHP_MIME = "application/x-php";
103 const char * const VIEWMODE_TYPE_FULLSCREEN = "fullscreen";
104 const char * const VIEWMODE_TYPE_MAXIMIZED = "maximized";
105 const std::size_t FILE_BUF_MAX_SIZE = 1024; // bytes
106 const std::size_t PLAIN_CHUNK_SIZE = 1008; // bytes
107 const unsigned int UID_ROOT = 0;
108 const unsigned int DEFAULT_PRIORITY = 0;
109 const char * const PRIVILEGE_APP_TYPE = "wgt";
110 #ifdef CORS_WHITELISTING_ENABLED
111 const char * const warpAllowProtocolsForWildcard[] = { "http", "https" };
115 static bool m_initWebApp = false;
117 Tizen::Base::ByteBuffer *DecryptChunkByTrustZone(
118 Tizen::Base::ByteBuffer *appInfo,
119 const unsigned char *inBuffer,
122 using namespace Tizen::Base;
126 pAppId = (char*)calloc(appInfo->GetRemaining()+1, 1);
127 memcpy(pAppId, appInfo->GetPointer(), appInfo->GetRemaining());
129 InitWebAppInfo(pAppId, "");
134 Tizen::Security::Crypto::_TrustZoneService* pInstance;
135 pInstance = Tizen::Security::Crypto::_TrustZoneService::GetInstance();
138 pBuf.Construct(inBufSize);
139 const byte *pByte = reinterpret_cast<const byte*>(inBuffer);
141 if (pBuf.SetArray(pByte, 0, inBufSize) != E_SUCCESS) {
142 LogDebug("Couldnot set pBuf");
148 return pInstance->_TrustZoneService::DecryptN(*appInfo, pBuf);
154 Bundle::Bundle(WKBundleRef bundle) :
159 m_willRemoveContext(NULL),
161 m_widgetType(WrtDB::APP_TYPE_UNKNOWN),
162 m_securityModelVersion(
163 WrtDB::WidgetSecurityModelVersion::WIDGET_SECURITY_MODEL_V1),
166 LOG_PROFILE_START("Bundle attachToThread");
167 WrtDB::WrtDatabase::attachToThreadRO();
168 LOG_PROFILE_STOP("Bundle attachToThread");
169 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
176 WrtDB::WrtDatabase::detachFromThread();
178 if (!m_pagesList.empty()) {
179 LogError("There are not closed pages!");
184 void Bundle::didCreatePageCallback(
185 WKBundleRef /*bundle*/,
186 WKBundlePageRef page,
187 const void* clientInfo)
189 LOG_PROFILE_START("didCreatePageCallback");
190 LogDebug("didCreatePageCallback called");
191 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
192 This->didCreatePage(page);
193 LOG_PROFILE_STOP("didCreatePageCallback");
196 void Bundle::didReceiveMessageCallback(
197 WKBundleRef /*bundle*/,
198 WKStringRef messageName,
199 WKTypeRef messageBody,
200 const void *clientInfo)
202 LogDebug("didReceiveMessageCallback called");
203 Bundle* bundle = static_cast<Bundle*>(const_cast<void*>(clientInfo));
204 bundle->didReceiveMessage(messageName, messageBody);
207 void Bundle::willDestroyPageCallback(
208 WKBundleRef /*bundle*/,
209 WKBundlePageRef page,
210 const void* clientInfo)
212 LogDebug("willDestroyPageCallback called");
213 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
214 This->willDestroyPage(page);
217 void Bundle::didCreatePage(WKBundlePageRef page)
219 auto mainFrame = WKBundlePageGetMainFrame(page);
220 auto context = WKBundleFrameGetJavaScriptContext(mainFrame);
221 m_pagesList.push_back(page);
222 m_pageGlobalContext.insertContextForPage(page, context);
223 LogDebug("created Page : " << page << " created JSContext : " << context);
225 WKBundlePageResourceLoadClient resourceLoadClient = {
226 kWKBundlePageResourceLoadClientCurrentVersion, /* version */
227 this, /* clientinfo */
228 0, /* didInitiateLoadForResource */
229 willSendRequestForFrameCallback, /* willSendRequestForFrame */
230 0, /* didReceiveResponseForResource */
231 0, /* didReceiveContentLengthForResource */
232 didFinishLoadForResourceCallback, /* didFinishLoadForResource */
233 0, /* didFailLoadForResource */
234 0, /* shouldCacheResponse */
235 0, /* shouldUseCredentialStorage */
237 WKBundlePageSetResourceLoadClient(page, &resourceLoadClient);
239 WKBundlePageLoaderClient loaderClient = {
240 kWKBundlePageLoaderClientCurrentVersion,
241 this, /* clientinfo */
242 didStartProvisionalLoadForFrameCallback, /* didStartProvisionalLoadForFrame */
243 0, /* didReceiveServerRedirectForProvisionalLoadForFrame */
244 0, /* didFailProvisionalLoadWithErrorForFrame */
245 didCommitLoadForFrameCallback, /* didCommitLoadForFrame */
246 0, /* didFinishDocumentLoadForFrame */
247 0, /* didFinishLoadForFrame */
248 0, /* didFailLoadWithErrorForFrame */
249 0, /* didSameDocumentNavigationForFrame */
250 0, /* didReceiveTitleForFrame */
251 0, /* didFirstLayoutForFrame */
252 0, /* didFirstVisuallyNonEmptyLayoutForFrame */
253 didRemoveFrameFromHierarchyCallback, /* didRemoveFrameFromHierarchy */
254 0, /* didDisplayInsecureContentForFrame */
255 0, /* didRunInsecureContentForFrame */
256 0, /* didClearWindowObjectForFrame */
257 0, /* didCancelClientRedirectForFrame */
258 0, /* willPerformClientRedirectForFrame */
259 0, /* didHandleOnloadEventsForFrame */
260 0, /* didLayoutForFrame */
261 0, /* didNewFirstVisuallyNonEmptyLayout */
262 0, /* didDetectXSSForFrame */
263 0, /* shouldGoToBackForwardListItem */
264 0, /* globalObjectIsAvailableForFrame */
265 0, /* willDisconnectDOMWindowExtensionFromGlobalObject */
266 0, /* didReconnectDOMWindowExtensionToGlobalObject */
267 0, /* willDestroyGlobalObjectForDOMWindowExtension */
268 0, /* didFinishProgress */
269 0, /* shouldForceUniversalAccessFromLocalURL */
270 0, /* didReceiveIntentForFrame */
271 0, /* registerIntentServiceForFrame */
273 WKBundlePageSetPageLoaderClient(page, &loaderClient);
276 WKBundlePagePolicyClient policyClient = {
277 kWKBundlePagePolicyClientCurrentVersion, /* version */
278 this, /* clientInfo */
279 decidePolicyForNavigationActionCallback, /* decidePolicyForNavigationAction */
280 decidePolicyForNewWindowActionCallback, /* decidePolicyForNavigationAction */
281 decidePolicyForResponseCallback, /* decidePolicyForResponse */
282 0, /* unableToImplementPolicy */
284 WKBundlePageSetPolicyClient(page, &policyClient);
287 void Bundle::willDestroyPage(WKBundlePageRef page)
289 LogDebug("Destroyed page : " << page);
291 auto context = m_pageGlobalContext.getContextForPage(page);
292 m_pagesList.remove(page);
293 m_pageGlobalContext.removeContextForPage(page);
294 m_pageContext[page].erase(context);
296 PluginModule::unloadFrame(context);
297 PluginModule::stop(context);
300 void Bundle::fixWKMessageArgs(std::string & argScale,
301 std::string & argEncodedBundle,
302 std::string & argTheme)
304 if (argScale != "null" && argScale[0] == '_') {
305 argScale.erase(0, 1);
307 std::stringstream ssScale(argScale);
311 if (argEncodedBundle != "null" && argEncodedBundle[0] == '_') {
312 argEncodedBundle.erase(0, 1);
314 m_encodedBundle = argEncodedBundle;
317 if (argTheme != "null" && argTheme[0] == '_') {
318 argTheme.erase(0, 1);
324 #ifdef CORS_WHITELISTING_ENABLED
325 void Bundle::bypassCORSforWARPAccessList(WrtDB::WidgetDAOReadOnly & dao)
327 // bypassing CORS using origin whitelist
328 WrtDB::WidgetAccessInfoList WAList;
329 dao.getWidgetAccessInfo(WAList);
332 const WrtDB::WidgetAccessInfo & access = *it;
333 WKURLRef url = WKURLCreateWithUTF8CString(DPL::ToUTF8String(access.strIRI).c_str());
335 #ifdef APP_SCHEME_ENABLED
336 std::string source = std::string("app://") + DPL::ToUTF8String(m_widgetTizenId) + "/";
338 std::string source = DPL::ToUTF8String(dao.getFullPath());
341 LogDebug("WARP to WK whitelist position: " << source << " for "
342 << access.strIRI << " subDomains: " << access.bSubDomains);
344 WKStringRef wkSource = WKStringCreateWithUTF8CString(source.c_str());
346 WKStringRef wkProtocol;
347 if(access.strIRI == L"*")
349 //wildcard force to explicitly say which protocol is used
350 // passed wkHost if empty means wildcard -> allow everything but protocol has to be set.
351 for(unsigned i = 0; i < sizeof(warpAllowProtocolsForWildcard) / sizeof(char*); i++)
353 wkHost = WKStringCreateWithUTF8CString("");
354 wkProtocol = WKStringCreateWithUTF8CString(warpAllowProtocolsForWildcard[i]);
355 WKBundleAddOriginAccessWhitelistEntry(m_bundle,
356 wkSource, wkProtocol, wkHost, access.bSubDomains);
361 wkHost = WKURLCopyHostName(url);
362 wkProtocol = WKURLCopyScheme(url);
363 WKBundleAddOriginAccessWhitelistEntry(m_bundle,
364 wkSource, wkProtocol, wkHost, access.bSubDomains);
368 WKRelease(wkProtocol);
374 void Bundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
376 LogDebug("got message type: " << toString(messageName).c_str());
377 if (WKStringIsEqualToUTF8CString(messageName,
378 BundleMessages::START))
380 if (!messageBody || WKStringGetTypeID() != WKGetTypeID(messageBody)) {
381 LogError("Wrong message format received, ignoring");
385 auto msgString = toString(static_cast<WKStringRef>(messageBody));
386 LogDebug("Got message text: " << msgString);
387 LogDebug("loading Page : " << m_pagesList.back() <<
388 " loading JSContext : " <<
389 m_pageGlobalContext.getContextForPage(m_pagesList.back()));
390 // set information from ui process
391 std::stringstream ssMsg(msgString);
392 std::string argScale;
393 std::string argEncodedBundle;
394 std::string argTheme;
398 m_widgetTizenId = DPL::FromASCIIString(id);
401 ssMsg >> argEncodedBundle;
403 ssMsg >> m_encrypted;
404 LogWarning("m_encrypted : " << m_encrypted);
406 // ** Language tags setting completed **
407 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
408 } else if (WKStringIsEqualToUTF8CString(messageName,
409 BundleMessages::SHUTDOWN))
411 LogDebug("shutdown plugins");
413 if (m_pagesList.empty()) {
414 PluginModule::shutdown();
417 "PluginModule shutdown ignored, there are still alive pages!");
420 else if (WKStringIsEqualToUTF8CString(messageName,
421 BundleMessages::SET_CUSTOM_PROPERTIES))
423 LogDebug("reset custom properties of window objects");
424 // set information from ui process
425 auto msgString = toString(static_cast<WKStringRef>(messageBody));
427 std::string argScale;
428 std::string argEncodedBundle;
429 std::string argTheme;
431 std::stringstream ssMsg(msgString);
433 ssMsg >> argEncodedBundle;
436 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
438 //apply for each context
439 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
440 for (; it != m_pageGlobalContext.end(); ++it) {
441 PluginModule::setCustomProperties(it->second,
443 m_encodedBundle.c_str(),
446 } else if (WKStringIsEqualToUTF8CString(
448 BundleMessages::DISPATCH_JAVASCRIPT_EVENT))
450 LogDebug("dispatch javascript event to created frames");
451 // set information from ui process
452 auto text = toString(static_cast<WKStringRef>(messageBody));
455 std::stringstream ss(text);
458 using namespace WrtPlugins::W3C;
459 // set arguments to be sent to js handler of this custom event
460 if (eventType == SoftKeyboardChangeCustomEvent) {
461 args = new SoftKeyboardChangeArgs;
462 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->state;
463 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->width;
464 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->height;
467 //apply for each context
468 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
469 for (; it != m_pageGlobalContext.end(); ++it) {
470 PluginModule::dispatchJavaScriptEvent(
472 static_cast<WrtPlugins::W3C::CustomEventType>(eventType),
477 delete static_cast<SoftKeyboardChangeArgs *>(args);
479 } else if (WKStringIsEqualToUTF8CString(
481 BundleMessages::INIT))
483 LogDebug("initializing plugins");
487 auto msgString = toString(static_cast<WKStringRef>(messageBody));
489 m_widgetTizenId = DPL::FromASCIIString(msgString);
491 WrtDB::WidgetDAOReadOnly dao(m_widgetTizenId);
493 // process pool - set app_privilige
494 if (UID_ROOT == getuid())
496 using namespace WrtDB::GlobalConfig;
499 std::string tzAppId = DPL::ToUTF8String(dao.getTzAppId());
500 std::string tzPkgId = DPL::ToUTF8String(dao.getTizenPkgId());
501 DPL::OptionalString installedPath = dao.getWidgetInstalledPath();
502 if (installedPath.IsNull()) {
503 appPath = std::string(GetUserInstalledWidgetPath()) + "/" +
504 tzPkgId + GetUserWidgetExecPath() + "/" + tzAppId;
506 appPath = DPL::ToUTF8String(*installedPath) +
507 GetUserWidgetExecPath() + "/" + tzAppId;
510 LogDebug("set_app_privilege(" << appPath << ")");
511 set_app_privilege(tzPkgId.c_str(), PRIVILEGE_APP_TYPE, appPath.c_str());
514 /* This type of message is received when widget is restarting
515 * (proably in other situation too). Widget restart can be
516 * called after system language change so language tags have to
518 * Do NOT MOVE LanguageTags reset before m_widgetHandle initialization
520 // reset language tags (create new tags based on system locales)
521 LanguageTagsProviderSingleton::Instance().resetLanguageTags();
522 DPL::OptionalString defaultLocale = dao.getDefaultlocale();
523 if (!defaultLocale.IsNull()) {
524 LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
528 LanguageTagsProviderSingleton::Instance().getLanguageTags();
529 LogDebug("Current widget locales (language tags):");
531 LogDebug("Locale: " << *it);
534 m_widgetType = dao.getWidgetType();
535 LogDebug("m_widgetType : " << m_widgetType.getApptypeToString() <<
536 "(m_widgetTizenId:" << m_widgetTizenId << ")");
538 LogDebug("Preload PluginLogicSingleton");
539 PluginModule::init(WrtDB::WidgetDAOReadOnly::getHandle(m_widgetTizenId));
540 LogDebug("Preload PluginLogicSingleton_end");
542 m_securityModelVersion = dao.getSecurityModelVersion();
543 #ifdef CORS_WHITELISTING_ENABLED
544 bypassCORSforWARPAccessList(dao);
546 m_initialized = true;
550 LogDebug("already initalized");
555 WKURLRequestRef Bundle::willSendRequestForFrameCallback(
556 WKBundlePageRef /*page*/,
557 WKBundleFrameRef /*frame*/,
558 uint64_t /*resourceIdentifier*/,
559 WKURLRequestRef request,
560 WKURLResponseRef /*response*/,
561 const void *clientInfo)
563 LogDebug("willSendRequestForFrameCallback called");
564 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
565 return This->willSendRequestForFrame(request);
568 void Bundle::didStartProvisionalLoadForFrameCallback(
569 WKBundlePageRef page,
570 WKBundleFrameRef frame,
571 WKTypeRef* /*userData*/,
572 const void *clientInfo)
574 LogDebug("didStartProvisionalLoadForFrameCallback called");
575 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
578 WrtDB::WidgetDAOReadOnly dao(This->m_widgetTizenId);
579 WrtDB::WindowModeList modeList = dao.getWindowModes();
580 FOREACH(it, modeList) {
581 std::string viewMode = DPL::ToUTF8String(*it);
582 if (viewMode == VIEWMODE_TYPE_FULLSCREEN
583 || viewMode == VIEWMODE_TYPE_MAXIMIZED)
585 WKBundlePageSetViewMode(
587 WKStringCreateWithUTF8CString(viewMode.c_str()));
592 if (This->m_pageGlobalContext.find(page) == This->m_pageGlobalContext.end()) {
595 if (This->m_pageContext.count(page) == 0) {
599 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
601 ContextSet::iterator i = This->m_pageContext[page].find(context);
603 if (i == This->m_pageContext[page].end()) {
604 LogDebug("Initially attached frame");
608 This->m_pageContext[page].erase(i);
609 This->m_willRemoveContext = context;
612 void Bundle::didRemoveFrameFromHierarchyCallback(
613 WKBundlePageRef page,
614 WKBundleFrameRef frame,
615 WKTypeRef* /*userData*/,
616 const void *clientInfo)
618 LogDebug("didRemoveFrameFromHierarchyCallback called");
619 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
621 if (This->m_pageContext.count(page) == 0) {
622 LogDebug("his->m_pageContext.count(page) == 0");
626 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
628 ContextSet::iterator i = This->m_pageContext[page].find(context);
630 if (i == This->m_pageContext[page].end()) {
631 LogWarning("Tried to unload frame which has never been loaded");
635 This->m_pageContext[page].erase(i);
637 PluginModule::unloadFrame(context);
640 void Bundle::didFinishLoadForResourceCallback(
641 WKBundlePageRef /*page*/,
642 WKBundleFrameRef /*frame*/,
643 uint64_t /*resourceIdentifier*/,
644 const void* /*clientInfo*/)
646 LogDebug("didFinishLoadForResourceCallback called");
649 void Bundle::didCommitLoadForFrameCallback(
650 WKBundlePageRef page,
651 WKBundleFrameRef frame,
652 WKTypeRef* /*userData*/,
653 const void *clientInfo)
655 LogInfo("didCommitLoadForFrameCallback called");
656 LOG_PROFILE_START("didCommitLoadForFrameCallback");
657 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
659 WKURLRef url = WKBundleFrameCopyURL(frame);
662 LogInfo("url is NULL");
666 if (This->m_willRemoveContext) {
667 PluginModule::unloadFrame(This->m_willRemoveContext);
668 This->m_willRemoveContext = NULL;
671 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
673 This->m_pageContext[page].insert(context);
675 if (!WKBundleFrameIsMainFrame(frame)) {
676 LogInfo("frame isn't main frame");
678 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
681 This->m_encodedBundle.c_str(),
682 This->m_theme.c_str());
683 PluginModule::loadFrame(context);
687 std::string urlStr = toString(url);
688 if (InjectedBundleURIHandling::processURIForPlugin(urlStr.c_str())) {
689 LogDebug("start plugin");
690 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
692 LogDebug("Previous context: " << This->m_pageGlobalContext.getContextForPage(page));
693 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
695 LogDebug("New context: " << context);
696 //note that since we need old context for unloading plugins it must be sotred
697 //custom container take care of increamenting and decrementing references
698 This->m_pageGlobalContext.insertContextForPage(page, context);
699 LOG_PROFILE_START("PluginModule start");
701 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
704 This->m_encodedBundle.c_str(),
705 This->m_theme.c_str() );
706 LOG_PROFILE_STOP("PluginModule start");
708 PluginModule::loadFrame(context);
710 LogDebug("stop plugin");
711 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
713 LogDebug("Previous context: " << This->m_pageGlobalContext.getContextForPage(page));
714 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
716 LogDebug("New context: " << context);
717 This->m_pageGlobalContext.insertContextForPage(page, context);
719 LOG_PROFILE_STOP("didCommitLoadForFrameCallback");
722 WKBundlePagePolicyAction Bundle::decidePolicyForNavigationActionCallback(
723 WKBundlePageRef page,
724 WKBundleFrameRef frame,
725 WKBundleNavigationActionRef navigationAction,
726 WKURLRequestRef request,
728 const void* clientInfo)
730 LogDebug("decidePolicyForNavigationActionCallback called");
732 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
733 return This->decidePolicyForAction(false,
741 WKBundlePagePolicyAction Bundle::decidePolicyForNewWindowActionCallback(
742 WKBundlePageRef page,
743 WKBundleFrameRef frame,
744 WKBundleNavigationActionRef navigationAction,
745 WKURLRequestRef request,
746 WKStringRef /*frameName*/,
748 const void* clientInfo)
750 LogDebug("decidePolicyForNewWindowActionCallback called");
752 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
753 return This->decidePolicyForAction(true,
761 WKBundlePagePolicyAction Bundle::decidePolicyForResponseCallback(
762 WKBundlePageRef /* page */,
763 WKBundleFrameRef /* frame */,
764 WKURLResponseRef response,
765 WKURLRequestRef /* request */,
766 WKTypeRef* /* userData */,
767 const void* /* clientInfo */)
769 LogDebug("decidePolicyForResponseCallback called");
772 WKStringRef contentTypeRef = WKURLResponseEflCopyContentType(response);
774 std::string contentType = toString(contentTypeRef);
775 LogDebug("contentTypeRef : " << contentType);
776 WKRelease(contentTypeRef);
778 if (contentType == HTML_MIME) {
779 LogDebug("Accepting HTML_MIME type");
780 return WKBundlePagePolicyActionUse;
782 if (contentType == PHP_MIME) {
783 LogDebug("Accepting php type");
784 return WKBundlePagePolicyActionUse;
787 return WKBundlePagePolicyActionPassThrough;
790 WKURLRequestRef Bundle::willSendRequestForFrame(WKURLRequestRef request)
792 LogDebug("willSendReq got " << toString(request).c_str());
793 WKURLRef url = WKURLRequestCopyURL(request);
794 WKStringRef urlStr = WKURLCopyString(url);
796 DPL::String dplurl = DPL::FromUTF8String(toString(urlStr));
799 DPL::Optional<DPL::String> localizedUrl =
800 InjectedBundleURIHandling::localizeURI(dplurl, m_widgetTizenId);
802 InjectedBundleURIHandling::processURI(*localizedUrl,
804 m_securityModelVersion);
807 LogDebug("Not permitted resource: " << *localizedUrl);
811 LogDebug("URI processing result: " << *localizedUrl);
812 std::string tmpUrlStr = DPL::ToUTF8String(*localizedUrl);
813 WKURLRef tmpUrl = WKURLCreateWithUTF8CString(tmpUrlStr.c_str());
814 std::string scheme = toString(WKURLCopyScheme(url)); //scheme of original request
817 #ifdef APP_SCHEME_ENABLED
818 if(scheme == SCHEME_FILE) {
819 LogError("File schema blocked for: " << dplurl);
824 // Return value must contain details information of input
825 // WKURLRequestRef. Current webkit2 doesn't support api that
826 // copy WKURLRequestRef or change url only. Before webkit2
827 // support api, callback return original WKURLRequestRef in the
828 // case of external scheme
830 // external scheme also need to send message to UI process for
831 // checking roaming and security
832 if (scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS) {
833 LogDebug("external scheme return original WKURLRequestRef");
838 std::string checkUrl = toString(tmpUrl);
842 if (isEncryptedResource(checkUrl, getFileSize)) {
843 std::string decryptString = DecryptResource(checkUrl,
845 if (!decryptString.empty()) {
846 std::string destString = DATA_STRING;
848 std::string mimeString =
850 MimeTypeUtils::identifyFileMimeType(
851 DPL::FromUTF8String(checkUrl)));
853 destString += mimeString;
854 destString += BASE64_STRING;
856 decryptString.insert(0, destString);
859 WKURLCreateWithUTF8CString(decryptString.c_str());
861 WKURLRequestRef req = WKURLRequestCreateWithWKURL(
864 LogDebug("return value " << decryptString << "]]");
869 WKURLRequestRef req = WKURLRequestCreateWithWKURL(tmpUrl);
871 LogDebug("return value " << toString(req).c_str());
876 WKBundlePagePolicyAction Bundle::decidePolicyForAction(
878 WKBundlePageRef /* page */,
879 WKBundleFrameRef frame,
880 WKBundleNavigationActionRef /* navigationAction */,
881 WKURLRequestRef request,
882 WKTypeRef* /* userData */)
884 using namespace ViewModule;
885 using namespace ViewModule::SchemeActionMap;
887 char const * const TIZEN_SCHEME = "tizen";
889 std::string request_uri = toString(request);
891 LogInfo("Uri being checked: " << request_uri);
894 if (request_uri == BLANK_PAGE_URL) {
895 return WKBundlePagePolicyActionUse;
898 // in case of box scheme, unconditionally PassThrough should be returned
899 if (!request_uri.compare(0, 6, SCHEME_BOX_SLASH)) {
900 return WKBundlePagePolicyActionPassThrough;
903 DPL::String dplUrl = DPL::FromUTF8String(request_uri);
905 InjectedBundleURIHandling::processMainResource(dplUrl,
907 m_securityModelVersion);
909 std::string blockedUrl = DPL::ToUTF8String(dplUrl);
910 LogDebug("URI is blocked: " << blockedUrl);
912 // Send information about blocked URI to UIProcess
913 WKStringRef urlStr = WKStringCreateWithUTF8CString(blockedUrl.c_str());
914 WKTypeRef retVal = NULL;
915 WKStringRef blockMessage = WKStringCreateWithUTF8CString(uriBlockedMessageName);
916 WKBundlePostSynchronousMessage(m_bundle, blockMessage, urlStr, &retVal);
919 WKRelease(blockMessage);
920 return WKBundlePagePolicyActionPassThrough;
924 std::string request_scheme = getScheme(request_uri);
927 if (request_scheme == TIZEN_SCHEME) {
928 return WKBundlePagePolicyActionPassThrough;
932 Scheme scheme(request_scheme);
933 LogDebug("Scheme: " << request_scheme);
935 Scheme::Type type = scheme.GetType();
936 if (type < Scheme::FILE || type >= Scheme::COUNT) {
937 LogError("Invalid scheme: " << request_scheme);
938 return WKBundlePagePolicyActionPassThrough;
941 bool mainFrame = WKBundleFrameIsMainFrame(frame);
942 NavigationContext ctx = mainFrame ? TOP_LEVEL : FRAME_LEVEL;
947 LogDebug("Scheme type: " << type);
948 LogDebug("Navigation context: " << ctx);
949 LogDebug("Application type: " << m_widgetType.getApptypeToString());
953 if (m_widgetType == WrtDB::APP_TYPE_TIZENWEBAPP) {
954 action = g_tizenActionMap[type][ctx];
956 LogError("Unsupported application type: " << type);
957 return WKBundlePagePolicyActionPassThrough;
960 LogDebug("Uri action: " << action);
962 if (action != URI_ACTION_WRT) {
963 return WKBundlePagePolicyActionPassThrough;
966 return WKBundlePagePolicyActionUse;
969 std::string Bundle::toString(WKStringRef str)
971 if (WKStringIsEmpty(str)) {
972 return std::string();
974 size_t size = WKStringGetMaximumUTF8CStringSize(str);
975 char buffer[size + 1];
976 WKStringGetUTF8CString(str, buffer, size + 1);
980 std::string Bundle::toString(WKURLRef url)
982 WKStringRef urlStr = WKURLCopyString(url);
983 std::string str = toString(urlStr);
988 std::string Bundle::toString(WKURLRequestRef req)
990 WKURLRef reqUrl = WKURLRequestCopyURL(req);
991 std::string str = toString(reqUrl);
996 std::string Bundle::toString(WKErrorRef err)
998 WKStringRef domErr = WKErrorCopyDomain(err);
999 WKStringRef desc = WKErrorCopyLocalizedDescription(err);
1000 std::string str = toString(domErr) + "\n" + toString(desc);
1006 std::string Bundle::getScheme(std::string uri)
1008 std::size_t found = uri.find(':');
1011 if (found != std::string::npos) {
1012 str = uri.substr(0, found);
1018 bool Bundle::isEncryptedResource(std::string Url, int &size)
1020 if (m_encryptedFiles.empty()) {
1021 WrtDB::WidgetDAOReadOnly(m_widgetTizenId).
1022 getEncryptedFileList(m_encryptedFiles);
1025 std::set<WrtDB::EncryptedFileInfo>::iterator it;
1026 WrtDB::EncryptedFileInfo info;
1027 std::string filePath;
1029 if (0 != strncmp(Url.c_str(), SCHEME_FILE_SLASH, strlen(SCHEME_FILE_SLASH))) {
1033 filePath = Url.substr(strlen(SCHEME_FILE_SLASH));
1034 info.fileName = DPL::FromUTF8String(filePath);
1036 if (m_encryptedFiles.end() != (it = m_encryptedFiles.find(info)))
1038 LogDebug(" info file name : " << it->fileName);
1039 LogDebug(" info file size : " << it->fileSize);
1040 size = it->fileSize;
1046 std::string Bundle::DecryptResource(std::string resource, int size)
1049 std::string filePath;
1051 size_t pos = resource.find_first_not_of(SCHEME_FILE_SLASH);
1052 if (std::string::npos != pos) {
1053 filePath = resource.substr(pos - 1);
1057 if (0 == stat(filePath.c_str(), &buf)) {
1058 const std::size_t fileSize = buf.st_size;
1059 std::unique_ptr<unsigned char[]> inChunk;
1061 FILE* fp = fopen(filePath.c_str(), "rb");
1063 LogDebug("Couldnot open file : " << filePath);
1064 return std::string();
1067 std::unique_ptr<unsigned char[]> DecryptedString(new unsigned
1069 std::string pkgid(DPL::ToUTF8String(m_widgetTizenId));
1071 using namespace Tizen::Base;
1072 const byte *b_pkgid = reinterpret_cast<const byte*>(pkgid.c_str());
1074 appInfo.Construct(pkgid.length());
1075 if (appInfo.SetArray(b_pkgid, 0, pkgid.length()) != E_SUCCESS) {
1076 LogDebug("Couldnot set appInfo");
1078 return std::string();
1084 unsigned char getDecSize[4];
1085 memset(getDecSize, 0x00, sizeof(getDecSize));
1087 size_t readSize = fread(getDecSize, sizeof(unsigned char),
1088 sizeof(getDecSize), fp);
1089 if (0 != readSize) {
1090 int readBufSize = 0;
1091 std::istringstream(std::string((char*)getDecSize)) >> readBufSize;
1092 inChunk.reset(new unsigned char[readBufSize]);
1094 size_t decReadSize = fread(inChunk.get(), sizeof(unsigned char),
1096 if (0 != decReadSize) {
1097 ByteBuffer *getBuffer =
1098 DecryptChunkByTrustZone(&appInfo, inChunk.get(),
1100 memcpy(DecryptedString.get() + writeCount,
1101 getBuffer->GetPointer(), getBuffer->GetRemaining());
1102 writeCount += getBuffer->GetRemaining();
1107 } while( 0 == std::feof(fp));
1110 memset(DecryptedString.get() + size, '\n', fileSize - size);
1111 LogDebug("resource need to encoding base64");
1115 b64 = BIO_new(BIO_f_base64());
1116 bmem = BIO_new(BIO_s_mem());
1117 b64 = BIO_push(b64, bmem);
1118 BIO_write(b64, DecryptedString.get(), fileSize);
1120 BIO_get_mem_ptr(b64, &bptr);
1122 std::string base64Enc((char *)bptr->data, bptr->length - 1);
1128 return std::string();
1131 #ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE
1132 void Bundle::sendWebProcessPid()
1134 std::stringstream strPid;
1136 WKStringRef pidStr = WKStringCreateWithUTF8CString(strPid.str().c_str());
1137 WKTypeRef retVal = NULL;
1138 WKStringRef message = WKStringCreateWithUTF8CString(webProcessPidMessageName);
1139 WKBundlePostSynchronousMessage(m_bundle, message, pidStr, &retVal);
1149 void WKBundleInitialize(WKBundleRef bundle,
1152 DPL::Log::LogSystemSingleton::Instance().SetTag("WRT-BUNDLE");
1153 LogDebug("Bundle initialized");
1155 DPL::Event::GetMainEventDispatcherInstance().ResetCrossEventCallHandler();
1156 LogDebug("ResetCrossEventCallHandler()");
1158 static Bundle s_bundle(bundle);
1160 WKBundleClient client = {
1161 kWKBundleClientCurrentVersion,
1163 &Bundle::didCreatePageCallback,
1164 &Bundle::willDestroyPageCallback,
1165 0, /* didInitializePageGroup */
1166 &Bundle::didReceiveMessageCallback
1168 WKBundleSetClient(bundle, &client);
1170 // process pool - restore process priority
1171 if (UID_ROOT == getuid())
1173 setpriority(PRIO_PROCESS, 0, DEFAULT_PRIORITY);