[M108 Migration][AppControl] Introduce app control scheme (appcontrol://) 97/287997/3
authorayush.k123 <ayush.k123@samsung.com>
Wed, 8 Feb 2023 06:46:34 +0000 (12:16 +0530)
committerBot Blink <blinkbot@samsung.com>
Mon, 13 Feb 2023 01:56:27 +0000 (01:56 +0000)
This patch introduces app control scheme in chromium-efl.

References:
https://review.tizen.org/gerrit/279925/

Change-Id: If6275c50a84def752db078b744db3bc792ab1751
Signed-off-by: Ayush Kumar <ayush.k123@samsung.com>
15 files changed:
content/browser/renderer_host/render_frame_host_manager.cc
packaging/chromium-efl.spec
tizen_src/build/BUILD.gn
tizen_src/ewk/efl_integration/BUILD.gn
tizen_src/ewk/efl_integration/content_browser_client_efl.cc
tizen_src/ewk/efl_integration/content_browser_client_efl.h
tizen_src/ewk/efl_integration/eweb_context.cc
tizen_src/ewk/efl_integration/eweb_context.h
tizen_src/ewk/efl_integration/eweb_view.cc
tizen_src/ewk/efl_integration/eweb_view.h [changed mode: 0755->0644]
tizen_src/ewk/efl_integration/private/ewk_app_control_private.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/private/ewk_app_control_private.h [new file with mode: 0644]
tizen_src/ewk/efl_integration/private/ewk_context_private.cc
tizen_src/ewk/efl_integration/private/ewk_context_private.h
tizen_src/ewk/efl_integration/public/ewk_context.cc

index d170099..44845cb 100644 (file)
@@ -3237,6 +3237,14 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
     return base::WrapRefCounted(current_site_instance);
   }
 
+#if BUILDFLAG(IS_TIZEN)
+  // For unknown url schemes like appcontrol new SiteInstance is created leading
+  // to creation of new RWHV. This results in empty page when we click a
+  // hyperlink with appcontrol scheme.
+  if (request->common_params().url.SchemeIs("appcontrol"))
+    return base::WrapRefCounted(current_site_instance);
+#endif
+
   // Srcdoc documents are only in the same SiteInstance as their parent if they
   // both have the same value for is_sandboxed(). They load their content from
   // the "srcdoc" iframe attribute which lives in the parent's process. Using
index 3820106..111d603 100644 (file)
@@ -103,6 +103,7 @@ BuildRequires: pkgconfig(mm-player)
 BuildRequires: pkgconfig(notification)
 BuildRequires: pkgconfig(nspr)
 BuildRequires: pkgconfig(nss)
+BuildRequires: pkgconfig(pkgmgr-info)
 BuildRequires: pkgconfig(scim)
 BuildRequires: pkgconfig(security-manager)
 BuildRequires: pkgconfig(sqlite3)
index bee9081..f354554 100644 (file)
@@ -313,6 +313,13 @@ config("capi-system-system-settings-public") {
   }
 }
 
