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>
40 #include <openssl/sha.h>
41 #include <openssl/hmac.h>
42 #include <openssl/evp.h>
43 #include <openssl/bio.h>
44 #include <openssl/buffer.h>
46 #include <dpl/log/log.h>
47 #include <dpl/foreach.h>
48 #include <dpl/assert.h>
49 #include <dpl/wrt-dao-ro/WrtDatabase.h>
50 #include <dpl/localization/localization_utils.h>
51 #include <dpl/string.h>
52 #include <dpl/wrt-dao-ro/global_config.h>
53 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
54 #include <dpl/utils/mime_type_utils.h>
55 #include <dpl/localization/LanguageTagsProvider.h>
56 #include <dpl/event/main_event_dispatcher.h>
57 #include <FBaseByteBuffer.h>
58 #include <security/FSecCrypto_TrustZoneService.h>
60 #include <wrt_plugin_module.h>
61 #include <profiling_util.h>
64 #include <appcore-efl.h>
66 #include "messages_names.h"
69 #include <scheme_action_map_type.h>
70 #include <scheme_action_map_data.h>
72 #include <js_overlay_types.h>
75 #include <sys/resource.h>
76 #include <privilege-control.h>
78 // URI localization on WebProcess side
79 #include "bundle_uri_handling.h"
81 void InitWebAppInfo(const char* appId, const char* rootPath);
85 const char * const uriChangedMessageName = "uri_changed_msg";
86 const char * const uriBlockedMessageName = "uri_blocked_msg";
87 const char * const URICHANGE_PLUGIN_STOP_ONLY = "plugin_stop_only";
88 const char * const URICHANGE_PLUGIN_RESTART = "plugin_restart";
89 const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
90 const char * const URICHANGE_BLOCKED_URL = "null";
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 DATA_STRING = "data:";
95 const char * const BASE64_STRING = ";base64,";
96 const char * const BLANK_PAGE_URL = "about:blank";
97 const char * const HTML_MIME = "text/html";
98 const char * const PHP_MIME = "application/x-php";
99 const char * const VIEWMODE_TYPE_FULLSCREEN = "fullscreen";
100 const char * const VIEWMODE_TYPE_MAXIMIZED = "maximized";
101 const std::size_t FILE_BUF_MAX_SIZE = 1024; // bytes
102 const std::size_t PLAIN_CHUNK_SIZE = 1008; // bytes
103 const unsigned int UID_ROOT = 0;
104 const unsigned int DEFAULT_PRIORITY = 0;
105 const char * const PRIVILEGE_APP_TYPE = "wgt";
107 static bool m_initWebApp = false;
109 Tizen::Base::ByteBuffer *DecryptChunkByTrustZone(
110 Tizen::Base::ByteBuffer *appInfo,
111 const unsigned char *inBuffer,
114 using namespace Tizen::Base;
118 pAppId = (char*)calloc(appInfo->GetRemaining()+1, 1);
119 memcpy(pAppId, appInfo->GetPointer(), appInfo->GetRemaining());
121 InitWebAppInfo(pAppId, "");
126 Tizen::Security::Crypto::_TrustZoneService* pInstance;
127 pInstance = Tizen::Security::Crypto::_TrustZoneService::GetInstance();
130 pBuf.Construct(inBufSize);
131 const byte *pByte = reinterpret_cast<const byte*>(inBuffer);
132 pBuf.SetArray(pByte, 0, inBufSize);
135 ByteBuffer *getBuffer = pInstance->_TrustZoneService::DecryptN(*appInfo, pBuf);
140 Bundle::Bundle(WKBundleRef bundle) :
145 m_willRemoveContext(NULL),
147 m_widgetType(WrtDB::APP_TYPE_UNKNOWN),
150 LOG_PROFILE_START("Bundle attachToThread");
151 WrtDB::WrtDatabase::attachToThreadRO();
152 m_uriChangedMessage = WKStringCreateWithUTF8CString(uriChangedMessageName);
153 LOG_PROFILE_STOP("Bundle attachToThread");
158 WrtDB::WrtDatabase::detachFromThread();
160 if (!m_pagesList.empty()) {
161 LogError("There are not closed pages!");
164 WKRelease(m_uriChangedMessage);
168 void Bundle::didCreatePageCallback(
169 WKBundleRef /*bundle*/,
170 WKBundlePageRef page,
171 const void* clientInfo)
173 LOG_PROFILE_START("didCreatePageCallback");
174 LogDebug("didCreatePageCallback called");
175 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
176 This->didCreatePage(page);
177 LOG_PROFILE_STOP("didCreatePageCallback");
180 void Bundle::didReceiveMessageCallback(
181 WKBundleRef /*bundle*/,
182 WKStringRef messageName,
183 WKTypeRef messageBody,
184 const void *clientInfo)
186 LogDebug("didReceiveMessageCallback called");
187 Bundle* bundle = static_cast<Bundle*>(const_cast<void*>(clientInfo));
188 bundle->didReceiveMessage(messageName, messageBody);
191 void Bundle::willDestroyPageCallback(
192 WKBundleRef /*bundle*/,
193 WKBundlePageRef page,
194 const void* clientInfo)
196 LogDebug("willDestroyPageCallback called");
197 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
198 This->willDestroyPage(page);
201 void Bundle::didCreatePage(WKBundlePageRef page)
203 auto mainFrame = WKBundlePageGetMainFrame(page);
204 auto context = WKBundleFrameGetJavaScriptContext(mainFrame);
205 m_pagesList.push_back(page);
206 m_pageGlobalContext.insertContextForPage(page, context);
207 LogDebug("created Page : " << page << " created JSContext : " << context);
209 WKBundlePageResourceLoadClient resourceLoadClient = {
210 kWKBundlePageResourceLoadClientCurrentVersion, /* version */
211 this, /* clientinfo */
212 0, /* didInitiateLoadForResource */
213 willSendRequestForFrameCallback, /* willSendRequestForFrame */
214 0, /* didReceiveResponseForResource */
215 0, /* didReceiveContentLengthForResource */
216 didFinishLoadForResourceCallback, /* didFinishLoadForResource */
217 0, /* didFailLoadForResource */
218 0, /* shouldCacheResponse */
219 0, /* shouldUseCredentialStorage */
221 WKBundlePageSetResourceLoadClient(page, &resourceLoadClient);
223 WKBundlePageLoaderClient loaderClient = {
224 kWKBundlePageLoaderClientCurrentVersion,
225 this, /* clientinfo */
226 didStartProvisionalLoadForFrameCallback, /* didStartProvisionalLoadForFrame */
227 0, /* didReceiveServerRedirectForProvisionalLoadForFrame */
228 0, /* didFailProvisionalLoadWithErrorForFrame */
229 didCommitLoadForFrameCallback, /* didCommitLoadForFrame */
230 0, /* didFinishDocumentLoadForFrame */
231 0, /* didFinishLoadForFrame */
232 0, /* didFailLoadWithErrorForFrame */
233 0, /* didSameDocumentNavigationForFrame */
234 0, /* didReceiveTitleForFrame */
235 0, /* didFirstLayoutForFrame */
236 0, /* didFirstVisuallyNonEmptyLayoutForFrame */
237 didRemoveFrameFromHierarchyCallback, /* didRemoveFrameFromHierarchy */
238 0, /* didDisplayInsecureContentForFrame */
239 0, /* didRunInsecureContentForFrame */
240 0, /* didClearWindowObjectForFrame */
241 0, /* didCancelClientRedirectForFrame */
242 0, /* willPerformClientRedirectForFrame */
243 0, /* didHandleOnloadEventsForFrame */
244 0, /* didLayoutForFrame */
245 0, /* didNewFirstVisuallyNonEmptyLayout */
246 0, /* didDetectXSSForFrame */
247 0, /* shouldGoToBackForwardListItem */
248 0, /* globalObjectIsAvailableForFrame */
249 0, /* willDisconnectDOMWindowExtensionFromGlobalObject */
250 0, /* didReconnectDOMWindowExtensionToGlobalObject */
251 0, /* willDestroyGlobalObjectForDOMWindowExtension */
252 0, /* didFinishProgress */
253 0, /* shouldForceUniversalAccessFromLocalURL */
254 0, /* didReceiveIntentForFrame */
255 0, /* registerIntentServiceForFrame */
257 WKBundlePageSetPageLoaderClient(page, &loaderClient);
260 WKBundlePagePolicyClient policyClient = {
261 kWKBundlePagePolicyClientCurrentVersion, /* version */
262 this, /* clientInfo */
263 pageDecidePolicyForNavigationActionCallback, /**/
264 0, /* decidePolicyForNewWindowAction */
265 pageDecidePolicyForResponseCallback, /* decidePolicyForResponse */
266 0, /* unableToImplementPolicy */
268 WKBundlePageSetPolicyClient(page, &policyClient);
271 void Bundle::willDestroyPage(WKBundlePageRef page)
273 LogDebug("Destroyed page : " << page);
275 auto context = m_pageGlobalContext.getContextForPage(page);
276 m_pagesList.remove(page);
277 m_pageGlobalContext.removeContextForPage(page);
278 m_pageContext[page].erase(context);
280 PluginModule::unloadFrame(context);
281 PluginModule::stop(context);
284 void Bundle::fixWKMessageArgs(std::string & argScale,
285 std::string & argEncodedBundle,
286 std::string & argTheme)
288 if (argScale != "null" && argScale[0] == '_') {
289 argScale.erase(0, 1);
291 std::stringstream ssScale(argScale);
295 if (argEncodedBundle != "null" && argEncodedBundle[0] == '_') {
296 argEncodedBundle.erase(0, 1);
298 m_encodedBundle = argEncodedBundle;
301 if (argTheme != "null" && argTheme[0] == '_') {
302 argTheme.erase(0, 1);
308 void Bundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
310 LogDebug("got message type: " << toString(messageName).c_str());
311 if (WKStringIsEqualToUTF8CString(messageName,
312 BundleMessages::START))
314 if (!messageBody || WKStringGetTypeID() != WKGetTypeID(messageBody)) {
315 LogError("Wrong message format received, ignoring");
319 auto msgString = toString(static_cast<WKStringRef>(messageBody));
320 LogDebug("Got message text: " << msgString);
321 LogDebug("loading Page : " << m_pagesList.back() <<
322 " loading JSContext : " <<
323 m_pageGlobalContext.getContextForPage(m_pagesList.back()));
324 // set information from ui process
325 std::stringstream ssMsg(msgString);
326 std::string argScale;
327 std::string argEncodedBundle;
328 std::string argTheme;
332 m_widgetTizenId = DPL::FromASCIIString(id);
335 ssMsg >> argEncodedBundle;
337 ssMsg >> m_encrypted;
339 // ** Language tags setting completed **
340 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
341 } else if (WKStringIsEqualToUTF8CString(messageName,
342 BundleMessages::SHUTDOWN))
344 LogDebug("shutdown plugins");
346 if (m_pagesList.empty()) {
347 PluginModule::shutdown();
350 "PluginModule shutdown ignored, there are still alive pages!");
353 else if (WKStringIsEqualToUTF8CString(messageName,
354 BundleMessages::SET_CUSTOM_PROPERTIES))
356 LogDebug("reset custom properties of window objects");
357 // set information from ui process
358 auto msgString = toString(static_cast<WKStringRef>(messageBody));
360 std::string argScale;
361 std::string argEncodedBundle;
362 std::string argTheme;
364 std::stringstream ssMsg(msgString);
366 ssMsg >> argEncodedBundle;
369 fixWKMessageArgs(argScale, argEncodedBundle, argTheme);
371 //apply for each context
372 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
373 for (; it != m_pageGlobalContext.end(); ++it) {
374 PluginModule::setCustomProperties(it->second,
376 m_encodedBundle.c_str(),
379 } else if (WKStringIsEqualToUTF8CString(
381 BundleMessages::DISPATCH_JAVASCRIPT_EVENT))
383 LogDebug("dispatch javascript event to created frames");
384 // set information from ui process
385 auto text = toString(static_cast<WKStringRef>(messageBody));
388 std::stringstream ss(text);
391 using namespace WrtPlugins::W3C;
392 // set arguments to be sent to js handler of this custom event
393 if (eventType == SoftKeyboardChangeCustomEvent) {
394 args = new SoftKeyboardChangeArgs;
395 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->state;
396 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->width;
397 ss >> static_cast<SoftKeyboardChangeArgs *>(args)->height;
400 //apply for each context
401 PageGlobalContextContainer::const_iterator it = m_pageGlobalContext.begin();
402 for (; it != m_pageGlobalContext.end(); ++it) {
403 PluginModule::dispatchJavaScriptEvent(
405 static_cast<WrtPlugins::W3C::CustomEventType>(eventType),
410 delete static_cast<SoftKeyboardChangeArgs *>(args);
412 } else if (WKStringIsEqualToUTF8CString(
414 BundleMessages::INIT))
416 LogDebug("initializing plugins");
420 auto msgString = toString(static_cast<WKStringRef>(messageBody));
422 m_widgetTizenId = DPL::FromASCIIString(msgString);
424 WrtDB::WidgetDAOReadOnly dao(m_widgetTizenId);
426 // process pool - set app_privilige
427 if (UID_ROOT == getuid())
429 using namespace WrtDB::GlobalConfig;
432 std::string tzAppId = DPL::ToUTF8String(dao.getTzAppId());
433 std::string tzPkgId = DPL::ToUTF8String(dao.getTizenPkgId());
435 appPath = appPath + GetUserInstalledWidgetPath() + "/" +
436 tzPkgId + GetUserWidgetExecPath() + "/" + tzAppId;
438 LogDebug("set_app_privilege(" << appPath << ")");
439 set_app_privilege(tzPkgId.c_str(), PRIVILEGE_APP_TYPE, appPath.c_str());
442 /* This type of message is received when widget is restarting
443 * (proably in other situation too). Widget restart can be
444 * called after system language change so language tags have to
446 * Do NOT MOVE LanguageTags reset before m_widgetHandle initialization
448 // reset language tags (create new tags based on system locales)
449 LanguageTagsProviderSingleton::Instance().resetLanguageTags();
450 DPL::OptionalString defaultLocale = dao.getDefaultlocale();
451 if (!defaultLocale.IsNull()) {
452 LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
456 LanguageTagsProviderSingleton::Instance().getLanguageTags();
457 LogDebug("Current widget locales (language tags):");
459 LogDebug("Locale: " << *it);
462 m_widgetType = dao.getWidgetType();
463 LogDebug("m_widgetType : " << m_widgetType.getApptypeToString() <<
464 "(m_widgetTizenId:" << m_widgetTizenId << ")");
466 LogDebug("Preload PluginLogicSingleton");
467 PluginModule::init(WrtDB::WidgetDAOReadOnly::getHandle(m_widgetTizenId));
468 LogDebug("Preload PluginLogicSingleton_end");
470 m_initialized = true;
474 LogDebug("already initalized");
479 WKURLRequestRef Bundle::willSendRequestForFrameCallback(
480 WKBundlePageRef /*page*/,
481 WKBundleFrameRef /*frame*/,
482 uint64_t /*resourceIdentifier*/,
483 WKURLRequestRef request,
484 WKURLResponseRef /*response*/,
485 const void *clientInfo)
487 LogDebug("willSendRequestForFrameCallback called");
488 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
489 return This->willSendRequestForFrame(request);
492 void Bundle::didStartProvisionalLoadForFrameCallback(
493 WKBundlePageRef page,
494 WKBundleFrameRef frame,
495 WKTypeRef* /*userData*/,
496 const void *clientInfo)
498 LogDebug("didStartProvisionalLoadForFrameCallback called");
499 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
502 WrtDB::WidgetDAOReadOnly dao(This->m_widgetTizenId);
503 WrtDB::WindowModeList modeList = dao.getWindowModes();
504 FOREACH(it, modeList) {
505 std::string viewMode = DPL::ToUTF8String(*it);
506 if (viewMode == VIEWMODE_TYPE_FULLSCREEN
507 || viewMode == VIEWMODE_TYPE_MAXIMIZED)
509 WKBundlePageSetViewMode(
511 WKStringCreateWithUTF8CString(viewMode.c_str()));
516 if (This->m_pageGlobalContext.find(page) == This->m_pageGlobalContext.end()) {
519 if (This->m_pageContext.count(page) == 0) {
523 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
525 ContextSet::iterator i = This->m_pageContext[page].find(context);
527 if (i == This->m_pageContext[page].end()) {
528 LogDebug("Initially attached frame");
532 This->m_pageContext[page].erase(i);
533 This->m_willRemoveContext = context;
536 void Bundle::didRemoveFrameFromHierarchyCallback(
537 WKBundlePageRef page,
538 WKBundleFrameRef frame,
539 WKTypeRef* /*userData*/,
540 const void *clientInfo)
542 LogDebug("didRemoveFrameFromHierarchyCallback called");
543 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
545 if (This->m_pageContext.count(page) == 0) {
546 LogDebug("his->m_pageContext.count(page) == 0");
550 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
552 ContextSet::iterator i = This->m_pageContext[page].find(context);
554 if (i == This->m_pageContext[page].end()) {
555 LogWarning("Tried to unload frame which has never been loaded");
559 This->m_pageContext[page].erase(i);
561 PluginModule::unloadFrame(context);
564 void Bundle::didFinishLoadForResourceCallback(
565 WKBundlePageRef /*page*/,
566 WKBundleFrameRef /*frame*/,
567 uint64_t /*resourceIdentifier*/,
568 const void* /*clientInfo*/)
570 LogDebug("didFinishLoadForResourceCallback called");
573 void Bundle::didCommitLoadForFrameCallback(
574 WKBundlePageRef page,
575 WKBundleFrameRef frame,
576 WKTypeRef* /*userData*/,
577 const void *clientInfo)
579 LogInfo("didCommitLoadForFrameCallback called");
580 LOG_PROFILE_START("didCommitLoadForFrameCallback");
581 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
583 WKURLRef url = WKBundleFrameCopyURL(frame);
584 WKTypeRef retVal = NULL;
587 LogInfo("url is NULL");
591 if (This->m_willRemoveContext) {
592 PluginModule::unloadFrame(This->m_willRemoveContext);
593 This->m_willRemoveContext = NULL;
596 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
598 This->m_pageContext[page].insert(context);
600 if (!WKBundleFrameIsMainFrame(frame)) {
601 LogInfo("frame isn't main frame");
603 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
606 This->m_encodedBundle.c_str(),
607 This->m_theme.c_str());
608 PluginModule::loadFrame(context);
612 std::string scheme = getScheme(toString(url));
613 std::string result = URICHANGE_PLUGIN_RESTART;
615 if (scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS) {
616 WKStringRef urlStr = WKURLCopyString(url);
617 WKBundlePostSynchronousMessage(This->m_bundle,
618 This->m_uriChangedMessage,
624 result = toString(static_cast<WKStringRef>(retVal));
626 LogInfo("result from UI process : " << result);
628 if (result == URICHANGE_PLUGIN_STOP_ONLY) {
629 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
631 LogDebug("Previous context: " << This->m_pageGlobalContext.getContextForPage(page));
632 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
634 LogDebug("New context: " << context);
635 This->m_pageGlobalContext.insertContextForPage(page, context);
636 } else if (result == URICHANGE_PLUGIN_RESTART) {
637 if(This->m_pageGlobalContext.find(page) != This->m_pageGlobalContext.end())
639 LogDebug("Previous context: " << This->m_pageGlobalContext.getContextForPage(page));
640 PluginModule::stop(This->m_pageGlobalContext.getContextForPage(page));
642 LogDebug("New context: " << context);
643 //note that since we need old context for unloading plugins it must be sotred
644 //custom container take care of increamenting and decrementing references
645 This->m_pageGlobalContext.insertContextForPage(page, context);
646 LOG_PROFILE_START("PluginModule start");
648 WrtDB::WidgetDAOReadOnly::getHandle(This->m_widgetTizenId),
651 This->m_encodedBundle.c_str(),
652 This->m_theme.c_str() );
653 LOG_PROFILE_STOP("PluginModule start");
655 PluginModule::loadFrame(context);
657 LOG_PROFILE_STOP("didCommitLoadForFrameCallback");
660 WKBundlePagePolicyAction Bundle::pageDecidePolicyForNavigationActionCallback(
661 WKBundlePageRef page,
662 WKBundleFrameRef frame,
663 WKBundleNavigationActionRef navigationAction,
664 WKURLRequestRef request,
666 const void* clientInfo)
668 LogDebug("pageDecidePolicyForNavigationActionCallback called");
670 Bundle* This = static_cast<Bundle*>(const_cast<void*>(clientInfo));
672 return This->pageDecidePolicyForNavigationAction(page,
679 WKBundlePagePolicyAction Bundle::pageDecidePolicyForResponseCallback(
680 WKBundlePageRef /* page */,
681 WKBundleFrameRef /* frame */,
682 WKURLResponseRef response,
683 WKURLRequestRef /* request */,
684 WKTypeRef* /* userData */,
685 const void* /* clientInfo */)
687 LogDebug("pageDecidePolicyForResponseCallback called");
690 WKStringRef contentTypeRef = WKURLResponseEflCopyContentType(response);
692 std::string contentType = toString(contentTypeRef);
693 LogDebug("contentTypeRef : " << contentType);
694 WKRelease(contentTypeRef);
696 if (contentType == HTML_MIME) {
697 LogDebug("Accepting HTML_MIME type");
698 return WKBundlePagePolicyActionUse;
700 if (contentType == PHP_MIME) {
701 LogDebug("Accepting php type");
702 return WKBundlePagePolicyActionUse;
705 return WKBundlePagePolicyActionPassThrough;
708 WKURLRequestRef Bundle::willSendRequestForFrame(WKURLRequestRef request)
710 LogDebug("willSendReq got " << toString(request).c_str());
711 WKURLRef url = WKURLRequestCopyURL(request);
712 WKStringRef urlStr = WKURLCopyString(url);
714 bool is_xhr = true; // Webkit should inform if it's XHR
715 DPL::String dplurl = DPL::FromUTF8String(toString(urlStr));
718 DPL::Optional<DPL::String> localizedUrl =
719 BundleURIHandling::localizeURI(dplurl, m_widgetTizenId);
720 bool ret = BundleURIHandling::processURI(
727 LogDebug("Not permitted resource: " << *localizedUrl);
731 LogDebug("URI processing result: " << *localizedUrl);
732 std::string tmpUrlStr = DPL::ToUTF8String(*localizedUrl);
733 WKURLRef tmpUrl = WKURLCreateWithUTF8CString(tmpUrlStr.c_str());
734 std::string scheme = toString(WKURLCopyScheme(url));
736 // Return value must contain details information of input
737 // WKURLRequestRef. Current webkit2 doesn't support api that
738 // copy WKURLRequestRef or change url only. Before webkit2
739 // support api, callback return original WKURLRequestRef in the
740 // case of external scheme
742 // external scheme also need to send message to UI process for
743 // checking roaming and security
744 if (scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS) {
745 LogDebug("external scheme return original WKURLRequestRef");
750 std::string checkUrl = toString(tmpUrl);
754 if (isEncryptedResource(checkUrl, getFileSize)) {
755 std::string decryptString = DecryptResource(checkUrl,
757 if (!decryptString.empty()) {
758 std::string destString = DATA_STRING;
760 std::string mimeString =
762 MimeTypeUtils::identifyFileMimeType(
763 DPL::FromUTF8String(checkUrl)));
765 destString += mimeString;
766 destString += BASE64_STRING;
768 decryptString.insert(0, destString);
771 WKURLCreateWithUTF8CString(decryptString.c_str());
773 WKURLRequestRef req = WKURLRequestCreateWithWKURL(
776 LogDebug("return value " << decryptString << "]]");
781 WKURLRequestRef req = WKURLRequestCreateWithWKURL(tmpUrl);
783 LogDebug("return value " << toString(req).c_str());
788 WKBundlePagePolicyAction Bundle::pageDecidePolicyForNavigationAction(
789 WKBundlePageRef /* page */,
790 WKBundleFrameRef frame,
791 WKBundleNavigationActionRef /* navigationAction */,
792 WKURLRequestRef request,
793 WKTypeRef* /* userData */)
795 using namespace ViewModule;
796 using namespace ViewModule::SchemeActionMap;
798 char const * const TIZEN_SCHEME = "tizen";
800 std::string request_uri = toString(request);
802 LogInfo("Uri being checked: " << request_uri);
805 if (request_uri == BLANK_PAGE_URL) {
806 return WKBundlePagePolicyActionUse;
810 DPL::String dplUrl = DPL::FromUTF8String(request_uri);
811 DPL::Optional<DPL::String> localizedUrl =
812 BundleURIHandling::localizeURI(dplUrl, m_widgetTizenId);
813 bool ret = BundleURIHandling::processURI(
814 *localizedUrl, true, m_widgetTizenId, m_bundle);
816 std::string blockedUrl = DPL::ToUTF8String(*localizedUrl);
817 LogDebug("URI is blocked: " << blockedUrl);
819 // Send information about blocked URI to UIProcess
820 WKStringRef urlStr = WKStringCreateWithUTF8CString(blockedUrl.c_str());
821 WKTypeRef retVal = NULL;
822 WKStringRef blockMessage = WKStringCreateWithUTF8CString(uriBlockedMessageName);
823 WKBundlePostSynchronousMessage(m_bundle, blockMessage, urlStr, &retVal);
826 WKRelease(blockMessage);
827 return WKBundlePagePolicyActionPassThrough;
831 std::string request_scheme = getScheme(request_uri);
834 if (request_scheme == TIZEN_SCHEME) {
835 return WKBundlePagePolicyActionPassThrough;
839 Scheme scheme(request_scheme);
840 LogDebug("Scheme: " << request_scheme);
842 Scheme::Type type = scheme.GetType();
843 if (type < Scheme::FILE || type >= Scheme::COUNT) {
844 LogError("Invalid scheme: " << request_scheme);
845 return WKBundlePagePolicyActionPassThrough;
848 bool mainFrame = WKBundleFrameIsMainFrame(frame);
849 NavigationContext ctx = mainFrame ? TOP_LEVEL : FRAME_LEVEL;
851 LogDebug("Scheme type: " << type);
852 LogDebug("Navigation context: " << ctx);
853 LogDebug("Application type: " << m_widgetType.getApptypeToString());
857 if (m_widgetType == WrtDB::APP_TYPE_WAC20) {
858 action = g_wacActionMap[type][ctx];
859 } else if (m_widgetType == WrtDB::APP_TYPE_TIZENWEBAPP) {
860 action = g_tizenActionMap[type][ctx];
862 LogError("Unsupported application type: " << type);
863 return WKBundlePagePolicyActionPassThrough;
866 LogDebug("Uri action: " << action);
868 if (action != URI_ACTION_WRT) {
869 return WKBundlePagePolicyActionPassThrough;
872 return WKBundlePagePolicyActionUse;
875 std::string Bundle::toString(WKStringRef str)
877 if (WKStringIsEmpty(str)) {
878 return std::string();
880 size_t size = WKStringGetMaximumUTF8CStringSize(str);
881 char buffer[size + 1];
882 WKStringGetUTF8CString(str, buffer, size + 1);
886 std::string Bundle::toString(WKURLRef url)
888 WKStringRef urlStr = WKURLCopyString(url);
889 std::string str = toString(urlStr);
894 std::string Bundle::toString(WKURLRequestRef req)
896 WKURLRef reqUrl = WKURLRequestCopyURL(req);
897 std::string str = toString(reqUrl);
902 std::string Bundle::toString(WKErrorRef err)
904 WKStringRef domErr = WKErrorCopyDomain(err);
905 WKStringRef desc = WKErrorCopyLocalizedDescription(err);
906 std::string str = toString(domErr) + "\n" + toString(desc);
912 std::string Bundle::getScheme(std::string uri)
914 std::size_t found = uri.find(':');
917 if (found != std::string::npos) {
918 str = uri.substr(0, found);
924 bool Bundle::isEncryptedResource(std::string Url, int &size)
926 if (m_encryptedFiles.empty()) {
927 WrtDB::WidgetDAOReadOnly(m_widgetTizenId).
928 getEncryptedFileList(m_encryptedFiles);
931 std::set<WrtDB::EncryptedFileInfo>::iterator it;
932 WrtDB::EncryptedFileInfo info;
933 std::string filePath;
935 if (0 != strncmp(Url.c_str(), SCHEME_FILE, strlen(SCHEME_FILE))) {
939 filePath = Url.substr(strlen(SCHEME_FILE));
940 info.fileName = DPL::FromUTF8String(filePath);
942 if (m_encryptedFiles.end() != (it = m_encryptedFiles.find(info)))
944 LogDebug(" info file name : " << it->fileName);
945 LogDebug(" info file size : " << it->fileSize);
952 std::string Bundle::DecryptResource(std::string resource, int size)
954 std::string filePath;
956 size_t pos = resource.find_first_not_of(SCHEME_FILE);
957 if (std::string::npos != pos) {
958 filePath = resource.substr(pos - 1);
962 if (0 == stat(filePath.c_str(), &buf)) {
963 const std::size_t fileSize = buf.st_size;
964 std::unique_ptr<unsigned char[]> inChunk;
966 FILE* fp = fopen(filePath.c_str(), "rb");
968 LogDebug("Couldnot open file : " << filePath);
969 return std::string();
972 std::unique_ptr<unsigned char[]> DecryptedString(new unsigned
974 std::string pkgid(DPL::ToUTF8String(m_widgetTizenId));
976 using namespace Tizen::Base;
977 const byte *b_pkgid = reinterpret_cast<const byte*>(pkgid.c_str());
979 appInfo.Construct(pkgid.length());
980 appInfo.SetArray(b_pkgid, 0, pkgid.length());
985 unsigned char getDecSize[4];
986 memset(getDecSize, 0x00, sizeof(getDecSize));
988 size_t readSize = fread(getDecSize, sizeof(unsigned char),
989 sizeof(getDecSize), fp);
992 std::istringstream(std::string((char*)getDecSize)) >> readBufSize;
993 inChunk.reset(new unsigned char[readBufSize]);
995 size_t decReadSize = fread(inChunk.get(), sizeof(unsigned char),
997 if (0 != decReadSize) {
998 ByteBuffer *getBuffer =
999 DecryptChunkByTrustZone(&appInfo, inChunk.get(),
1001 memcpy(DecryptedString.get() + writeCount,
1002 getBuffer->GetPointer(), getBuffer->GetRemaining());
1003 writeCount += getBuffer->GetRemaining();
1008 } while( 0 == std::feof(fp));
1011 memset(DecryptedString.get() + size, '\n', fileSize - size);
1012 LogDebug("resource need to encoding base64");
1016 b64 = BIO_new(BIO_f_base64());
1017 bmem = BIO_new(BIO_s_mem());
1018 b64 = BIO_push(b64, bmem);
1019 BIO_write(b64, DecryptedString.get(), fileSize);
1021 BIO_get_mem_ptr(b64, &bptr);
1023 std::string base64Enc((char *)bptr->data, bptr->length - 1);
1028 return std::string();
1034 void WKBundleInitialize(WKBundleRef bundle,
1037 DPL::Log::LogSystemSingleton::Instance().SetTag("WRT-BUNDLE");
1038 LogDebug("Bundle initialized");
1040 DPL::Event::GetMainEventDispatcherInstance().ResetCrossEventCallHandler();
1041 LogDebug("ResetCrossEventCallHandler()");
1043 static Bundle s_bundle(bundle);
1045 WKBundleClient client = {
1046 kWKBundleClientCurrentVersion,
1048 &Bundle::didCreatePageCallback,
1049 &Bundle::willDestroyPageCallback,
1050 0, /* didInitializePageGroup */
1051 &Bundle::didReceiveMessageCallback
1053 WKBundleSetClient(bundle, &client);
1055 // process pool - restore process priority
1056 if (UID_ROOT == getuid())
1058 setpriority(PRIO_PROCESS, 0, DEFAULT_PRIORITY);