Merge pull request #6 from myroot/handle-scheme-to-appcontrol
authorWonYoung Choi <wy80.choi@samsung.com>
Mon, 21 Sep 2015 01:04:27 +0000 (10:04 +0900)
committerWonYoung Choi <wy80.choi@samsung.com>
Mon, 21 Sep 2015 01:04:27 +0000 (10:04 +0900)
Implement Scheme to Appcontrol request

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

index 799af8b..5818b8f 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 00fcedb..e59de11 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 03aa954..3d6e50a 100755 (executable)
@@ -187,6 +187,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(
@@ -669,9 +691,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);
 }