app uri implementation
authorTomasz Iwanek <t.iwanek@samsung.com>
Mon, 4 Mar 2013 10:25:49 +0000 (11:25 +0100)
committerTomasz Iwanek <t.iwanek@samsung.com>
Thu, 14 Mar 2013 13:48:40 +0000 (14:48 +0100)
[Issue#]       LINUXWRT-149
[Feature]      app uri implementation
[Cause]        N/A
[Solution]     app:// sheme support in webkit. whitelist for xhr to http
[Verification] Build wrt repository. Run some widgets. More tests are in wrt-extra change
[SCMRequest]   This requires: https://tizendev.org/gerrit/#/c/49849/ and http://tizendev.org/gerrit/51615
               and patched webkit: $ID@porucznik:../t.iwanek/webkit2-efl-123997_0.10.67-local.armv7l.rpm

Change-Id: Ifc6b02f5eeede17e10108b9b343b55082fe86fe0

src/domain/widget_model.cpp
src/view/common/scheme.cpp
src/view/common/scheme.h
src/view/common/scheme_action_map_data.h
src/view/common/view_logic_uri_support.cpp
src/view/webkit/bundles/bundle_uri_handling.cpp
src/view/webkit/bundles/wrt-wk2-bundle.cpp
src/view/webkit/bundles/wrt-wk2-bundle.h

index b378da4..96c9026 100644 (file)
@@ -68,7 +68,7 @@ WidgetModel::WidgetModel(const std::string &tizenId) :
     StartFileInfo(this),
     //localized, so not binded
     // file:// + / : without "/" path, webkit return security error
-    PrefixURL(this, L"file:///"),
+    PrefixURL(this, DPL::String(L"app://") + DPL::FromASCIIString(tizenId) + L"/"),
     InstallPath(
         this,
         &BindToWidgetDAO<DPL::String, &WidgetDAOReadOnly::getFullPath>::Get),
index 7539c10..b5279d1 100644 (file)
@@ -35,6 +35,7 @@ const char * const type2name[Scheme::COUNT] = {
     "http",
     "https",
     "widget",
+    "app",
     "vnd.youtube",
     "rtsp"
 };
index e004efa..e12e583 100644 (file)
@@ -39,6 +39,7 @@ class Scheme
         HTTP,
         HTTPS,
         WIDGET,
+        APP,
         YOUTUBE,
         RTSP,
 
index 3a13f31..4eac021 100644 (file)
@@ -69,6 +69,7 @@ const UriAction g_tizenActionMap[Scheme::COUNT][SchemeActionMap::COUNT] = {
     { URI_ACTION_WRT, URI_ACTION_WRT, URI_ACTION_WRT },           // HTTP
     { URI_ACTION_WRT, URI_ACTION_WRT, URI_ACTION_WRT },           // HTTPS
     { URI_ACTION_WRT, URI_ACTION_WRT, URI_ACTION_WRT },           // WIDGET
+    { URI_ACTION_WRT, URI_ACTION_WRT, URI_ACTION_WRT },           // APP
     { URI_ACTION_VIDEO, URI_ACTION_VIDEO, URI_ACTION_VIDEO },     // YOUTUBE
     { URI_ACTION_VIDEO, URI_ACTION_VIDEO, URI_ACTION_VIDEO }      // RTSP
 };
@@ -85,6 +86,7 @@ const UriAction g_wacActionMap[Scheme::COUNT][SchemeActionMap::COUNT] = {
     { URI_ACTION_APPSVC, URI_ACTION_WRT, URI_ACTION_APPSVC },     // HTTP
     { URI_ACTION_APPSVC, URI_ACTION_WRT, URI_ACTION_APPSVC },     // HTTPS
     { URI_ACTION_WRT, URI_ACTION_WRT, URI_ACTION_APPSVC },        // WIDGET
+    { URI_ACTION_WRT, URI_ACTION_WRT, URI_ACTION_APPSVC },        // APP
     { URI_ACTION_VIDEO, URI_ACTION_VIDEO, URI_ACTION_VIDEO },     // YOUTUBE
     { URI_ACTION_VIDEO, URI_ACTION_VIDEO, URI_ACTION_VIDEO }      // RTSP
 };
index b636eea..24d16e9 100644 (file)
@@ -46,6 +46,7 @@ enum ServiceDataType
     SERVICE_DATA_TYPE_MIME
 };
 