+tizen_pkg_config("pkgmgr-info") {
+  packages = []
+  if (is_tizen) {
+    packages = [ "pkgmgr-info" ]
+  }
+}
+
 config("libdri2") {
   if (is_tizen && !use_wayland) {
     ldflags = [ "-llibdri2" ]
index 9688fd7..c0a8b8c 100755 (executable)
@@ -60,6 +60,7 @@ shared_library("chromium-ewk") {
     "//components/autofill/content/browser",
     "//components/autofill/content/renderer",
     "//components/error_page/common",
+    "//components/navigation_interception",
     "//components/network_session_configurator/browser",
     "//components/password_manager/content/browser",
     "//components/password_manager/core/browser",
@@ -130,6 +131,7 @@ shared_library("chromium-ewk") {
     deps += [ "//cc:cc" ]
     configs += [ "//tizen_src/build:capi-appfw-app-manager" ]
     configs += [ "//tizen_src/build:libcapi-appfw-app-manager" ]
+    configs += [ "//tizen_src/build:pkgmgr-info" ]
   } else {
     if (use_gio) {
       configs += [ "//build/linux:gio_config" ]
@@ -369,6 +371,8 @@ shared_library("chromium-ewk") {
     "common/web_contents_utils.h",
     "common/web_preferences_efl.h",
     "private/back_forward_list.h",
+    "private/ewk_app_control_private.cc",
+    "private/ewk_app_control_private.h",
     "private/ewk_auth_challenge_private.h",
     "private/ewk_autofill_profile_private.cc",
     "private/ewk_autofill_profile_private.h",
index 13a6a06..9c7381e 100644 (file)
@@ -23,6 +23,7 @@
 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
 #include "components/error_page/common/error.h"
 #include "components/error_page/common/localized_error.h"
+#include "components/navigation_interception/intercept_navigation_throttle.h"
 #include "components/password_manager/content/browser/content_password_manager_driver_factory.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_handle.h"
@@ -61,6 +62,18 @@ using content::BrowserThread;
 
 namespace content {
 
+bool ShouldIgnoreNavigationOnUIThread(
+    content::NavigationHandle* navigation_handle) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(navigation_handle->GetWebContents());
+
+  EWebView* wv = WebViewFromWebContents(navigation_handle->GetWebContents());
+  if (wv)
+    return wv->ShouldIgnoreNavigation(navigation_handle);
+
+  return false;
+}
+
 namespace {
 
 const char* const kDefaultAcceptLanguages = "en-us,en";
@@ -493,6 +506,13 @@ ContentBrowserClientEfl::CreateThrottlesForNavigation(
     NavigationHandle* handle) {
   std::vector<std::unique_ptr<NavigationThrottle>> throttles;
   throttles.push_back(std::make_unique<NavigationThrottleEfl>(handle));
+
+  if (enabled_app_control && handle->IsInMainFrame()) {
+    throttles.push_back(
+        std::make_unique<navigation_interception::InterceptNavigationThrottle>(
+            handle, base::BindRepeating(&ShouldIgnoreNavigationOnUIThread),
+            navigation_interception::SynchronyMode::kSync));
+  }
   return throttles;
 }
 
index 1d23e7f..04a7e13 100644 (file)
@@ -149,6 +149,8 @@ class ContentBrowserClientEfl : public ContentBrowserClient {
       int frame_tree_node_id) override;
   std::string GetAcceptLangs(BrowserContext* context) override;
 
+  void EnableAppControl(bool enabled) { enabled_app_control = enabled; }
+
  private:
   bool WillCreateURLLoaderFactory(
       BrowserContext* browser_context,
@@ -177,6 +179,7 @@ class ContentBrowserClientEfl : public ContentBrowserClient {
 
   std::unique_ptr<AcceptLanguagesHelper> accept_langs_helper_;
   bool shutting_down_ = false;
+  bool enabled_app_control = true;
 };
 }  // namespace content
 
index 7b96734..4001a4c 100644 (file)
@@ -881,6 +881,15 @@ void EWebContext::SetInterceptRequestCallback(
                                                     user_data);
 }
 
+void EWebContext::EnableAppControl(bool enabled) {
+#if BUILDFLAG(IS_TIZEN)
+  content::ContentBrowserClient* cbc =
+      content::GetContentClientExport()->browser();
+  auto cbce = static_cast<content::ContentBrowserClientEfl*>(cbc);
+  cbce->EnableAppControl(enabled);
+#endif
+}
+
 #if BUILDFLAG(IS_TIZEN_TV)
 void EWebContext::SetApplicationType(
     const Ewk_Application_Type application_type) {
index c7700a2..ce38dc9 100644 (file)
@@ -193,6 +193,8 @@ class EWebContext {
   Ewk_Application_Type GetApplicationType() const { return application_type_; }
 #endif
 
+  void EnableAppControl(bool enabled);
+
  private:
   EWebContext(bool incognito);
   EWebContext(const std::string& injectedBundlePath);
index 3717f26..eb95895 100644 (file)
 #include "content/public/browser/host_zoom_map.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_handle.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/mhtml_generation_params.h"
 #include "content/public/common/user_agent.h"
 #include "net/base/filename_util.h"
 #include "permission_popup_manager.cc"
+#include "private/ewk_app_control_private.h"
 #include "private/ewk_back_forward_list_private.h"
 #include "private/ewk_context_private.h"
 #include "private/ewk_frame_private.h"
@@ -2762,6 +2764,20 @@ void EWebView::ExceededIndexedDatabaseQuotaReply(bool allow) {
   exceeded_indexed_db_quota_origin_.reset();
 }
 
+bool EWebView::ShouldIgnoreNavigation(
+    content::NavigationHandle* navigation_handle) {
+  if (!navigation_handle->GetURL().is_valid() ||
+      !navigation_handle->GetURL().SchemeIs("appcontrol") ||
+      (!navigation_handle->HasUserGesture() &&
+       !navigation_handle->WasServerRedirect())) {
+    return false;
+  }
+
+  _Ewk_App_Control app_control(
+      this, navigation_handle->GetURL().possibly_invalid_spec());
+  return app_control.Proceed();
+}
+
 bool EWebView::SetVisibility(bool enable) {
   if (!web_contents_)
     return false;
old mode 100755 (executable)
new mode 100644 (file)
index 704ac99..c1575df
@@ -79,9 +79,11 @@ class ContextMenuControllerEfl;
 class PopupControllerEfl;
 class InputPicker;
 class GinNativeBridgeDispatcherHost;
+class NavigationHandle;
 }
 
 class ErrorParams;
+class _Ewk_App_Control;
 class _Ewk_Policy_Decision;
 class _Ewk_Hit_Test;
 class Ewk_Context;
@@ -593,6 +595,8 @@ class EWebView {
     return date_time_chooser_;
   }
 
+  bool ShouldIgnoreNavigation(content::NavigationHandle* navigation_handle);
+
  private:
   void InitializeContent();
   void InitializeWindowTreeHost();
diff --git a/tizen_src/ewk/efl_integration/private/ewk_app_control_private.cc b/tizen_src/ewk/efl_integration/private/ewk_app_control_private.cc
new file mode 100644 (file)
index 0000000..ea39d8d
--- /dev/null
@@ -0,0 +1,399 @@
+// Copyright 2018 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ewk_app_control_private.h"
+
+#include "base/logging.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_tokenizer.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "eweb_view.h"
+#include "url/url_util.h"
+
+const char kAppControlScheme[] = "appcontrol";
+const char kAppControlStart[] = "AppControl";
+const char kAppControlEnd[] = "end";
+const char kOperation[] = "operation=";
+const char kUri[] = "uri=";
+const char kMime[] = "mime=";
+const char kAppID[] = "appid=";
+const char kExtraData[] = "e.";
+const char kLaunchMode[] = "launch_mode=";
+const char kLaunchModeGroup[] = "group";
+const char kFallbackUrl[] = "fallback_url";
+const char kDefaultCategory[] = "http://tizen.org/category/browsableapp";
+
+#if BUILDFLAG(IS_TIZEN)
+static void AppControlResultCb(app_control_h request,
+                               app_control_h reply,
+                               app_control_result_e result,
+                               void* data) {
+  auto* app_control = static_cast<_Ewk_App_Control*>(data);
+
+  if (result == APP_CONTROL_RESULT_APP_STARTED ||
+      result == APP_CONTROL_RESULT_SUCCEEDED) {
+    LOG(INFO) << __FUNCTION__ << " > Success ";
+  } else {
+    LOG(ERROR) << __FUNCTION__
+               << " > Fail or cancel app control. ERR: " << result;
+    app_control->FailHandling();
+  }
+}
+#endif
+
+_Ewk_App_Control::_Ewk_App_Control(EWebView* webview,
+                                   std::string intercepted_url)
+    : webview_(webview),
+#if BUILDFLAG(IS_TIZEN)
+      app_control_(nullptr),
+#endif
+      intercepted_url_(DecodeUrl(intercepted_url)),
+      explicit_category(false) {
+}
+
+_Ewk_App_Control::~_Ewk_App_Control() {
+#if BUILDFLAG(IS_TIZEN)
+  if (app_control_)
+    app_control_destroy(app_control_);
+#endif
+}
+
+bool _Ewk_App_Control::Proceed() {
+#if BUILDFLAG(IS_TIZEN)
+  if (ParseNavigationParams() && MakeAppControl()) {
+    // Launch request
+    int ret = app_control_send_launch_request(app_control_, AppControlResultCb,
+                                              reinterpret_cast<void*>(this));
+    if (ret != APP_CONTROL_ERROR_NONE) {
+      LOG(ERROR) << __FUNCTION__
+                 << " > Fail to send launch request. ERR: " << ret;
+      return FailHandling();
+    }
+    return true;
+  }
+#endif
+  return false;
+}
+
+bool _Ewk_App_Control::FailHandling() {
+  if (!webview_) {
+    LOG(INFO) << __FUNCTION__ << " > webview object is null";
+    return false;
+  }
+
+  if (!fallback_url_.empty()) {
+    // Launch fallback_url!
+    LOG(INFO) << __FUNCTION__ << " > fallback url : " << fallback_url_.c_str();
+    webview_->SetURL(GURL(fallback_url_));
+    return true;
+  }
+
+  // TODO(djmix.kim) : Connect to Tizen app store
+  LOG(INFO) << __FUNCTION__ << " > Not implemented : connect to app store";
+  return false;
+}
+
+bool _Ewk_App_Control::ParseNavigationParams() {
+  base::StringTokenizer str_tok(intercepted_url_, ";");
+
+  if (!str_tok.GetNext()) {
+    LOG(ERROR) << __FUNCTION__ << " > Parsing error";
+    return false;
+  }
+
+  // check start : "#AppControl"
+  const std::string& buf = str_tok.token();
+  base::StringTokenizer check_start(buf, "#");
+  check_start.GetNext();
+  if (!check_start.GetNext() || check_start.token() != kAppControlStart) {
+    LOG(ERROR) << __FUNCTION__ << " > #AppControl is missing! ";
+    return false;
+  }
+
+  bool check_end = false;
+  bool check_operation = false;
+  bool check_uri = false;
+  bool check_mime = false;
+  bool check_app_id = false;
+  bool check_launch_mode = false;
+  while (str_tok.GetNext()) {
+    const std::string& token = str_tok.token();
+
+    // check end : "end"
+    if (token == kAppControlEnd) {
+      check_end = true;
+      break;
+    }
+
+    std::string buf = GetValue(token);
+    if (base::StartsWith(token, kOperation,
+                         base::CompareCase::INSENSITIVE_ASCII)) {
+      if (check_operation) {
+        LOG(ERROR) << __FUNCTION__ << " > Invalid operation";
+        return false;
+      }
+      operation_ = buf;
+      check_operation = true;
+    } else if (base::StartsWith(token, kUri,
+                                base::CompareCase::INSENSITIVE_ASCII)) {
+      if (check_uri) {
+        LOG(ERROR) << __FUNCTION__ << " > Invalid uri";
+        return false;
+      }
+      uri_ = buf;
+      check_uri = true;
+    } else if (base::StartsWith(token, kMime,
+                                base::CompareCase::INSENSITIVE_ASCII)) {
+      if (check_mime) {
+        LOG(ERROR) << __FUNCTION__ << " > Invalid mime";
+        return false;
+      }
+      mime_ = buf;
+      check_mime = true;
+    } else if (base::StartsWith(token, kAppID,
+                                base::CompareCase::INSENSITIVE_ASCII)) {
+      if (check_app_id) {
+        LOG(ERROR) << __FUNCTION__ << " > Invalid app id";
+        return false;
+      }
+      app_id_ = buf;
+      check_app_id = true;
+    } else if (base::StartsWith(token, kLaunchMode,
+                                base::CompareCase::INSENSITIVE_ASCII)) {
+      if (check_launch_mode) {
+        LOG(ERROR) << __FUNCTION__ << " > Invalid launch mode";
+        return false;
+      }
+      launch_mode_ = buf;
+      check_launch_mode = true;
+    } else if (base::StartsWith(token, kExtraData,
+                                base::CompareCase::INSENSITIVE_ASCII)) {
+      SetExtraData(token);
+    }
+  }
+
+  if (!check_end) {
+    LOG(ERROR) << __FUNCTION__ << " > end; is missing! ";
+    return false;
+  }
+
+  ShowParseNavigationParams();
+  return true;
+}
+
+std::string _Ewk_App_Control::GetValue(std::string token) {
+  std::string full_str;
+  std::vector<std::string> values = base::SplitString(
+      token, "=", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+
+  if (values.size() <= 1)
+    return std::string("");
+
+  for (int i = 1; i < values.size(); i++) {
+    if (i > 1)
+      full_str += "=";
+    full_str += values[i];
+  }
+
+  return full_str;
+}
+
+void _Ewk_App_Control::SetExtraData(std::string token) {
+  std::string full_str;
+  std::vector<std::string> values = base::SplitString(
+      token, "=", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+
+  if (values.size() > 0) {
+    for (int i = 1; i < values.size(); i++) {
+      if (i > 1)
+        full_str += "=";
+      full_str += values[i];
+    }
+
+    std::vector<std::string> keys = base::SplitString(
+        values[0], ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+
+    if (keys.size() == 1)
+      return;
+
+    if (keys[1] == kFallbackUrl)
+      fallback_url_ = full_str;
+    else
+      extra_data_[keys[1]] = full_str;
+  }
+}
+
+bool _Ewk_App_Control::MakeAppControl() {
+#if BUILDFLAG(IS_TIZEN)
+  if (app_control_)
+    app_control_destroy(app_control_);
+
+  int ret = app_control_create(&app_control_);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LOG(ERROR) << __FUNCTION__ << " > app_control_create is failed with err "
+               << ret;
+    return false;
+  }
+
+  // Set category to http://tizen.org/category/browsableapp as default.
+  ret = app_control_set_category(app_control_, kDefaultCategory);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LOG(ERROR) << __FUNCTION__
+               << " > app_control_set_category is failed with err " << ret;
+    return FailHandling();
+  }
+
+  // Check app_id
+  if (!app_id_.empty()) {  // explicit launch
+    explicit_category = false;
+    ret = app_control_set_app_id(app_control_, app_id_.c_str());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+      LOG(ERROR) << __FUNCTION__
+                 << " > app_control_set_app_id is failed with err " << ret;
+      return FailHandling();
+    }
+
+    pkgmgrinfo_appinfo_h handle;
+    ret = pkgmgrinfo_appinfo_get_appinfo(app_id_.c_str(), &handle);
+    if (ret != PMINFO_R_OK) {
+      LOG(ERROR) << __FUNCTION__
+                 << " > pkgmgrinfo_appinfo_get_appinfo failed!!! : " << ret;
+      return FailHandling();
+    }
+
+    ret = pkgmgrinfo_appinfo_foreach_category(
+        handle,
+        [](const char* category, void* user_data) -> int {
+          auto app_control = static_cast<_Ewk_App_Control*>(user_data);
+          if ((nullptr != category) &&
+              std::string(category) == kDefaultCategory) {
+            app_control->explicit_category = true;
+          }
+          return 0;
+        },
+        this);
+
+    if (!explicit_category) {
+      LOG(ERROR) << __FUNCTION__
+                 << "> Explicit launch : This is not a browsable app";
+      return FailHandling();
+    }
+
+    pkgmgrinfo_appinfo_destroy_appinfo(handle);
+  }
+
+  // operation
+  if (!operation_.empty()) {
+    ret = app_control_set_operation(app_control_, operation_.c_str());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+      LOG(ERROR) << __FUNCTION__
+                 << " > app_control_set_operation is failed with err " << ret;
+      return FailHandling();
+    }
+  }
+
+  // uri
+  if (!uri_.empty()) {
+    ret = app_control_set_uri(app_control_, uri_.c_str());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+      LOG(ERROR) << __FUNCTION__ << " > app_control_set_uri is failed with err "
+                 << ret;
+      return FailHandling();
+    }
+  }
+
+  // mime
+  if (!mime_.empty()) {
+    ret = app_control_set_mime(app_control_, mime_.c_str());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+      LOG(ERROR) << __FUNCTION__
+                 << " > app_control_set_mime is failed with err " << ret;
+      return FailHandling();
+    }
+  }
+
+  // launch_mode
+  if (!launch_mode_.empty()) {
+    ret = app_control_set_launch_mode(app_control_, GetLaunchMode());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+      LOG(ERROR) << __FUNCTION__
+                 << " > app_control_set_launch_mode is failed with err " << ret;
+      return FailHandling();
+    }
+  }
+
+  // extra_data
+  if (!extra_data_.empty()) {
+    std::map<std::string, std::string>::iterator it;
+    for (it = extra_data_.begin(); it != extra_data_.end(); it++) {
+      app_control_add_extra_data(app_control_, it->first.c_str(),
+                                 it->second.c_str());
+    }
+  }
+
+  ret = app_control_enable_app_started_result_event(app_control_);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LOG(ERROR)
+        << __FUNCTION__
+        << " > app_control_enable_app_started_result_event is failed with err "
+        << ret;
+    return FailHandling();
+  }
+
+  return true;
+#else
+  return false;
+#endif
+}
+
+void _Ewk_App_Control::ShowParseNavigationParams() {
+  LOG(INFO) << __FUNCTION__;
+  LOG(INFO) << "operation : " << GetOperation();
+  LOG(INFO) << "uri : " << GetUri();
+  LOG(INFO) << "mime : " << GetMime();
+  LOG(INFO) << "appid : " << GetAppId();
+#if BUILDFLAG(IS_TIZEN)
+  LOG(INFO) << "launch_mode : " << GetLaunchMode();
+#endif
+  LOG(INFO) << "fallback_url : " << fallback_url_.c_str();
+
+  std::map<std::string, std::string>::iterator it;
+  for (it = extra_data_.begin(); it != extra_data_.end(); it++) {
+    LOG(INFO) << "extra_data : key=" << it->first.c_str()
+              << " value=" << it->second.c_str();
+  }
+}
+
+const char* _Ewk_App_Control::GetOperation() const {
+  return operation_.c_str();
+}
+
+const char* _Ewk_App_Control::GetUri() const {
+  return uri_.c_str();
+}
+
+const char* _Ewk_App_Control::GetMime() const {
+  return mime_.c_str();
+}
+
+const char* _Ewk_App_Control::GetAppId() const {
+  return app_id_.c_str();
+}
+
+#if BUILDFLAG(IS_TIZEN)
+app_control_launch_mode_e _Ewk_App_Control::GetLaunchMode() const {
+  return (launch_mode_ == kLaunchModeGroup) ? APP_CONTROL_LAUNCH_MODE_GROUP
+                                            : APP_CONTROL_LAUNCH_MODE_SINGLE;
+}
+#endif
+
+std::string _Ewk_App_Control::DecodeUrl(std::string url) {
+  std::string output;
+  url::RawCanonOutputT<char16_t> decode;
+  url::DecodeURLEscapeSequences(url.data(), url.size(),
+                                url::DecodeURLMode::kUTF8, &decode);
+  base::UTF16ToUTF8(decode.data(), decode.length(), &output);
+  return output;
+}
diff --git a/tizen_src/ewk/efl_integration/private/ewk_app_control_private.h b/tizen_src/ewk/efl_integration/private/ewk_app_control_private.h
new file mode 100644 (file)
index 0000000..1b20aea
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright 2018 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ewk_app_control_private_h
+#define ewk_app_control_private_h
+
+#include <map>
+#include <string>
+#include "build/build_config.h"
+
+#if BUILDFLAG(IS_TIZEN)
+#include <app_control_internal.h>
+#include <app_manager.h>
+#include <pkgmgr-info.h>
+#endif
+
+class EWebView;
+
+class _Ewk_App_Control {
+ public:
+  explicit _Ewk_App_Control(EWebView* webview, std::string intercepted_url);
+  ~_Ewk_App_Control();
+
+  _Ewk_App_Control(const _Ewk_App_Control&) = delete;
+  _Ewk_App_Control& operator=(const _Ewk_App_Control&) = delete;
+
+  bool Proceed();
+  const char* GetOperation() const;
+  const char* GetUri() const;
+  const char* GetMime() const;
+  const char* GetAppId() const;
+#if BUILDFLAG(IS_TIZEN)
+  app_control_launch_mode_e GetLaunchMode() const;
+#endif
+  bool FailHandling();
+
+ private:
+  bool MakeAppControl();
+  bool ParseNavigationParams();
+  std::string GetValue(std::string token);
+  void SetExtraData(std::string token);
+  void ShowParseNavigationParams();
+  void CheckResultCb();
+  std::string DecodeUrl(std::string url);
+
+  EWebView* webview_;
+#if BUILDFLAG(IS_TIZEN)
+  app_control_h app_control_;
+#endif
+  std::string intercepted_url_;
+  std::string operation_;
+  std::string uri_;
+  std::string mime_;
+  std::string app_id_;
+  std::string launch_mode_;
+  std::string fallback_url_;
+  bool explicit_category;
+  std::map<std::string, std::string> extra_data_;
+};
+
+#endif  // ewk_app_control_private_h
index ef02ab9..50a4a39 100644 (file)
@@ -291,6 +291,10 @@ double Ewk_Context::GetDefaultZoomFactor() const {
   return impl->GetDefaultZoomFactor();
 }
 
+void Ewk_Context::EnableAppControl(bool enabled) {
+  impl->EnableAppControl(enabled);
+}
+
 #if BUILDFLAG(IS_TIZEN_TV)
 void Ewk_Context::SetApplicationType(
     const Ewk_Application_Type application_type) {
index 811d426..b991e58 100644 (file)
@@ -153,6 +153,8 @@ struct Ewk_Context : public base::RefCounted<Ewk_Context> {
   Ewk_Application_Type GetApplicationType() const;
 #endif
 
+  void EnableAppControl(bool enabled);
+
  private:
   EWebContext* impl;
 
index 8f1b688..9288686 100644 (file)
@@ -962,9 +962,9 @@ void ewk_context_service_worker_unregister(Ewk_Context *context, const char* sco
   LOG_EWK_API_MOCKUP();
 }
 
-void ewk_context_enable_app_control(Ewk_Context *context, Eina_Bool enabled)
-{
-  LOG_EWK_API_MOCKUP();
+void ewk_context_enable_app_control(Ewk_Context* context, Eina_Bool enabled) {
+  EINA_SAFETY_ON_NULL_RETURN(context);
+  context->EnableAppControl(enabled);
 }
 
 void ewk_context_form_autofill_credit_card_changed_callback_set(