Implement Scheme to Appcontrol request
authorSeungkeun Lee <sngn.lee@samsung.com>
Mon, 7 Sep 2015 06:29:46 +0000 (15:29 +0900)
committerSeungkeun Lee <sngn.lee@samsung.com>
Fri, 18 Sep 2015 08:31:51 +0000 (17:31 +0900)
 - Well-known scheme was converted to AppControl request
 - Except (http(s), file, app, data, blob), all custom scheme was send to AppControl request

Change-Id: Id4fe074cdec87bd8812519f555dea31f28be60ea

common/app_control.cc
common/app_control.h
runtime/browser/web_application.cc

index 799af8b385caf355f5afe731a1b7dfbb22aee6b1..5818b8f6e49324186e814a4428684071014a89a1 100755 (executable)
 
 #include <algorithm>
 #include <memory>
+#include <map>
+#include <vector>
+#include <regex> // NOLINT
+#include <utility>
 
 #include "common/logger.h"
+#include "common/string_utils.h"
+#include "common/file_utils.h"
 
 namespace common {
 
@@ -57,6 +63,46 @@ static bool BundleAddDataArray(bundle* target, const std::string& key,
   }
 }
 
+static const std::string GetOperationFromScheme(const std::string& scheme) {
+  static std::map<const std::string, const std::string> table = {
+    {"sms", APP_CONTROL_OPERATION_COMPOSE},
+    {"mmsto", APP_CONTROL_OPERATION_COMPOSE},
+    {"mailto", APP_CONTROL_OPERATION_COMPOSE},
+    {"tel", APP_CONTROL_OPERATION_CALL}
+  };
+  auto found = table.find(scheme);
+  if (found == table.end()) {
+    // default operation
+    return APP_CONTROL_OPERATION_VIEW;
+  }
+  return found->second;
+}
+
+static void AppendExtraDatafromUrl(AppControl* request,
+                                   const std::string& url) {
+  static std::vector<std::pair<std::string, std::string> > patterns = {
+    {".*[?&]body=([^&]+).*", APP_CONTROL_DATA_TEXT},
+    {".*[?&]cc=([^&]+).*", APP_CONTROL_DATA_CC},
+    {".*[?&]bcc=([^&]+).*", APP_CONTROL_DATA_BCC},
+    {".*[?&]subject=([^&]+).*", APP_CONTROL_DATA_SUBJECT},
+    {".*[?&]to=([^&]+).*", APP_CONTROL_DATA_TO},
+    {"sms:([^?&]+).*", APP_CONTROL_DATA_TO},
+    {"mmsto:([^?&]+).*", APP_CONTROL_DATA_TO},
+    {"mailto:([^?&]+).*", APP_CONTROL_DATA_TO}
+  };
+
+  for (auto& param : patterns) {
+    std::regex pattern(param.first, std::regex_constants::icase);
+    std::smatch result;
+    if (std::regex_match(url, result, pattern) && result.size() >= 2) {
+      std::string extra_data = result[1].str();
+      request->AddData(
+        param.second,
+        utils::UrlDecode(extra_data));
+    }
+  }
+}
+
 
 }  // namespace
 
@@ -210,4 +256,24 @@ bool AppControl::LaunchRequest() {
           APP_CONTROL_ERROR_NONE);
 }
 
+std::unique_ptr<AppControl> AppControl::MakeAppcontrolFromURL(
+    const std::string& url) {
+  std::string smsto_scheme("smsto");
+
+  std::string request_url(url);
+  std::string scheme = utils::SchemeName(request_url);
+  // smsto: does not supported by platform. change to sms:
+  if (scheme == smsto_scheme) {
+    request_url = "sms" + request_url.substr(smsto_scheme.length());
+    scheme = "sms";
+  }
+
+  std::unique_ptr<AppControl> request(new AppControl());
+  request->set_uri(request_url);
+  request->set_operation(GetOperationFromScheme(scheme));
+  AppendExtraDatafromUrl(request.get(), request_url);
+
+  return std::move(request);
+}
+
 }  // namespace common
index 00fcedbe47b495518348226c761df05a3a4e85ed..e59de115b9306c0579aafac2138b2b685ea6aaeb 100755 (executable)
 #include <string>
 #include <vector>
 #include <map>
+#include <memory>
 
 namespace common {
 
 class AppControl {
  public:
+  static std::unique_ptr<AppControl> MakeAppcontrolFromURL(
+      const std::string& url);
   explicit AppControl(app_control_h app_control);
   AppControl();
   ~AppControl();
index 3733a9171cbb2c639fdf4397f9f45bf454ce1d4d..7b8cb8203715486b8d097cadd3ce78692afe1b35 100755 (executable)
@@ -184,6 +184,28 @@ static bool ClearCookie(Ewk_Context* ewk_context) {
   return true;
 }
 
+static bool ProcessWellKnownScheme(const std::string& url) {
+  if (utils::StartsWith(url, "file:") ||
+      utils::StartsWith(url, "app:") ||
+      utils::StartsWith(url, "data:") ||
+      utils::StartsWith(url, "http:") ||
+      utils::StartsWith(url, "https:") ||
+      utils::StartsWith(url, "widget:") ||
+      utils::StartsWith(url, "about:") ||
+      utils::StartsWith(url, "blob:")) {
+    return false;
+  }
+
+  std::unique_ptr<AppControl> request(AppControl::MakeAppcontrolFromURL(url));
+  if (request.get() == NULL || !request->LaunchRequest()) {
+    LOGGER(ERROR) << "Fail to send appcontrol request";
+    SLoggerE("Fail to send appcontrol request [%s]", url.c_str());
+  }
+
+  // Should return true, to stop the WebEngine progress step about this URL
+  return true;
+}
+
 }  // namespace
 
 WebApplication::WebApplication(
@@ -666,9 +688,11 @@ void WebApplication::SetupWebView(WebView* view) {
 
 bool WebApplication::OnDidNavigation(WebView* /*view*/,
                                      const std::string& url) {
-  // TODO(sngn.lee): scheme handling
+  // scheme handling
   // except(file , http, https, app) pass to appcontrol and return false
-
+  if (ProcessWellKnownScheme(url)) {
+    return false;
+  }
   return resource_manager_->AllowNavigation(url);
 }