+char const * const SCHEME_TYPE_APP = "app";
 char const * const SCHEME_TYPE_FILE = "file";
 char const * const SCHEME_TYPE_WIDGET = "widget";
 
@@ -294,7 +295,7 @@ DPL::OptionalString localizeURI(const DPL::String& inputURI,
     }
 
     std::string scheme(urlcstr, end);
-    if (scheme != SCHEME_TYPE_WIDGET && scheme != SCHEME_TYPE_FILE) {
+    if (scheme != SCHEME_TYPE_WIDGET && scheme != SCHEME_TYPE_FILE && scheme != SCHEME_TYPE_APP) {
         LogDebug("scheme doesn't need to localize");
         return DPL::OptionalString(inputURI);
     }
index 9a9792e..c8727b4 100644 (file)
@@ -22,6 +22,7 @@
 #include "bundle_uri_handling.h"
 #include <dpl/log/log.h>
 #include <string.h>
+#include <sys/stat.h>
 #include <dpl/utils/wrt_global_settings.h>
 // For dao creation (widget info fetching)
 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
 namespace {
 char const * const SCHEME_TYPE_FILE = "file";
 char const * const SCHEME_TYPE_WIDGET = "widget";
+char const * const SCHEME_TYPE_APP = "app";
 char const * const WARP_ERROR_MSG =
     "file:///usr/etc/wrt/warp_security_error.msg";
 char const * const PARAM_URL = "param:url";
-char const * const ACE_IGNORED_SCHEMA[] = { "file://", "widget://", "data:",
-                                            "tel:", "sms:", "mmsto:", "mailto:",
-                                            0 };
+char const * const ACE_IGNORED_SCHEMA[] = { "file://", "widget://", "app://",
+                                            "data:", "tel:", "sms:", "mmsto:",
+                                            "mailto:", 0 };
 
 bool checkWARP(const char *url, const DPL::String& tizenId)
 {
@@ -69,6 +71,25 @@ bool checkWARP(const char *url, const DPL::String& tizenId)
                DPL::FromUTF8String(std::string(url)));
 }
 
+bool preventSymlink(const std::string & url)
+{
+    if(0 != strncmp(url.c_str(), SCHEME_TYPE_FILE, strlen(SCHEME_TYPE_FILE)))
+    {
+        return true;
+    }
+    if(url.size() >= strlen(SCHEME_TYPE_FILE) + 3)
+    {
+        std::string file = url.substr(strlen(SCHEME_TYPE_FILE) + 3);
+        struct stat st;
+        if(0 != stat(file.c_str(), &st)) return true;
+        return !S_ISLNK(st.st_mode);
+    }
+    else
+    {
+        return true;
+    }
+}
+
 bool checkACE(const char* url, bool xhr, const DPL::String& tizenId)
 {
     if (url) {
@@ -135,12 +156,17 @@ bool filterURIBySecurity(DPL::OptionalString &op_uri,
 
     auto uri = DPL::ToUTF8String(*op_uri);
     if (!checkWARP(uri.c_str(), tizenId)) {
-        LogDebug("Request was blocked by WARP: " << uri);
+        LogWarning("Request was blocked by WARP: " << uri);
         return false;
     }
 
     if (!checkACE(uri.c_str(), is_xhr, tizenId)) {
-        LogDebug("Request was blocked by ACE: " << uri);
+        LogWarning("Request was blocked by ACE: " << uri);
+        return false;
+    }
+
+    if (!preventSymlink(uri)) {
+        LogWarning("Request for symlink is invalid: " << uri);
         return false;
     }
 
@@ -171,20 +197,18 @@ bool processURI(const DPL::String& inputURI,
 DPL::OptionalString localizeURI(const DPL::String& inputURI,
                                 const DPL::String& tizenId)
 {
-    auto uri = DPL::ToUTF8String(inputURI);
+    std::string uri = DPL::ToUTF8String(inputURI);
     LogDebug("localizing url: " << uri);
-
     auto urlcstr = uri.c_str();
-
     const char *end = strstr(urlcstr, ":");
     if (!end) {
         LogDebug("no schema in link, return null");
         // lack of schema
         return DPL::Optional<DPL::String>::Null;
     }
-
     std::string scheme(urlcstr, end);
-    if (scheme != SCHEME_TYPE_WIDGET && scheme != SCHEME_TYPE_FILE) {
+
+    if (scheme != SCHEME_TYPE_WIDGET && scheme != SCHEME_TYPE_FILE && scheme != SCHEME_TYPE_APP) {
         LogDebug("scheme doesn't need to localize");
         return DPL::OptionalString(inputURI);
     }
index c374f9e..6540ed8 100644 (file)
 // URI localization on WebProcess side
 #include "bundle_uri_handling.h"
 
+//TODO: this is temprary hack for ENABLE marco is webkit!
+//do not include header webkits after this as they want work probably
+#define ENABLE(X) 0
+#include <WKBundlePrivate.h>
+#undef ENABLE
+
 namespace {
 const char * const uriChangedMessageName = "uri_changed_msg";
 const char * const uriBlockedMessageName = "uri_blocked_msg";
@@ -82,7 +88,8 @@ const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
 const char * const URICHANGE_BLOCKED_URL = "null";
 const char * const SCHEME_HTTP = "http";
 const char * const SCHEME_HTTPS = "https";
-const char * const SCHEME_FILE = "file://";
+const char * const SCHEME_FILE = "file";
+const char * const SCHEME_FILE_SLASH = "file://";
 const char * const DATA_STRING = "data:";
 const char * const BASE64_STRING = ";base64,";
 const char * const BLANK_PAGE_URL = "about:blank";
@@ -92,6 +99,7 @@ const char * const VIEWMODE_TYPE_FULLSCREEN = "fullscreen";
 const char * const VIEWMODE_TYPE_MAXIMIZED = "maximized";
 const std::size_t FILE_BUF_MAX_SIZE = 1024; // bytes
 const std::size_t PLAIN_CHUNK_SIZE = 1008; // bytes
+const char * const warpAllowProtocolsForWildcard[] = { "http", "https" };
 }
 
 Bundle::Bundle(WKBundleRef bundle) :
@@ -262,6 +270,50 @@ void Bundle::fixWKMessageArgs(std::string & argScale,
     }
 }
 
+void Bundle::bypassCORSforWARPAccessList(WrtDB::WidgetDAOReadOnly & dao)
+{
+    // bypassing CORS using origin whitelist
+    WrtDB::WidgetAccessInfoList WAList;
+    dao.getWidgetAccessInfo(WAList);
+    FOREACH(it, WAList)
+    {
+        const WrtDB::WidgetAccessInfo & access = *it;
+        WKURLRef url = WKURLCreateWithUTF8CString(DPL::ToUTF8String(access.strIRI).c_str());
+
+        std::string source = std::string("app://") + DPL::ToUTF8String(m_widgetTizenId) + "/";
+
+        LogDebug("WARP to WK whitelist position: " << source << " for "
+            << access.strIRI << " subDomains: " << access.bSubDomains);
+
+        WKStringRef wkSource = WKStringCreateWithUTF8CString(source.c_str());
+        WKStringRef wkHost;
+        WKStringRef wkProtocol;
+        if(access.strIRI == L"*")
+        {
+            //wildcard force to explicitly say which protocol is used
+            // passed wkHost if empty means wildcard -> allow everything but protocol has to be set.
+            for(unsigned i = 0; i < sizeof(warpAllowProtocolsForWildcard); i++)
+            {
+                wkHost = WKStringCreateWithUTF8CString("");
+                wkProtocol = WKStringCreateWithUTF8CString(warpAllowProtocolsForWildcard[i]);
+                WKBundleAddOriginAccessWhitelistEntry(m_bundle,
+                    wkSource, wkProtocol, wkHost, access.bSubDomains);
+            }
+        }
+        else
+        {
+            wkHost = WKURLCopyHostName(url);
+            wkProtocol = WKURLCopyScheme(url);
+            WKBundleAddOriginAccessWhitelistEntry(m_bundle,
+                wkSource, wkProtocol, wkHost, access.bSubDomains);
+        }
+
+        WKRelease(wkHost);
+        WKRelease(wkProtocol);
+        WKRelease(wkSource);
+    }
+}
+
 void Bundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
 {
     LogDebug("got message type: " << toString(messageName).c_str());
@@ -379,6 +431,9 @@ void Bundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
             m_widgetTizenId = DPL::FromASCIIString(msgString);
 
             WrtDB::WidgetDAOReadOnly dao(m_widgetTizenId);
+
+            bypassCORSforWARPAccessList(dao);
+
             /* This type of message is received when widget is restarting
              * (proably in other situation too). Widget restart can be
              * called after system language change so language tags have to
@@ -658,8 +713,14 @@ WKURLRequestRef Bundle::willSendRequestForFrame(WKURLRequestRef request)
     LogDebug("URI processing result: " << *localizedUrl);
     std::string tmpUrlStr = DPL::ToUTF8String(*localizedUrl);
     WKURLRef tmpUrl = WKURLCreateWithUTF8CString(tmpUrlStr.c_str());
-    std::string scheme = toString(WKURLCopyScheme(url));
+    std::string scheme = toString(WKURLCopyScheme(url)); //scheme of original request
     WKRelease(url);
+
+    if(scheme == SCHEME_FILE) {
+        LogError("File schema blocked for: " << dplurl);
+        return NULL;
+    }
+
     // Return value must contain details information of input
     // WKURLRequestRef. Current webkit2 doesn't support api that
     // copy WKURLRequestRef or change url only. Before webkit2
@@ -851,7 +912,7 @@ bool Bundle::isEncryptedResource(std::string Url, int &size)
 {
     std::string filePath;
 
-    size_t pos = Url.find_first_not_of(SCHEME_FILE);
+    size_t pos = Url.find_first_not_of(SCHEME_FILE_SLASH);
     if (std::string::npos != pos) {
         filePath = Url.substr(pos - 1);
     }
@@ -865,7 +926,7 @@ bool Bundle::isEncryptedResource(std::string Url, int &size)
     std::set<WrtDB::EncryptedFileInfo>::iterator it;
     info.fileName = DPL::FromUTF8String(filePath);
 
-    if ((0 == strncmp(Url.c_str(), SCHEME_FILE, strlen(SCHEME_FILE))) &&
+    if ((0 == strncmp(Url.c_str(), SCHEME_FILE_SLASH, strlen(SCHEME_FILE_SLASH))) &&
         (m_encryptedFiles.end() != (it =
                                         m_encryptedFiles.find(info))))
     {
@@ -881,7 +942,7 @@ std::string Bundle::DecryptResource(std::string resource, int size)
 {
     std::string filePath;
 
-    size_t pos = resource.find_first_not_of(SCHEME_FILE);
+    size_t pos = resource.find_first_not_of(SCHEME_FILE_SLASH);
     if (std::string::npos != pos) {
         filePath = resource.substr(pos - 1);
     }
index 9d93fca..875250d 100644 (file)
@@ -160,6 +160,9 @@ class Bundle
     void fixWKMessageArgs(std::string & argScale,
                           std::string & argEncodedBundle,
                           std::string & argTheme);
+
+    void bypassCORSforWARPAccessList(WrtDB::WidgetDAOReadOnly &dao);
+
     void *DecryptChunkByTrustZone(const unsigned char *inBuffer,
                                  int inBufSize);
 };