[M108 Aura Migration][NaCl][PPFwk] Enable VD Trusted Plugins functionality 27/289527/3
authorXiaoshu Wei <xiaoshu.wei@samsung.com>
Thu, 9 Mar 2023 07:26:39 +0000 (15:26 +0800)
committerBot Blink <blinkbot@samsung.com>
Mon, 13 Mar 2023 04:21:40 +0000 (04:21 +0000)
Migrated from tizen 7.0:
https://review.tizen.org/gerrit/#/c/279658/

Change-Id: Id0dcc051a1fbc83f0180b4419b31c7b96c594a42
Signed-off-by: Xiaoshu Wei <xiaoshu.wei@samsung.com>
109 files changed:
chrome/renderer/chrome_content_renderer_client.cc
components/nacl/features.gni
content/browser/plugin_service_impl.cc
content/browser/plugin_service_impl.h
content/ppapi_plugin/ppapi_plugin_main.cc
content/public/common/content_plugin_info.cc
content/public/common/content_plugin_info.h
content/public/renderer/content_renderer_client.cc
content/renderer/pepper/pepper_plugin_instance_impl.cc
content/renderer/pepper/pepper_plugin_instance_impl.h
content/renderer/pepper/pepper_plugin_registry.cc
content/renderer/pepper/pepper_plugin_registry.h
content/renderer/pepper/plugin_module.cc
electron/shell/app/electron_content_client.cc
packaging/chromium-efl.spec
packaging/chromium-tizen_ppapi_extension_unittests.manifest [new file with mode: 0644]
ppapi/BUILD.gn
ppapi/PRESUBMIT.py
ppapi/api/samsung/ppb_extension_system_samsung.idl [new file with mode: 0644]
ppapi/api/samsung/ppb_remote_controller_samsung.idl [new file with mode: 0644]
ppapi/buildflags/buildflags.gni
ppapi/c/samsung/ppb_extension_system_samsung.h [new file with mode: 0644]
ppapi/c/samsung/ppb_remote_controller_samsung.h [new file with mode: 0644]
ppapi/cpp/samsung/extension_system_samsung.cc [new file with mode: 0644]
ppapi/cpp/samsung/extension_system_samsung.h [new file with mode: 0644]
ppapi/cpp/samsung/extension_system_samsung_tizen.cc [new file with mode: 0644]
ppapi/cpp/samsung/extension_system_samsung_tizen.h [new file with mode: 0644]
ppapi/cpp/samsung/extension_system_samsung_wrt.cc [new file with mode: 0644]
ppapi/cpp/samsung/extension_system_samsung_wrt.h [new file with mode: 0644]
ppapi/cpp/samsung/remote_controller_samsung.cc [new file with mode: 0644]
ppapi/cpp/samsung/remote_controller_samsung.h [new file with mode: 0644]
ppapi/generators/idl_parser.py
ppapi/generators/idl_thunk.py
ppapi/proxy/BUILD.gn
ppapi/proxy/extension_system_resource.cc [new file with mode: 0644]
ppapi/proxy/extension_system_resource.h [new file with mode: 0644]
ppapi/proxy/interface_list.cc
ppapi/proxy/ppapi_messages.h
ppapi/proxy/ppb_instance_proxy.cc
ppapi/proxy/remote_controller_resource.cc [new file with mode: 0644]
ppapi/proxy/remote_controller_resource.h [new file with mode: 0644]
ppapi/proxy/var_value_converter.cc [new file with mode: 0644]
ppapi/proxy/var_value_converter.h [new file with mode: 0644]
ppapi/proxy/var_value_converter_unittest.cc [new file with mode: 0644]
ppapi/shared_impl/resource.h
ppapi/shared_impl/singleton_resource_id.h
ppapi/tests/all_c_includes.h
ppapi/tests/all_cpp_includes.h
ppapi/thunk/BUILD.gn
ppapi/thunk/interfaces_ppb_samsung.h [new file with mode: 0644]
ppapi/thunk/ppb_extension_system_samsung_api.h [new file with mode: 0644]
ppapi/thunk/ppb_extension_system_samsung_thunk.cc [new file with mode: 0644]
ppapi/thunk/ppb_remote_controller_samsung_api.h [new file with mode: 0644]
ppapi/thunk/ppb_remote_controller_samsung_thunk.cc [new file with mode: 0644]
ppapi/thunk/thunk.h
sandbox/policy/linux/sandbox_linux.cc
sandbox/policy/linux/sandbox_linux.h
tizen_src/build/common.sh
tizen_src/build/config/BUILD.gn
tizen_src/build/gn_chromiumefl.sh
tizen_src/chromium_impl/content/browser/browser_efl.gni
tizen_src/chromium_impl/content/browser/renderer_host/pepper/browser_pepper_host_factory_efl.cc [new file with mode: 0644]
tizen_src/chromium_impl/content/browser/renderer_host/pepper/browser_pepper_host_factory_efl.h [new file with mode: 0644]
tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_extension_system_host.cc [new file with mode: 0644]
tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_extension_system_host.h [new file with mode: 0644]
tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_remote_controller_host.cc [new file with mode: 0644]
tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_remote_controller_host.h [new file with mode: 0644]
tizen_src/chromium_impl/content/browser/renderer_host/pepper/remote_controller_wrt.cc [new file with mode: 0644]
tizen_src/chromium_impl/content/browser/renderer_host/pepper/remote_controller_wrt.h [new file with mode: 0644]
tizen_src/chromium_impl/content/public/browser/extension_system_delegate.cc [new file with mode: 0644]
tizen_src/chromium_impl/content/public/browser/extension_system_delegate.h [new file with mode: 0644]
tizen_src/ewk/efl_integration/BUILD.gn
tizen_src/ewk/efl_integration/common/content_client_efl.cc
tizen_src/ewk/efl_integration/common/content_client_efl.h
tizen_src/ewk/efl_integration/common/content_switches_efl.cc
tizen_src/ewk/efl_integration/common/content_switches_efl.h
tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_info_cache.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_info_cache.h [new file with mode: 0644]
tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_info_cache_unittest.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_util.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_util.h [new file with mode: 0644]
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_view.cc
tizen_src/ewk/efl_integration/eweb_view.h
tizen_src/ewk/efl_integration/ewk_extension_system_delegate.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/ewk_extension_system_delegate.h [new file with mode: 0644]
tizen_src/ewk/efl_integration/ewk_privilege_checker.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/ewk_privilege_checker.h [new file with mode: 0644]
tizen_src/ewk/efl_integration/private/ewk_value_private.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/private/ewk_value_private.h [new file with mode: 0644]
tizen_src/ewk/efl_integration/public/ewk_context.cc
tizen_src/ewk/efl_integration/public/ewk_value.cc
tizen_src/ewk/efl_integration/public/ewk_view.cc
tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.cc
tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.h [new file with mode: 0644]
tizen_src/ewk/efl_integration/renderer/pepper/pepper_shared_memory_message_filter.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/renderer/pepper/pepper_shared_memory_message_filter.h [new file with mode: 0644]
tizen_src/ewk/efl_integration/test/run_all_unittests.cc [new file with mode: 0644]
tizen_src/ewk/unittest/BUILD.gn
tizen_src/ewk/unittest/utc_blink_ewk_array_value.cpp [new file with mode: 0644]
tizen_src/ewk/unittest/utc_blink_ewk_boolean_value.cpp [new file with mode: 0644]
tizen_src/ewk/unittest/utc_blink_ewk_dictionary_value.cpp [new file with mode: 0644]
tizen_src/ewk/unittest/utc_blink_ewk_double_value.cpp [new file with mode: 0644]
tizen_src/ewk/unittest/utc_blink_ewk_int_value.cpp [new file with mode: 0644]
tizen_src/ewk/unittest/utc_blink_ewk_string_value.cpp [new file with mode: 0644]
tizen_src/ewk/unittest/utc_blink_ewk_value_compare.h [new file with mode: 0644]
wrt/src/renderer/wrt_renderer_client.cc

index 2c7ca0d..d6059f1 100644 (file)
@@ -1438,26 +1438,7 @@ bool ChromeContentRendererClient::IsExternalPepperPlugin(
 
 bool ChromeContentRendererClient::IsOriginIsolatedPepperPlugin(
     const base::FilePath& plugin_path) {
-  // Hosting plugins in-process is inherently incompatible with attempting to
-  // process-isolate plugins from different origins.
-  auto* cmdline = base::CommandLine::ForCurrentProcess();
-  if (cmdline->HasSwitch(switches::kPpapiInProcess)) {
-    // The kPpapiInProcess switch should only be used by tests.  In particular,
-    // we expect that the PDF plugin should always be isolated in the product
-    // (and that the switch won't interfere with PDF isolation).
-    CHECK_NE(ChromeContentClient::kPDFPluginPath, plugin_path.value());
-
-    return false;
-  }
-
-#if BUILDFLAG(ENABLE_NACL)
-  // Don't isolate the NaCl plugin (preserving legacy behavior).
-  if (plugin_path.value() == nacl::kInternalNaClPluginFileName)
-    return false;
-#endif
-
-  // Isolate all the other plugins (including the PDF plugin + test plugins).
-  return true;
+  return plugin_path.value() == ChromeContentClient::kPDFPluginPath;
 }
 
 #if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_EXTENSIONS)
index 754b12e..d4c6a68 100644 (file)
@@ -22,10 +22,11 @@ declare_args() {
   # Enables Native Client support.
   #
   # Intentionally and permanently disable nacl on arm64 mac.
-  enable_nacl =
-      checkout_nacl && _cpu_is_supported && target_os != "ios" && !is_android &&
-      !is_fuchsia && !is_castos && !(is_win && host_os != "win") &&
-      !(is_mac && (host_os != "mac" || target_cpu != "x64")) && !use_efl
+  #enable_nacl = !is_ios && !is_android && !is_fuchsia && !is_chromecast &&
+  #              current_cpu != "mipsel" && current_cpu != "mips64el" &&
+  #              !(is_linux && target_cpu == "arm64") && !use_efl
+  #TDDO: When nacl module upload, enable_nacl will be changed.
+  enable_nacl = false
 }
 
 assert(!(is_win && host_os != "win") || !enable_nacl,
index ab3e8c8..2c3f337 100644 (file)
@@ -342,6 +342,16 @@ void PluginServiceImpl::RegisterPluginCrash(const base::FilePath& path) {
   i->second.push_back(time);
 }
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+void PluginServiceImpl::AddPepperPlugins(
+    const std::vector<ContentPluginInfo>& plugins) {
+  for (const auto& plugin : plugins) {
+    plugins_.push_back(plugin);
+    RegisterInternalPlugin(plugin.ToWebPluginInfo(), true);
+  }
+}
+#endif
+
 bool PluginServiceImpl::IsPluginUnstable(const base::FilePath& path) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   std::map<base::FilePath, std::vector<base::Time> >::const_iterator i =
index e179b53..5b8305e 100644 (file)
@@ -97,6 +97,10 @@ class CONTENT_EXPORT PluginServiceImpl : public PluginService {
   // Used to monitor plugin stability.
   void RegisterPluginCrash(const base::FilePath& plugin_path);
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+  void AddPepperPlugins(const std::vector<ContentPluginInfo>& plugins);
+#endif
+
   // For testing without creating many, many processes.
   void SetMaxPpapiProcessesPerProfileForTesting(int number) {
     max_ppapi_processes_per_profile_ = number;
index 86e093a..d3bd543 100644 (file)
@@ -136,7 +136,12 @@ int PpapiPluginMain(MainFunctionParams parameters) {
   setenv("HOME", homedir.value().c_str(), 1);
 #endif
 
+#if defined(USE_EFL) && defined(TIZEN_PEPPER_EXTENSIONS)
+  base::SingleThreadTaskExecutor main_thread_task_executor(
+      base::MessagePumpType::ECORE);
+#else
   base::SingleThreadTaskExecutor main_thread_task_executor;
+#endif
   base::PlatformThread::SetName("CrPPAPIMain");
   base::trace_event::TraceLog::GetInstance()->set_process_name("PPAPI Process");
   base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex(
index a598bcf..2637fde 100644 (file)
@@ -17,8 +17,8 @@ ContentPluginInfo::EntryPoints::EntryPoints() = default;
 
 ContentPluginInfo::ContentPluginInfo() = default;
 ContentPluginInfo::ContentPluginInfo(const ContentPluginInfo& other) = default;
-ContentPluginInfo::ContentPluginInfo(ContentPluginInfo&& other) noexcept =
-    default;
+//ContentPluginInfo::ContentPluginInfo(ContentPluginInfo&& other) noexcept =
+//    default;
 ContentPluginInfo::~ContentPluginInfo() = default;
 
 WebPluginInfo ContentPluginInfo::ToWebPluginInfo() const {
index 7d018f2..e3f5b55 100644 (file)
@@ -44,7 +44,7 @@ struct CONTENT_EXPORT ContentPluginInfo {
 
   ContentPluginInfo();
   ContentPluginInfo(const ContentPluginInfo& other);
-  ContentPluginInfo(ContentPluginInfo&& other) noexcept;
+//  ContentPluginInfo(ContentPluginInfo&& other) noexcept;
   ~ContentPluginInfo();
 
   WebPluginInfo ToWebPluginInfo() const;
index e1925ba..c677267 100644 (file)
@@ -4,10 +4,8 @@
 
 #include "content/public/renderer/content_renderer_client.h"
 
-#include "base/command_line.h"
 #include "build/build_config.h"
 #include "components/cast_streaming/renderer/public/resource_provider.h"
-#include "content/public/common/content_switches.h"
 #include "media/base/demuxer.h"
 #include "media/base/renderer_factory.h"
 #include "third_party/blink/public/common/security/protocol_handler_security_level.h"
@@ -147,13 +145,7 @@ bool ContentRendererClient::IsExternalPepperPlugin(
 
 bool ContentRendererClient::IsOriginIsolatedPepperPlugin(
     const base::FilePath& plugin_path) {
-  // Hosting plugins in-process is inherently incompatible with attempting to
-  // process-isolate plugins from different origins.
-  auto* cmdline = base::CommandLine::ForCurrentProcess();
-  if (cmdline->HasSwitch(switches::kPpapiInProcess))
-    return false;
-
-  return true;
+  return false;
 }
 
 void ContentRendererClient::GetSupportedKeySystems(
index 67e3034..8218fcd 100644 (file)
@@ -741,6 +741,9 @@ void PepperPluginInstanceImpl::FinishedConsumingCommittedTexture(
 }
 
 void PepperPluginInstanceImpl::InstanceCrashed() {
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+  SendCrashEvent();
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
   // Force free all resources and vars.
   HostGlobals::Get()->InstanceCrashed(pp_instance());
 
@@ -2086,8 +2089,10 @@ ppapi::Resource* PepperPluginInstanceImpl::GetSingletonResource(
   // Some APIs aren't implemented in-process.
   switch (id) {
     case ppapi::BROWSER_FONT_SINGLETON_ID:
+    case ppapi::EXTENSION_SYSTEM_SINGLETON_ID:
     case ppapi::ISOLATED_FILESYSTEM_SINGLETON_ID:
     case ppapi::NETWORK_PROXY_SINGLETON_ID:
+    case ppapi::REMOTE_CONTROLLER_SINGLETON_ID:
       NOTIMPLEMENTED();
       return nullptr;
     case ppapi::GAMEPAD_SINGLETON_ID:
@@ -2771,4 +2776,37 @@ void PepperPluginInstanceImpl::SetVolume(double volume) {
   audio_controller().SetVolume(volume);
 }
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+void PepperPluginInstanceImpl::SendCrashEventOnMainThread() {
+  LOG(WARNING) << "Sending event crash";
+  // It's possible that container() is NULL if the plugin has been removed from
+  // the DOM (but the PluginInstance is not destroyed yet).
+  if (!container_) {
+    LOG(WARNING) << "No container information, can't send crash event";
+    return;
+  }
+
+  blink::WebLocalFrame* frame =
+      container_->GetElement().GetDocument().GetFrame();
+  if (!frame) {
+    LOG(WARNING) << "Failed to acquire frame, can't send crash event";
+    return;
+  }
+  v8::HandleScope handle_scope(GetIsolate());
+  v8::Local<v8::Context> context(GetIsolate()->GetCurrentContext());
+  if (context.IsEmpty()) {
+    // If there's no JavaScript on the stack, we have to make a new Context.
+    context = v8::Context::New(GetIsolate());
+  }
+  v8::Context::Scope context_scope(context);
+  container_->DispatchProgressEvent(WebString::FromUTF8("crash"), true, 1, 1,
+                                    WebString::FromUTF8(""));
+}
+
+void PepperPluginInstanceImpl::SendCrashEvent() {
+  ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&PepperPluginInstanceImpl::SendCrashEventOnMainThread, this));
+}
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
 }  // namespace content
index 8a29df0..e191cc2 100644 (file)
@@ -610,6 +610,11 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
   // Whether a given viz::TransferableResource is in use by |texture_layer_|.
   bool IsTextureInUse(const viz::TransferableResource& resource) const;
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+  void SendCrashEvent();
+  void SendCrashEventOnMainThread();
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+
   RenderFrameImpl* render_frame_;
   scoped_refptr<PluginModule> module_;
   std::unique_ptr<ppapi::PPP_Instance_Combined> instance_interface_;
index 07bd3a0..9b9e730 100644 (file)
 #include "content/renderer/pepper/plugin_module.h"
 #include "ppapi/shared_impl/ppapi_permissions.h"
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include <algorithm>
+#endif
+
 namespace content {
 
 // static
@@ -106,6 +110,13 @@ PepperPluginRegistry::~PepperPluginRegistry() {
 
 PepperPluginRegistry::PepperPluginRegistry() {}
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+void PepperPluginRegistry::AddOutOfProcessPlugins(
+    const std::vector<ContentPluginInfo>& plugins) {
+  std::copy(plugins.begin(), plugins.end(), std::back_inserter(plugin_list_));
+}
+#endif
+
 void PepperPluginRegistry::Initialize() {
   ComputePepperPluginList(&plugin_list_);
 
index cc490dd..6f7d160 100644 (file)
@@ -7,6 +7,10 @@
 
 #include <map>
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include <vector>
+#endif
+
 #include "base/memory/ref_counted.h"
 #include "content/public/common/content_plugin_info.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -54,6 +58,12 @@ class PepperPluginRegistry {
 
   void PluginModuleDead(PluginModule* dead_module);
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+  // Adds out-of-process plugins which became available after registry
+  // has been initialized
+  void AddOutOfProcessPlugins(const std::vector<ContentPluginInfo>& plugins);
+#endif
+
  private:
   PepperPluginRegistry();
   void Initialize();
index f8831ab..4da1144 100644 (file)
 #include "ppapi/thunk/enter.h"
 #include "ppapi/thunk/ppb_graphics_2d_api.h"
 #include "ppapi/thunk/thunk.h"
+
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "ppapi/c/samsung/ppb_extension_system_samsung.h"
+#include "ppapi/c/samsung/ppb_remote_controller_samsung.h"
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_view.h"
@@ -297,6 +303,9 @@ const void* InternalGetInterface(const char* name) {
 #include "ppapi/thunk/interfaces_ppb_public_dev_channel.h"
 #include "ppapi/thunk/interfaces_ppb_public_socket.h"
 #include "ppapi/thunk/interfaces_ppb_public_stable.h"
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "ppapi/thunk/interfaces_ppb_samsung.h"
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
 
 #undef PROXIED_IFACE
 
index 4371515..2686f14 100644 (file)
@@ -45,7 +45,7 @@
 #if BUILDFLAG(ENABLE_PLUGINS)
 #if defined(ENABLE_WRT_JS)
 namespace content {
-struct PepperPluginInfo;
+struct ContentPluginInfo;
 }
 #else
 #include "content/public/common/content_plugin_info.h"
index 5506c64..6a4b46e 100755 (executable)
@@ -161,6 +161,8 @@ BuildRequires: pkgconfig(aul-extension)
 BuildRequires: pkgconfig(capi-media-sound-manager)
 BuildRequires: pkgconfig(capi-stt-wrapper-tv)
 BuildRequires: pkgconfig(capi-system-display-rotator)
+BuildRequires: pkgconfig(capi-appfw-app-manager)
+BuildRequires: pkgconfig(cynara-client)
 BuildRequires: pkgconfig(drmdecrypt)
 BuildRequires: pkgconfig(efl-assist)
 BuildRequires: pkgconfig(lwipc)
@@ -330,6 +332,15 @@ Requires: %{name} = %{version}-%{release}
 Chromium EFL unit test utilities
 %endif
 
+%if 0%{?build_tizen_ppapi_extension_unittests}
+%package tizen_ppapi_extension_unittests
+Summary: Chromium tizen ppapi extension unittests
+Group: Development/UnitTests
+Requires: %{name} = %{version}-%{release}
+%description tizen_ppapi_extension_unittests
+Chromium tizen ppapi extension unit test utilities
+%endif
+
 # The macros '%TZ_' are valid from tizen v3.0
 %define _pkgid org.tizen.%{name}
 %define _xmldir %TZ_SYS_RO_PACKAGES
@@ -497,6 +508,10 @@ ninja %{_smp_mflags} -C "%{OUTPUT_FOLDER}" \
 %if 0%{?build_ewk_unittests}
   ewk_unittests \
 %endif
+%if 0%{?build_tizen_ppapi_extension_unittests}
+  efl_integration_unittests \
+  ppapi_unittests \
+%endif
 %if 0%{?__enable_wrt_js}
   wrt wrt-service wrt-service-launcher \
 %endif
@@ -514,6 +529,7 @@ ninja %{_smp_mflags} -C "%{OUTPUT_FOLDER}" \
 
 %if 0%{?_enable_unittests}
 ninja %{_smp_mflags} -C"%{OUTPUT_FOLDER}" angle_unittests env_chromium_unittests cacheinvalidation_unittests \
+  angle_unittests env_chromium_unittests cacheinvalidation_unittests \
   url_unittests sandbox_linux_unittests crypto_unittests sql_unittests accessibility_unittests \
   gfx_unittests printing_unittests events_unittests ppapi_unittests jingle_unittests \
   flip_in_mem_edsm_server_unittests breakpad_unittests dbus_unittests libphonenumber_unittests \
@@ -538,6 +554,13 @@ cp third_party/icu/android/icudtl.dat "%{OUTPUT_FOLDER}"
 if [ ! -d %{buildroot}/../../OTHER/ -a -f /opt/testing/bin/rpmlint ]; then
    mkdir -p %{buildroot}/../../OTHER/
 fi
+# Running unittests
+%if 0%{?run_unittests_in_gbs}
+%if 0%{?build_tizen_ppapi_extension_unittests}
+%{OUTPUT_FOLDER}/efl_integration_unittests
+%{OUTPUT_FOLDER}/ppapi_unittests
+%endif
+%endif
 
 echo %{version} > "%{OUTPUT_FOLDER}"/version
 
@@ -786,6 +809,11 @@ install -m 0644 "%{OUTPUT_FOLDER}"/ewk_unittests %{buildroot}/opt/usr/utc_exec/
 install -m 0755 tizen_src/ewk/utc_gtest_run.sh %{buildroot}/opt/usr/utc_exec/
 %endif
 
+%if 0%{?build_tizen_ppapi_extension_unittests}
+mkdir -p %{buildroot}/opt/usr/utc_exec/
+install -m 0755 -p -D %{OUTPUT_FOLDER}/efl_integration_unittests %{buildroot}/opt/usr/utc_exec/
+install -m 0755 -p -D %{OUTPUT_FOLDER}/ppapi_unittests %{buildroot}/opt/usr/utc_exec/
+%endif
 %if 0%{?__enable_wrt_js}
   %define __wrt_resourcedir %{CHROMIUM_LIB_DIR}/wrt
   %if "%{?tizen_profile_name}" != "tv"
@@ -1131,3 +1159,14 @@ rm -rf %{CHROMIUM_TPK_DIR}/%{_tpk_file_name}.tpk
 /opt/usr/utc_exec/*
 /opt/usr/resources/*
 %endif
+
+%if "%{chromium_efl_tizen_profile}" == "tv"
+ln -s %{CHROMIUM_EXE_DIR}/efl_webprocess %{buildroot}%{CHROMIUM_EXE_DIR}/efl_pluginprocess
+%endif
+
+%if 0%{?build_tizen_ppapi_extension_unittests}
+%files tizen_ppapi_extension_unittests
+%defattr(-,root,root,-)
+%manifest ./packaging/chromium-tizen_ppapi_extension_unittests.manifest
+/opt/usr/utc_exec/*
+%endif
diff --git a/packaging/chromium-tizen_ppapi_extension_unittests.manifest b/packaging/chromium-tizen_ppapi_extension_unittests.manifest
new file mode 100644 (file)
index 0000000..4ef1828
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+  <request>
+    <domain name="_"/>
+  </request>
+</manifest>
\ No newline at end of file
index dbe25b5..72d22fc 100644 (file)
@@ -293,6 +293,12 @@ test("ppapi_unittests") {
     "shared_impl/var_tracker_unittest.cc",
   ]
 
+  if(tizen_pepper_extensions == 1 && enable_plugins == 1) {
+    sources += [
+      "proxy/var_value_converter_unittest.cc",
+    ]
+  }
+
   deps = [
     "//base/test:test_support",
     "//gpu/ipc/common:command_buffer_traits",
index 4086c41..fa32c09 100644 (file)
@@ -196,7 +196,9 @@ def CheckHistogramXml(input_api, output_api):
                      'ppapi/thunk/interfaces_ppb_public_dev_channel.h',
                      'ppapi/thunk/interfaces_ppb_public_dev.h',
                      'ppapi/thunk/interfaces_ppb_public_stable.h',
-                     'ppapi/thunk/interfaces_ppb_public_socket.h')
+                     'ppapi/thunk/interfaces_ppb_public_socket.h',
+                     'ppapi/thunk/interfaces_ppb_samsung.h')
+
   HISTOGRAM_XML_FILE = 'tools/metrics/histograms/enums.xml'
   interface_changes = []
   has_histogram_xml_change = False
diff --git a/ppapi/api/samsung/ppb_extension_system_samsung.idl b/ppapi/api/samsung/ppb_extension_system_samsung.idl
new file mode 100644 (file)
index 0000000..bb2c190
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2016 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.
+/**
+ * This file defines the <code>PPB_ExtensionSystem_Samsung</code> interface.
+ */
+
+[generate_thunk]
+
+label Chrome {
+   M35 = 0.1
+ };
+
+/**
+ * The PPB_ExtensionSystem_Samsung interface contains pointers to functions
+ * related to the extension system. The extension system can be different for
+ * each browser.
+ */
+ [singleton]
+interface PPB_ExtensionSystem_Samsung {
+  /**
+   * GetEmbedderName() provides string with embedder name (embedder of current
+   * extension). "Chrome", "TizenWRT", "ExtensionEngine" are one of possible
+   * values.
+   *
+   * @param[in] instance A <code>PP_Instance</code> identifying one instance
+   * of a module.
+   *
+   * @return A <code>PP_Var</code> with name of extension embedder.
+   */
+  PP_Var GetEmbedderName(
+      [in] PP_Instance instance);
+
+  /**
+   * GetCurrentExtensionInfo() gets dictionary with information for current
+   * extension. Keys and values of the dictionary are dependant on the
+   * embedder, and they can differ between embedders. If current embedder does
+   * not support extension system undefined value is returned.
+   *
+   * @param[in] instance A <code>PP_Instance</code> identifying one instance
+   * of a module.
+   *
+   * @return A <code>PP_Var</code> with information of current extension.
+   */
+  PP_Var GetCurrentExtensionInfo(
+      [in] PP_Instance instance);
+
+  /**
+   * GenericSyncCall() executes operation associated with the current
+   * extension. The operation is synchronous and blocks the caller until
+   * completes. See embedder documentation to know what operations are
+   * possible.
+   *
+   * @param[in] instance A <code>PP_Instance</code> identifying one instance
+   * of a module.
+   * @param[in] operation_name A string with name of operation to execute.
+   * @param[in] operation_argument A variable to be passed to embedder
+   * @param[out] result A variable containing result of execution (embedder
+   * defined).
+   *
+   * @return An int32_t containing an error code from <code>pp_errors.h</code>.
+   */
+  int32_t GenericSyncCall(
+      [in] PP_Instance instance,
+      [in] PP_Var operation_name,
+      [in] PP_Var operation_argument,
+      [out] PP_Var result);
+};
diff --git a/ppapi/api/samsung/ppb_remote_controller_samsung.idl b/ppapi/api/samsung/ppb_remote_controller_samsung.idl
new file mode 100644 (file)
index 0000000..8bd9463
--- /dev/null
@@ -0,0 +1,93 @@
+/* Copyright 2016 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.
+ */
+
+/**
+ * This file defines <code>PPB_RemoteController_Samsung</code> interface,
+ * which can be used for various actions related to TV Remote Controller like
+ * registering for input Keys.
+ *
+ * See
+ * <code>https://www.samsungdforum.com/TizenGuide/tizen231/index.html</code>
+ * for description of Remote Controller and its keys.
+ */
+
+[generate_thunk]
+
+label Chrome {
+  M47 = 0.1
+};
+
+/**
+ * The PPB_RemoteControl_Samsung interface contains pointer to functions
+ * related to Remote Controller.
+ *
+ * See
+ * <code>https://www.samsungdforum.com/TizenGuide/tizen231/index.html</code>
+ * for description of Remote Controller and its keys.
+ */
+[singleton]
+interface PPB_RemoteController_Samsung {
+  /**
+   * RegisterKeys() function registers given key arrays to be grabbed by
+   * the application/widget containing pepper plugin calling this method.
+   *
+   * <strong>Note:</strong>
+   * After registering for grabbing keys, events related to that key
+   * will be delivered directly to the application/widget.
+   *
+   * <strong>Note:</strong>
+   * For some embedders, we can`t tell if key that we try to register have
+   * failed because it have been already registered. So if at least one key
+   * have been successfully processed, we assume that other keys that failed,
+   * have been already registered before this call.
+   *
+   * @param[in] instance A <code>PP_Instance</code> identifying instance
+   * of the module
+   * @param[in] key_count A number of keys which will be grabbed.
+   * @param[in] keys An array containing list of keys which should be grabbed.
+   *
+   * @return An int32_t containing an error code from <code>pp_errors.h</code>.
+   * Returns <code>PP_ERROR_BADARGUMENT</code> if <code>key_count</code> is
+   * equal 0 or one of <code>keys</code> is not supported anymore.
+   * Returns <code>PP_ERROR_NOTSUPPORTED</code> if currently launched embedder
+   * doesn`t support key registering.
+   * Returns <code>PP_ERROR_FAILED</code> if registering all <code>keys</code>
+   * have failed.
+   * Returns <code>PP_OK</code> if at lest one key from <code>keys</code> have
+   * been registered.
+   */
+   int32_t RegisterKeys([in] PP_Instance instance,
+                        [in] uint32_t key_count,
+                        [in, size_as=key_count] str_t[] keys);
+
+  /**
+   * UnregisterKeys() function unregisters given key arrays from being grabbed
+   * by the application/widget containing pepper plugin calling this method.
+   *
+   * <strong>Note:</strong>
+   * For some embedders, we can`t tell if key that we try to unregister have
+   * failed because it have been already unregistered. So if at least one key
+   * have been successfully processed, we assume that other keys that failed,
+   * have been already unregistered before this call.
+   *
+   * @param[in] instance A <code>PP_Instance</code> identifying instance
+   * of the module
+   * @param[in] key_count A number of keys which will be grabbed.
+   * @param[in] keys An array containing list of keys which should be grabbed.
+   *
+   * @return An int32_t containing an error code from <code>pp_errors.h</code>.
+   * Returns <code>PP_ERROR_BADARGUMENT</code> if <code>key_count</code> is
+   * equal 0 or one of <code>keys</code> is not supported anymore.
+   * Returns <code>PP_ERROR_NOTSUPPORTED</code> if currently launched embedder
+   * doesn`t support key registering.
+   * Returns <code>PP_ERROR_FAILED</code> if registering all <code>keys</code>
+   * have failed.
+   * Returns <code>PP_OK</code> if at lest one key from <code>keys</code> have
+   * been registered.
+   */
+  int32_t UnRegisterKeys([in] PP_Instance instance,
+                         [in] uint32_t key_count,
+                         [in, size_as=key_count] str_t[] keys);
+};
index 9f1cc34..7996a36 100644 (file)
@@ -11,7 +11,7 @@ declare_args() {
   #
   # In particular, the PDF viewer (enable_pdf) requires plugin support, but it
   # does not require Pepper support (enable_ppapi).
-  enable_plugins = !is_android && !is_ios && !is_castos
+  enable_plugins = is_tizen || (!is_android && !is_ios && !is_castos)
 }
 
 declare_args() {
diff --git a/ppapi/c/samsung/ppb_extension_system_samsung.h b/ppapi/c/samsung/ppb_extension_system_samsung.h
new file mode 100644 (file)
index 0000000..d3d55cd
--- /dev/null
@@ -0,0 +1,85 @@
+/* Copyright (c) 2016 Samsung Electronics. All rights reserved.
+ */
+
+/* From samsung/ppb_extension_system_samsung.idl,
+ *   modified Thu Feb 25 15:18:37 2016.
+ */
+
+#ifndef PPAPI_C_SAMSUNG_PPB_EXTENSION_SYSTEM_SAMSUNG_H_
+#define PPAPI_C_SAMSUNG_PPB_EXTENSION_SYSTEM_SAMSUNG_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_macros.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_var.h"
+
+#define PPB_EXTENSIONSYSTEM_SAMSUNG_INTERFACE_0_1 \
+  "PPB_ExtensionSystem_Samsung;0.1"
+#define PPB_EXTENSIONSYSTEM_SAMSUNG_INTERFACE \
+  PPB_EXTENSIONSYSTEM_SAMSUNG_INTERFACE_0_1
+
+/**
+ * @file
+ * This file defines the <code>PPB_ExtensionSystem_Samsung</code> interface.
+ */
+
+/**
+ * @addtogroup Interfaces
+ * @{
+ */
+/**
+ * The PPB_ExtensionSystem_Samsung interface contains pointers to functions
+ * related to the extension system. The extension system can be different for
+ * each browser.
+ */
+struct PPB_ExtensionSystem_Samsung_0_1 {
+  /**
+   * GetEmbedderName() provides string with embedder name (embedder of current
+   * extension).
+   *
+   * @param[in] instance A <code>PP_Instance</code> identifying one instance
+   * of a module.
+   *
+   * @return A <code>PP_Var</code> with name of extension embedder.
+   */
+  struct PP_Var (*GetEmbedderName)(PP_Instance instance);
+  /**
+   * GetCurrentExtensionInfo() gets dictionary with information for current
+   * extension. Keys and values of the dictionary are dependant on the
+   * embedder, and they can differ between embedders. If current embedder does
+   * not support extension system undefined value is returned.
+   *
+   * @param[in] instance A <code>PP_Instance</code> identifying one instance
+   * of a module.
+   *
+   * @return A <code>PP_Var</code> with information of current extension.
+   */
+  struct PP_Var (*GetCurrentExtensionInfo)(PP_Instance instance);
+  /**
+   * GenericSyncCall() executes operation associated with the current
+   * extension. The operation is synchronous and blocks the caller until
+   * completes. See embedder documentation to know what operations are
+   * possible.
+   *
+   * @param[in] instance A <code>PP_Instance</code> identifying one instance
+   * of a module.
+   * @param[in] operation_name A string with name of operation to execute.
+   * @param[in] operation_argument A variable to be passed to embedder
+   * @param[out] result A variable containing result of execution (embedder
+   * defined).
+   *
+   * @return An int32_t containing an error code from <code>pp_errors.h</code>.
+   */
+  int32_t (*GenericSyncCall)(PP_Instance instance,
+                             struct PP_Var operation_name,
+                             struct PP_Var operation_argument,
+                             struct PP_Var* result);
+};
+
+typedef struct PPB_ExtensionSystem_Samsung_0_1 PPB_ExtensionSystem_Samsung;
+/**
+ * @}
+ */
+
+#endif /* PPAPI_C_SAMSUNG_PPB_EXTENSION_SYSTEM_SAMSUNG_H_ */
diff --git a/ppapi/c/samsung/ppb_remote_controller_samsung.h b/ppapi/c/samsung/ppb_remote_controller_samsung.h
new file mode 100644 (file)
index 0000000..08fbd3e
--- /dev/null
@@ -0,0 +1,113 @@
+/* Copyright 2016 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.
+ */
+
+/* From samsung/ppb_remote_controller_samsung.idl,
+ *   modified Fri Oct  7 12:45:45 2016.
+ */
+
+#ifndef PPAPI_C_SAMSUNG_PPB_REMOTE_CONTROLLER_SAMSUNG_H_
+#define PPAPI_C_SAMSUNG_PPB_REMOTE_CONTROLLER_SAMSUNG_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_macros.h"
+#include "ppapi/c/pp_stdint.h"
+
+#define PPB_REMOTECONTROLLER_SAMSUNG_INTERFACE_0_1 \
+  "PPB_RemoteController_Samsung;0.1"
+#define PPB_REMOTECONTROLLER_SAMSUNG_INTERFACE \
+  PPB_REMOTECONTROLLER_SAMSUNG_INTERFACE_0_1
+
+/**
+ * @file
+ * This file defines <code>PPB_RemoteController_Samsung</code> interface,
+ * which can be used for various actions related to TV Remote Controller like
+ * registering for input Keys.
+ *
+ * See
+ * <code>https://www.samsungdforum.com/TizenGuide/tizen231/index.html</code>
+ * for description of Remote Controller and its keys.
+ */
+
+/**
+ * @addtogroup Interfaces
+ * @{
+ */
+/**
+ * The PPB_RemoteControl_Samsung interface contains pointer to functions
+ * related to Remote Controller.
+ *
+ * See
+ * <code>https://www.samsungdforum.com/TizenGuide/tizen231/index.html</code>
+ * for description of Remote Controller and its keys.
+ */
+struct PPB_RemoteController_Samsung_0_1 {
+  /**
+   * RegisterKeys() function registers given key arrays to be grabbed by
+   * the application/widget containing pepper plugin calling this method.
+   *
+   * <strong>Note:</strong>
+   * After registering for grabbing keys, events related to that key
+   * will be delivered directly to the application/widget.
+   *
+   * <strong>Note:</strong>
+   * For some embedders, we can`t tell if key that we try to register have
+   * failed because it have been already registered. So if at least one key
+   * have been successfully processed, we assume that other keys that failed,
+   * have been already registered before this call.
+   *
+   * @param[in] instance A <code>PP_Instance</code> identifying instance
+   * of the module
+   * @param[in] key_count A number of keys which will be grabbed.
+   * @param[in] keys An array containing list of keys which should be grabbed.
+   *
+   * @return An int32_t containing an error code from <code>pp_errors.h</code>.
+   * Returns <code>PP_ERROR_BADARGUMENT</code> if <code>key_count</code> is
+   * equal 0 or one of <code>keys</code> is not supported anymore.
+   * Returns <code>PP_ERROR_NOTSUPPORTED</code> if currently launched embedder
+   * doesn`t support key registering.
+   * Returns <code>PP_ERROR_FAILED</code> if registering all <code>keys</code>
+   * have failed.
+   * Returns <code>PP_OK</code> if at lest one key from <code>keys</code> have
+   * been registered.
+   */
+  int32_t (*RegisterKeys)(PP_Instance instance,
+                          uint32_t key_count,
+                          const char* keys[]);
+  /**
+   * UnregisterKeys() function unregisters given key arrays from being grabbed
+   * by the application/widget containing pepper plugin calling this method.
+   *
+   * <strong>Note:</strong>
+   * For some embedders, we can`t tell if key that we try to unregister have
+   * failed because it have been already unregistered. So if at least one key
+   * have been successfully processed, we assume that other keys that failed,
+   * have been already unregistered before this call.
+   *
+   * @param[in] instance A <code>PP_Instance</code> identifying instance
+   * of the module
+   * @param[in] key_count A number of keys which will be grabbed.
+   * @param[in] keys An array containing list of keys which should be grabbed.
+   *
+   * @return An int32_t containing an error code from <code>pp_errors.h</code>.
+   * Returns <code>PP_ERROR_BADARGUMENT</code> if <code>key_count</code> is
+   * equal 0 or one of <code>keys</code> is not supported anymore.
+   * Returns <code>PP_ERROR_NOTSUPPORTED</code> if currently launched embedder
+   * doesn`t support key registering.
+   * Returns <code>PP_ERROR_FAILED</code> if registering all <code>keys</code>
+   * have failed.
+   * Returns <code>PP_OK</code> if at lest one key from <code>keys</code> have
+   * been registered.
+   */
+  int32_t (*UnRegisterKeys)(PP_Instance instance,
+                            uint32_t key_count,
+                            const char* keys[]);
+};
+
+typedef struct PPB_RemoteController_Samsung_0_1 PPB_RemoteController_Samsung;
+/**
+ * @}
+ */
+
+#endif /* PPAPI_C_SAMSUNG_PPB_REMOTE_CONTROLLER_SAMSUNG_H_ */
diff --git a/ppapi/cpp/samsung/extension_system_samsung.cc b/ppapi/cpp/samsung/extension_system_samsung.cc
new file mode 100644 (file)
index 0000000..7e23f80
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2016 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 "ppapi/cpp/samsung/extension_system_samsung.h"
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/samsung/ppb_extension_system_samsung.h"
+#include "ppapi/cpp/module_impl.h"
+
+namespace pp {
+
+namespace {
+
+template <>
+const char* interface_name<PPB_ExtensionSystem_Samsung_0_1>() {
+  return PPB_EXTENSIONSYSTEM_SAMSUNG_INTERFACE_0_1;
+}
+
+}  // namespace
+
+ExtensionSystemSamsung::ExtensionSystemSamsung(const InstanceHandle& instance)
+    : instance_(instance) {}
+
+ExtensionSystemSamsung::~ExtensionSystemSamsung() {}
+
+std::string ExtensionSystemSamsung::GetEmbedderName() const {
+  if (!has_interface<PPB_ExtensionSystem_Samsung_0_1>())
+    return std::string();
+  Var result(PASS_REF,
+             get_interface<PPB_ExtensionSystem_Samsung_0_1>()->GetEmbedderName(
+                 instance_.pp_instance()));
+  return result.is_string() ? result.AsString() : std::string();
+}
+
+Var ExtensionSystemSamsung::GetCurrentExtensionInfo() {
+  if (!has_interface<PPB_ExtensionSystem_Samsung_0_1>())
+    return Var();
+  PP_Var rv =
+      get_interface<PPB_ExtensionSystem_Samsung_0_1>()->GetCurrentExtensionInfo(
+          instance_.pp_instance());
+  return Var(PASS_REF, rv);
+}
+
+Var ExtensionSystemSamsung::GenericSyncCall(const Var& operation_name,
+                                            const Var& operation_data) {
+  if (!has_interface<PPB_ExtensionSystem_Samsung_0_1>())
+    return Var();
+  PP_Var operation_result;
+  int32_t error =
+      get_interface<PPB_ExtensionSystem_Samsung_0_1>()->GenericSyncCall(
+          instance_.pp_instance(), operation_name.pp_var(),
+          operation_data.pp_var(), &operation_result);
+  if (error != PP_OK)
+    return Var();
+  return Var(PASS_REF, operation_result);
+}
+
+}  // namespace pp
diff --git a/ppapi/cpp/samsung/extension_system_samsung.h b/ppapi/cpp/samsung/extension_system_samsung.h
new file mode 100644 (file)
index 0000000..e1c1049
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2016 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 PPAPI_CPP_SAMSUNG_EXTENSION_SYSTEM_SAMSUNG_H_
+#define PPAPI_CPP_SAMSUNG_EXTENSION_SYSTEM_SAMSUNG_H_
+
+#include <string>
+
+#include "ppapi/cpp/instance_handle.h"
+#include "ppapi/cpp/var.h"
+
+/// @file
+/// This file defines APIs related to extension system provided by the browser.
+
+namespace pp {
+
+class ExtensionSystemSamsung {
+ public:
+  /// GetEmbedderName() returns name of the extension system provider.
+  std::string GetEmbedderName() const;
+
+  /// GetCurrentExtensionInfo() returns information about current extension.
+  /// If browser does not support extension system, it will return undefined
+  /// value.
+  Var GetCurrentExtensionInfo();
+
+  /// GenericSyncCall() communicates synchronously with extension system.
+  /// The extension system will execute operation |operation_name| with provided
+  /// arguments |operation_data|. See embedder documentation to know what
+  /// operations are possible.
+  ///
+  /// @param[in] operation_name The name of operation to execute.
+  /// @param[in] operation_data Additional arguments for operation execution.
+  Var GenericSyncCall(const Var& operation_name, const Var& operation_data);
+
+ protected:
+  /// A constructor for creating a <code>ExtensionSystemSamsung</code>.
+  ///
+  /// @param[in] instance The instance with which this resource will be
+  /// associated.
+  explicit ExtensionSystemSamsung(const InstanceHandle& instance);
+
+  /// Destructor.
+  ~ExtensionSystemSamsung();
+
+ private:
+  InstanceHandle instance_;
+};
+
+}  // namespace pp
+
+#endif  // PPAPI_CPP_SAMSUNG_EXTENSION_SYSTEM_SAMSUNG_H_
diff --git a/ppapi/cpp/samsung/extension_system_samsung_tizen.cc b/ppapi/cpp/samsung/extension_system_samsung_tizen.cc
new file mode 100644 (file)
index 0000000..5bdd609
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright 2016 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 "ppapi/cpp/samsung/extension_system_samsung_tizen.h"
+
+namespace {
+const char kCheckPrivilegeOperationName[] = "check_ace_privilege";
+const char kGetWindowIdOperationName[] = "get_window_id";
+#if defined(OS_TIZEN_TV_PRODUCT)
+const char kSetIMERecommendedWordsName[] = "set_ime_recommended_words";
+const char kSetIMERecommendedWordsTypeName[] = "set_ime_recommended_words_type";
+#endif
+}  // namespace
+
+namespace pp {
+ExtensionSystemSamsungTizen::ExtensionSystemSamsungTizen(
+    const InstanceHandle& instance)
+    : ExtensionSystemSamsung(instance) {}
+
+ExtensionSystemSamsungTizen::~ExtensionSystemSamsungTizen() {}
+
+bool ExtensionSystemSamsungTizen::CheckPrivilege(const Var& privilege) {
+  if (!privilege.is_string())
+    return false;
+  std::string privilege_string = privilege.AsString();
+  std::map<std::string, bool>::iterator it =
+      privileges_result_.find(privilege_string);
+  if (it != privileges_result_.end())
+    return it->second;
+  Var call_result = GenericSyncCall(kCheckPrivilegeOperationName, privilege);
+  bool has_privilege = false;
+  if (call_result.is_bool())
+    has_privilege = call_result.AsBool();
+  privileges_result_[privilege_string] = has_privilege;
+  return has_privilege;
+}
+
+#if defined(OS_TIZEN_TV_PRODUCT)
+bool ExtensionSystemSamsungTizen::SetIMERecommendedWords(const Var& words) {
+  Var call_result = GenericSyncCall(kSetIMERecommendedWordsName, words);
+  if (call_result.is_bool())
+    return call_result.AsBool();
+  return false;
+}
+
+bool ExtensionSystemSamsungTizen::SetIMERecommendedWordsType(
+    bool should_enable) {
+  Var enable_var(should_enable);
+  Var call_result =
+      GenericSyncCall(kSetIMERecommendedWordsTypeName, enable_var);
+  if (call_result.is_bool())
+    return call_result.AsBool();
+  return false;
+}
+#endif
+
+int32_t ExtensionSystemSamsungTizen::GetWindowId() {
+  // The 'dummy' variable is not used, but needed because of the signature
+  // of the get_window_id operation.
+  Var call_result = GenericSyncCall(kGetWindowIdOperationName, pp::Var());
+  if (call_result.is_number())
+    return call_result.AsInt();
+  return -1;
+}
+}  // namespace pp
diff --git a/ppapi/cpp/samsung/extension_system_samsung_tizen.h b/ppapi/cpp/samsung/extension_system_samsung_tizen.h
new file mode 100644 (file)
index 0000000..4aeee1a
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2016 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 PPAPI_CPP_SAMSUNG_EXTENSION_SYSTEM_SAMSUNG_TIZEN_H_
+#define PPAPI_CPP_SAMSUNG_EXTENSION_SYSTEM_SAMSUNG_TIZEN_H_
+
+#include <map>
+#include <string>
+
+#include "ppapi/cpp/samsung/extension_system_samsung.h"
+
+/// @file
+/// This file defines APIs related to extension system provided by the Tizen.
+
+namespace pp {
+
+class ExtensionSystemSamsungTizen : public ExtensionSystemSamsung {
+ public:
+  /// A constructor for creating a <code>ExtensionSystemSamsung</code>.
+  ///
+  /// @param[in] instance The instance with which this resource will be
+  /// associated.
+  explicit ExtensionSystemSamsungTizen(const InstanceHandle& instance);
+
+  /// Destructor.
+  ~ExtensionSystemSamsungTizen();
+
+  /// CheckPrivilege() returns true if the current extension has given
+  /// privilege, false otherwise.
+  bool CheckPrivilege(const Var& privilege);
+
+  /// SetIMERecommendedWords() returns true if setting recommended words
+  /// was successful, false otherwise.
+  ///
+  /// @param[in] words Var containing std::string with words to set.
+  bool SetIMERecommendedWords(const Var& words);
+
+  /// SetIMERecommendedWordsType() returns true if setting specified
+  /// IME Recommended Words type was successful, false otherwise.
+  ///
+  /// @param[in] should_enable bool indicating if
+  /// IMERecommendedWordsType should be enabled or disabled.
+  bool SetIMERecommendedWordsType(bool should_enable);
+
+  /// GetWindowId() returns the X window Id for the current window.
+  int32_t GetWindowId();
+
+ private:
+  std::map<std::string, bool> privileges_result_;
+};
+
+}  // namespace pp
+
+#endif  // PPAPI_CPP_SAMSUNG_EXTENSION_SYSTEM_SAMSUNG_TIZEN_H_
diff --git a/ppapi/cpp/samsung/extension_system_samsung_wrt.cc b/ppapi/cpp/samsung/extension_system_samsung_wrt.cc
new file mode 100644 (file)
index 0000000..3875a0c
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2016 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 "ppapi/cpp/samsung/extension_system_samsung_wrt.h"
+
+namespace {
+const char kWrtEmbedderName[] = "TizenWRT";
+}  // namespace
+
+namespace pp {
+ExtensionSystemSamsungWRT::ExtensionSystemSamsungWRT(
+    const InstanceHandle& instance)
+    : ExtensionSystemSamsungTizen(instance) {}
+
+ExtensionSystemSamsungWRT::~ExtensionSystemSamsungWRT() {}
+
+bool ExtensionSystemSamsungWRT::IsValid() const {
+  static bool is_valid = (GetEmbedderName() == kWrtEmbedderName);
+  return is_valid;
+}
+}  // namespace pp
diff --git a/ppapi/cpp/samsung/extension_system_samsung_wrt.h b/ppapi/cpp/samsung/extension_system_samsung_wrt.h
new file mode 100644 (file)
index 0000000..294b488
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2016 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 PPAPI_CPP_SAMSUNG_EXTENSION_SYSTEM_SAMSUNG_WRT_H_
+#define PPAPI_CPP_SAMSUNG_EXTENSION_SYSTEM_SAMSUNG_WRT_H_
+
+#include <map>
+#include <string>
+
+#include "ppapi/cpp/samsung/extension_system_samsung_tizen.h"
+
+/// @file
+/// This file defines APIs related to extension system provided by the WRT.
+
+namespace pp {
+
+class ExtensionSystemSamsungWRT : public ExtensionSystemSamsungTizen {
+ public:
+  /// A constructor for creating a <code>ExtensionSystemSamsung</code>.
+  ///
+  /// @param[in] instance The instance with which this resource will be
+  /// associated.
+  explicit ExtensionSystemSamsungWRT(const InstanceHandle& instance);
+
+  /// Destructor.
+  ~ExtensionSystemSamsungWRT();
+
+  /// IsValid() returns true if this object is valid in this context, i.e.
+  /// current extension system is WRT.
+  bool IsValid() const;
+
+ private:
+  std::map<std::string, bool> privileges_result_;
+};
+
+}  // namespace pp
+
+#endif  // PPAPI_CPP_SAMSUNG_EXTENSION_SYSTEM_SAMSUNG_WRT_H_
diff --git a/ppapi/cpp/samsung/remote_controller_samsung.cc b/ppapi/cpp/samsung/remote_controller_samsung.cc
new file mode 100644 (file)
index 0000000..2de366d
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2016 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 "ppapi/cpp/samsung/remote_controller_samsung.h"
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/cpp/module_impl.h"
+
+namespace pp {
+
+namespace {
+
+template <>
+const char* interface_name<PPB_RemoteController_Samsung_0_1>() {
+  return PPB_REMOTECONTROLLER_SAMSUNG_INTERFACE_0_1;
+}
+
+}  // namespace
+
+RemoteControllerSamsung::RemoteControllerSamsung(const InstanceHandle& instance)
+    : instance_(instance) {}
+
+int32_t RemoteControllerSamsung::RegisterKeys(uint32_t key_count,
+                                              const char* keys[]) {
+  if (!has_interface<PPB_RemoteController_Samsung_0_1>())
+    return PP_ERROR_NOINTERFACE;
+
+  return get_interface<PPB_RemoteController_Samsung_0_1>()->RegisterKeys(
+      instance_.pp_instance(), key_count, keys);
+}
+
+int32_t RemoteControllerSamsung::RegisterKeys(
+    const std::vector<std::string>& keys) {
+  std::vector<const char*> v;
+  v.reserve(keys.size());
+  for (uint32_t i = 0; i < keys.size(); ++i)
+    v.push_back(keys[i].c_str());
+  return RegisterKeys(static_cast<uint32_t>(v.size()), &v[0]);
+}
+
+int32_t RemoteControllerSamsung::UnRegisterKeys(uint32_t key_count,
+                                                const char* keys[]) {
+  if (!has_interface<PPB_RemoteController_Samsung_0_1>())
+    return PP_ERROR_NOINTERFACE;
+
+  return get_interface<PPB_RemoteController_Samsung_0_1>()->UnRegisterKeys(
+      instance_.pp_instance(), key_count, keys);
+}
+
+int32_t RemoteControllerSamsung::UnRegisterKeys(
+    const std::vector<std::string>& keys) {
+  std::vector<const char*> v;
+  v.reserve(keys.size());
+  for (uint32_t i = 0; i < keys.size(); ++i)
+    v.push_back(keys[i].c_str());
+  return UnRegisterKeys(static_cast<uint32_t>(v.size()), &v[0]);
+}
+
+}  // namespace pp
diff --git a/ppapi/cpp/samsung/remote_controller_samsung.h b/ppapi/cpp/samsung/remote_controller_samsung.h
new file mode 100644 (file)
index 0000000..af6e9d6
--- /dev/null
@@ -0,0 +1,129 @@
+// Copyright 2016 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 PPAPI_CPP_SAMSUNG_REMOTE_CONTROLLER_SAMSUNG_H_
+#define PPAPI_CPP_SAMSUNG_REMOTE_CONTROLLER_SAMSUNG_H_
+
+#include <string>
+#include <vector>
+
+#include "ppapi/c/samsung/ppb_remote_controller_samsung.h"
+#include "ppapi/cpp/instance_handle.h"
+
+/// @file
+/// This file defines API related to TV Remote Controller
+
+namespace pp {
+
+class RemoteControllerSamsung {
+ public:
+  /// A constructor for creating a <code>RemoteControllerSamsung</code> class
+  /// for given instance of a module.
+  explicit RemoteControllerSamsung(const InstanceHandle& instance);
+
+  /// RegisterKeys() function registers given key arrays to be grabbed by
+  /// the application/widget containing pepper plugin calling this method.
+  ///
+  /// <strong>Note:</strong>
+  /// After registering for grabbing keys, events related to that key
+  /// will be delivered directly to the application/widget.
+  ///
+  /// <strong>Note:</strong>
+  /// For some embedders, we can`t tell if key that we try to register have
+  /// failed because it have been already registered. So if at least one key
+  /// have been successfully processed, we assume that other keys that failed,
+  /// have been already registered before this call.
+  ///
+  /// @param[in] key_count A number of keys which will be grabbed.
+  /// @param[in] keys An array containing list of keys which should be grabbed.
+  ///
+  /// @return An int32_t containing an error code from <code>pp_errors.h</code>.
+  /// Returns <code>PP_ERROR_BADARGUMENT</code> if <code>key_count</code> is
+  /// equal 0 or one of <code>keys</code> is not supported anymore.
+  /// Returns <code>PP_ERROR_NOTSUPPORTED</code> if currently launched embedder
+  /// doesn`t support key registering.
+  /// Returns <code>PP_ERROR_FAILED</code> if registering all <code>keys</code>
+  /// have failed.
+  /// Returns <code>PP_OK</code> if at lest one key from <code>keys</code> have
+  /// been registered.
+  int32_t RegisterKeys(uint32_t key_count, const char* keys[]);
+
+  /// RegisterKeys() function registers given key arrays to be grabbed by
+  /// the application/widget containing pepper plugin calling this method.
+  ///
+  /// <strong>Note:</strong>
+  /// After registering for grabbing keys, events related to that key
+  /// will be delivered directly to the application/widget.
+  ///
+  /// <strong>Note:</strong>
+  /// For some embedders, we can`t tell if key that we try to register have
+  /// failed because it have been already registered. So if at least one key
+  /// have been successfully processed, we assume that other keys that failed,
+  /// have been already registered before this call.
+  ///
+  /// @param[in] keys A vector containing list of keys which should be grabbed.
+  ///
+  /// @return An int32_t containing an error code from <code>pp_errors.h</code>.
+  /// Returns <code>PP_ERROR_BADARGUMENT</code> if <code>key_count</code> is
+  /// equal 0 or one of <code>keys</code> is not supported anymore.
+  /// Returns <code>PP_ERROR_NOTSUPPORTED</code> if currently launched embedder
+  /// doesn`t support key registering.
+  /// Returns <code>PP_ERROR_FAILED</code> if registering all <code>keys</code>
+  /// have failed.
+  /// Returns <code>PP_OK</code> if at lest one key from <code>keys</code> have
+  /// been registered.
+  int32_t RegisterKeys(const std::vector<std::string>& keys);
+
+  /// UnregisterKeys() function unregisters given key arrays from being grabbed
+  /// by the application/widget containing pepper plugin calling this method.
+  ///
+  /// <strong>Note:</strong>
+  /// For some embedders, we can`t tell if key that we try to unregister have
+  /// failed because it have been already unregistered. So if at least one key
+  /// have been successfully processed, we assume that other keys that failed,
+  /// have been already unregistered before this call.
+  ///
+  /// @param[in] key_count A number of keys which will be grabbed.
+  /// @param[in] keys An array containing list of keys which should be grabbed.
+  ///
+  /// @return An int32_t containing an error code from <code>pp_errors.h</code>.
+  /// Returns <code>PP_ERROR_BADARGUMENT</code> if <code>key_count</code> is
+  /// equal 0 or one of <code>keys</code> is not supported anymore.
+  /// Returns <code>PP_ERROR_NOTSUPPORTED</code> if currently launched embedder
+  /// doesn`t support key registering.
+  /// Returns <code>PP_ERROR_FAILED</code> if registering all <code>keys</code>
+  /// have failed.
+  /// Returns <code>PP_OK</code> if at lest one key from <code>keys</code> have
+  /// been registered.
+  int32_t UnRegisterKeys(uint32_t key_count, const char* keys[]);
+
+  /// UnregisterKeys() function unregisters given key arrays from being grabbed
+  /// by the application/widget containing pepper plugin calling this method.
+  ///
+  /// <strong>Note:</strong>
+  /// For some embedders, we can`t tell if key that we try to unregister have
+  /// failed because it have been already unregistered. So if at least one key
+  /// have been successfully processed, we assume that other keys that failed,
+  /// have been already unregistered before this call.
+  ///
+  /// @param[in] keys A vector containing list of keys which should be grabbed.
+  ///
+  /// @return An int32_t containing an error code from <code>pp_errors.h</code>.
+  /// Returns <code>PP_ERROR_BADARGUMENT</code> if <code>key_count</code> is
+  /// equal 0 or one of <code>keys</code> is not supported anymore.
+  /// Returns <code>PP_ERROR_NOTSUPPORTED</code> if currently launched embedder
+  /// doesn`t support key registering.
+  /// Returns <code>PP_ERROR_FAILED</code> if registering all <code>keys</code>
+  /// have failed.
+  /// Returns <code>PP_OK</code> if at lest one key from <code>keys</code> have
+  /// been registered.
+  int32_t UnRegisterKeys(const std::vector<std::string>& keys);
+
+ private:
+  InstanceHandle instance_;
+};
+
+}  // namespace pp
+
+#endif  // PPAPI_CPP_SAMSUNG_REMOTE_CONTROLLER_SAMSUNG_H_
index f5aa1f6..6dcf2b3 100755 (executable)
@@ -5,6 +5,8 @@
 
 """ Parser for PPAPI IDL """
 
+# Modified by SRPOL, take caution when updating.
+
 #
 # IDL Parser
 #
@@ -1239,7 +1241,7 @@ def TestVersionFiles(filter):
   return errs
 
 
-default_dirs = ['.', 'trusted', 'dev', 'private']
+default_dirs = ['.', 'trusted', 'dev', 'private', 'samsung']
 def ParseFiles(filenames):
   parser = IDLParser()
   filenodes = []
index 3d5d731..89e2217 100755 (executable)
@@ -5,6 +5,8 @@
 
 """ Generator for C++ style thunks """
 
+# Modified by SRPOL, take caution when updating.
+
 from __future__ import print_function
 
 import glob
@@ -101,6 +103,8 @@ def _StripFileName(filenode):
     api_basename = api_basename[:-len('_trusted')]
   if api_basename.endswith('_private'):
     api_basename = api_basename[:-len('_private')]
+  if api_basename.endswith('_samsung'):
+    api_basename = api_basename[:-len('_samsung')]
   return api_basename
 
 
@@ -112,6 +116,8 @@ def _StripApiName(api_name):
     api_name = api_name[:-len('_Dev')]
   if api_name.endswith('_Private'):
     api_name = api_name[:-len('_Private')]
+  if api_name.endswith('_Samsung'):
+    api_name = api_name[:-len('_Samsung')]
   return api_name
 
 
index 21cacd8..34ba497 100644 (file)
@@ -2,6 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+if (is_tizen) {
+  import("//tizen_src/build/config/tizen_features.gni")
+}
 import("//build/config/nacl/config.gni")
 import("//components/nacl/toolchain.gni")
 import("//ppapi/buildflags/buildflags.gni")
@@ -256,6 +259,18 @@ component("proxy") {
       "//ui/surface",
     ]
   }
+  if (is_tizen) {
+    if(tizen_pepper_extensions) {
+      sources += [
+        "extension_system_resource.cc",
+        "extension_system_resource.h",
+        "remote_controller_resource.cc",
+        "remote_controller_resource.h",
+        "var_value_converter.cc",
+        "var_value_converter.h",
+      ]
+    }
+  }
 }
 
 source_set("common") {
diff --git a/ppapi/proxy/extension_system_resource.cc b/ppapi/proxy/extension_system_resource.cc
new file mode 100644 (file)
index 0000000..1cc0953
--- /dev/null
@@ -0,0 +1,136 @@
+// Copyright 2016 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 "ppapi/proxy/extension_system_resource.h"
+
+#include "base/json/json_string_value_serializer.h"
+#include "base/logging.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/raw_var_data.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/proxy/var_value_converter.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+ExtensionSystemResource::ExtensionSystemResource(Connection connection,
+                                                 PP_Instance instance)
+    : PluginResource(connection, instance) {
+  SendCreate(BROWSER, PpapiHostMsg_ExtensionSystem_Create());
+}
+
+ExtensionSystemResource::~ExtensionSystemResource() {}
+
+thunk::PPB_ExtensionSystem_API*
+ExtensionSystemResource::AsPPB_ExtensionSystem_API() {
+  return this;
+}
+
+PP_Var ExtensionSystemResource::GetEmbedderName() {
+  if (!embedder_name_.empty())
+    return StringVar::StringToPPVar(embedder_name_);
+
+  int32_t result =
+      SyncCall<PpapiPluginMsg_ExtensionSystem_GetEmbedderNameReply>(
+          BROWSER, PpapiHostMsg_ExtensionSystem_GetEmbedderName(),
+          &embedder_name_);
+  if (result != PP_OK)
+    return PP_MakeUndefined();
+
+  return StringVar::StringToPPVar(embedder_name_);
+}
+
+PP_Var ExtensionSystemResource::GetCurrentExtensionInfo() {
+  if (current_extension_info_.get().type == PP_VARTYPE_UNDEFINED) {
+    std::string json_result;
+
+    int32_t sync_call_result =
+        SyncCall<PpapiPluginMsg_ExtensionSystem_GetCurrentExtensionInfoReply>(
+            BROWSER, PpapiHostMsg_ExtensionSystem_GetCurrentExtensionInfo(),
+            &json_result);
+    if (sync_call_result != PP_OK)
+      return PP_MakeUndefined();
+
+    base::StringPiece result_str(json_result);
+    JSONStringValueDeserializer json_deserializer(result_str);
+    std::unique_ptr<base::Value> result_ptr(
+        json_deserializer.Deserialize(nullptr, nullptr));
+    if (!result_ptr)
+      return PP_MakeUndefined();
+
+    ScopedPPVar var = VarFromValue(result_ptr.get());
+    if (var.get().type != PP_VARTYPE_DICTIONARY)
+      return PP_MakeUndefined();
+
+    // cache the value of the extension info
+    current_extension_info_ = var;
+  }
+
+  ScopedPPVar info_copy = current_extension_info_;
+  return info_copy.Release();
+}
+
+int32_t ExtensionSystemResource::GenericSyncCall(PP_Var operation_name,
+                                                 PP_Var operation_data,
+                                                 PP_Var* operation_result) {
+  if (!operation_result) {
+    LOG(ERROR) << "Operation result is NULL";
+    return PP_ERROR_BADARGUMENT;
+  }
+  StringVar* op_name = StringVar::FromPPVar(operation_name);
+  if (!op_name) {
+    LOG(ERROR) << "Invalid operation name";
+    return PP_ERROR_BADARGUMENT;
+  }
+  if (op_name->value().empty()) {
+    LOG(ERROR) << "Empty operation name";
+    return PP_ERROR_BADARGUMENT;
+  }
+
+  // We do not support cycles in operation_data parameter.
+  // We check it by trying to create RawVarDataGraph (will return NULL if
+  // operation_data parameter does contain any cycles) because neither
+  // JSONStringValueSerializer or ValueFromVar check for it.
+  std::unique_ptr<RawVarDataGraph> cycle_check(
+      RawVarDataGraph::Create(operation_data, pp_instance()));
+  if (!cycle_check) {
+    LOG(ERROR) << "Cycle detected in operation data";
+    return PP_ERROR_BADARGUMENT;
+  }
+
+  std::string serialized_operation_data;
+  JSONStringValueSerializer json_serializer(&serialized_operation_data);
+  if (!json_serializer.Serialize(*(ValueFromVar(operation_data).get()))) {
+    LOG(ERROR) << "JSON serialization failed";
+    return PP_ERROR_BADARGUMENT;
+  }
+
+  std::string json_result;
+
+  int32_t sync_call_result =
+      SyncCall<PpapiPluginMsg_ExtensionSystem_GenericSyncCallReply>(
+          BROWSER,
+          PpapiHostMsg_ExtensionSystem_GenericSyncCall(
+              op_name->value(), serialized_operation_data),
+          &json_result);
+  if (sync_call_result != PP_OK)
+    return sync_call_result;
+
+  base::StringPiece result_str(json_result);
+  JSONStringValueDeserializer json_deserializer(result_str);
+  std::unique_ptr<base::Value> result_ptr(
+      json_deserializer.Deserialize(nullptr, nullptr));
+  if (!result_ptr) {
+    LOG(ERROR) << "JSON deserialization failed";
+    return PP_ERROR_FAILED;
+  }
+
+  *operation_result = VarFromValue(result_ptr.get()).Release();
+  return PP_OK;
+}
+
+}  // namespace proxy
+}  // namespace ppapi
diff --git a/ppapi/proxy/extension_system_resource.h b/ppapi/proxy/extension_system_resource.h
new file mode 100644 (file)
index 0000000..1eaf846
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2016 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 PPAPI_PROXY_EXTENSION_SYSTEM_RESOURCE_H_
+#define PPAPI_PROXY_EXTENSION_SYSTEM_RESOURCE_H_
+
+#include <string>
+
+#include "ppapi/c/samsung/ppb_extension_system_samsung.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/thunk/ppb_extension_system_samsung_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class ExtensionSystemResource : public PluginResource,
+                                public thunk::PPB_ExtensionSystem_API {
+ public:
+  ExtensionSystemResource(Connection connection, PP_Instance instance);
+
+  ~ExtensionSystemResource() override;
+
+  // Resource implementation.
+  thunk::PPB_ExtensionSystem_API* AsPPB_ExtensionSystem_API() override;
+
+  // PPBExtensionSystemAPI implementation.
+  PP_Var GetEmbedderName() override;
+  PP_Var GetCurrentExtensionInfo() override;
+  int32_t GenericSyncCall(PP_Var operation_name,
+                          PP_Var operation_data,
+                          PP_Var* operation_result) override;
+
+ private:
+  ScopedPPVar current_extension_info_;
+  std::string embedder_name_;
+};
+
+}  // namespace proxy
+}  // namespace ppapi
+
+#endif  // PPAPI_PROXY_EXTENSION_SYSTEM_RESOURCE_H_
index 6bfeb89..9797b5c 100644 (file)
 #include "ppapi/shared_impl/ppb_var_shared.h"
 #include "ppapi/thunk/thunk.h"
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "ppapi/c/samsung/ppb_extension_system_samsung.h"
+#include "ppapi/c/samsung/ppb_remote_controller_samsung.h"
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+
 // Helper to get the proxy name PPB_Foo_Proxy given the API name PPB_Foo.
 #define PROXY_CLASS_NAME(api_name) api_name##_Proxy
 
@@ -168,6 +173,9 @@ InterfaceList::InterfaceList() {
     Permission current_required_permission = PERMISSION_NONE;
     #include "ppapi/thunk/interfaces_ppb_private_no_permissions.h"
     #include "ppapi/thunk/interfaces_ppb_public_stable.h"
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+    #include "ppapi/thunk/interfaces_ppb_samsung.h"
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
   }
   {
     Permission current_required_permission = PERMISSION_DEV;
index e512022..52e73ff 100644 (file)
@@ -84,6 +84,9 @@
 #include "ppapi/shared_impl/url_request_info_data.h"
 #include "ppapi/shared_impl/url_response_info_data.h"
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "ppapi/c/samsung/ppb_remote_controller_samsung.h"
+#endif
 #undef IPC_MESSAGE_EXPORT
 #define IPC_MESSAGE_EXPORT PPAPI_PROXY_EXPORT
 
@@ -1737,6 +1740,34 @@ IPC_MESSAGE_CONTROL1(PpapiPluginMsg_VideoEncoder_NotifyError,
                      int32_t /* error */)
 IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoEncoder_Close)
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+
+// Extension system samsung messages
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_ExtensionSystem_Create)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_ExtensionSystem_GetEmbedderName)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_ExtensionSystem_GetEmbedderNameReply,
+                     std::string /*Embedder name*/)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_ExtensionSystem_GetCurrentExtensionInfo)
+IPC_MESSAGE_CONTROL1(
+    PpapiPluginMsg_ExtensionSystem_GetCurrentExtensionInfoReply,
+    std::string /*extension info dictionary in JSON format*/)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_ExtensionSystem_GenericSyncCall,
+                     std::string /*operation name*/,
+                     std::string /*operation data in JSON format*/)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_ExtensionSystem_GenericSyncCallReply,
+                     std::string /*operation result in JSON format*/)
+
+// Remote Controller Samsung messages
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_RemoteController_Create)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_RemoteController_RegisterKeys,
+                     std::vector<std::string> /* keys */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_RemoteController_RegisterKeysReply)
+
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_RemoteController_UnRegisterKeys,
+                     std::vector<std::string> /* keys */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_RemoteController_UnRegisterKeysReply)
+
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
 #if !BUILDFLAG(IS_NACL) && !defined(NACL_WIN64)
 
 // Audio input.
index 7de78e2..37a791c 100644 (file)
 #include "ppapi/thunk/ppb_graphics_3d_api.h"
 #include "ppapi/thunk/thunk.h"
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "ppapi/proxy/extension_system_resource.h"
+#include "ppapi/proxy/remote_controller_resource.h"
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+
 // Windows headers interfere with this file.
 #ifdef PostMessage
 #undef PostMessage
@@ -326,8 +331,24 @@ Resource* PPB_Instance_Proxy::GetSingletonResource(PP_Instance instance,
     case BROWSER_FONT_SINGLETON_ID:
       new_singleton = new BrowserFontSingletonResource(connection, instance);
       break;
+    case EXTENSION_SYSTEM_SINGLETON_ID:
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+      new_singleton = new ExtensionSystemResource(connection, instance);
+#else
+      NOTREACHED();
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+      break;
+    case REMOTE_CONTROLLER_SINGLETON_ID:
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+      new_singleton = new RemoteControllerResource(connection, instance);
+#else
+      NOTREACHED();
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+      break;
 #else
     case BROWSER_FONT_SINGLETON_ID:
+    case EXTENSION_SYSTEM_SINGLETON_ID:
+    case REMOTE_CONTROLLER_SINGLETON_ID:
       NOTREACHED();
       break;
 #endif  // !BUILDFLAG(IS_NACL) && !defined(NACL_WIN64)
diff --git a/ppapi/proxy/remote_controller_resource.cc b/ppapi/proxy/remote_controller_resource.cc
new file mode 100644 (file)
index 0000000..ce80056
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright 2016 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 "ppapi/proxy/remote_controller_resource.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+int32_t CheckParameters(uint32_t key_count, const char* keys[]) {
+  if (key_count == 0 || !keys) {
+    LOG(ERROR) << "keys is " << keys << ", key_count= " << key_count;
+    return PP_ERROR_BADARGUMENT;
+  }
+
+  for (uint32_t i = 0; i < key_count; ++i) {
+    if (!keys[i]) {
+      LOG(ERROR) << "keys[" << i << "] is NULL";
+      return PP_ERROR_BADARGUMENT;
+    }
+  }
+  return PP_OK;
+}
+
+}  // namespace
+
+RemoteControllerResource::RemoteControllerResource(Connection connection,
+                                                   PP_Instance instance)
+    : PluginResource(connection, instance) {
+  SendCreate(BROWSER, PpapiHostMsg_RemoteController_Create());
+}
+
+RemoteControllerResource::~RemoteControllerResource() = default;
+
+// Resource implementation.
+thunk::PPB_RemoteController_API*
+RemoteControllerResource::AsPPB_RemoteController_API() {
+  return this;
+}
+
+// PPB_RemoteController_API implementation.
+int32_t RemoteControllerResource::RegisterKeys(PP_Instance instance,
+                                               uint32_t key_count,
+                                               const char* keys[]) {
+  int32_t ret = CheckParameters(key_count, keys);
+  if (ret != PP_OK)
+    return ret;
+
+  std::vector<std::string> keys_vec(keys, keys + key_count);
+  return SyncCall<PpapiHostMsg_RemoteController_RegisterKeysReply>(
+      BROWSER, PpapiHostMsg_RemoteController_RegisterKeys(keys_vec));
+}
+
+int32_t RemoteControllerResource::UnRegisterKeys(PP_Instance instance,
+                                                 uint32_t key_count,
+                                                 const char* keys[]) {
+  int32_t ret = CheckParameters(key_count, keys);
+  if (ret != PP_OK)
+    return ret;
+
+  std::vector<std::string> keys_vec(keys, keys + key_count);
+  return SyncCall<PpapiHostMsg_RemoteController_UnRegisterKeysReply>(
+      BROWSER, PpapiHostMsg_RemoteController_UnRegisterKeys(keys_vec));
+}
+
+}  // namespace proxy
+}  // namespace ppapi
diff --git a/ppapi/proxy/remote_controller_resource.h b/ppapi/proxy/remote_controller_resource.h
new file mode 100644 (file)
index 0000000..fa81a75
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2016 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 PPAPI_PROXY_REMOTE_CONTROLLER_RESOURCE_H_
+#define PPAPI_PROXY_REMOTE_CONTROLLER_RESOURCE_H_
+
+#include <string>
+
+#include "ppapi/c/samsung/ppb_remote_controller_samsung.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/thunk/ppb_remote_controller_samsung_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class RemoteControllerResource : public PluginResource,
+                                 public thunk::PPB_RemoteController_API {
+ public:
+  RemoteControllerResource(Connection connection, PP_Instance instance);
+
+  ~RemoteControllerResource() override;
+
+  // Resource implementation.
+  thunk::PPB_RemoteController_API* AsPPB_RemoteController_API() override;
+
+  // PPB_RemoteController_API implementation.
+  int32_t RegisterKeys(PP_Instance instance,
+                       uint32_t key_count,
+                       const char* keys[]) override;
+  int32_t UnRegisterKeys(PP_Instance instance,
+                         uint32_t key_count,
+                         const char* keys[]) override;
+};
+
+}  // namespace proxy
+}  // namespace ppapi
+
+#endif  // PPAPI_PROXY_REMOTE_CONTROLLER_RESOURCE_H_
diff --git a/ppapi/proxy/var_value_converter.cc b/ppapi/proxy/var_value_converter.cc
new file mode 100644 (file)
index 0000000..9e36bde
--- /dev/null
@@ -0,0 +1,171 @@
+// Copyright 2016 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 "ppapi/proxy/var_value_converter.h"
+
+#include <string>
+
+#include "base/memory/ptr_util.h"
+#include "ppapi/shared_impl/array_var.h"
+#include "ppapi/shared_impl/dictionary_var.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+std::unique_ptr<base::Value> ValueFromVarArray(const PP_Var& var) {
+  if (var.type == PP_VARTYPE_ARRAY) {
+    scoped_refptr<ArrayVar> array =
+        scoped_refptr<ArrayVar>(ArrayVar::FromPPVar(var));
+    if (!array) {
+      return std::make_unique<base::Value>();
+    }
+    auto ret = std::make_unique<base::ListValue>();
+    for (size_t i = 0; i < array->GetLength(); ++i) {
+      ScopedPPVar var(ScopedPPVar::PassRef(), array->Get(i));
+      ret->Append(std::move(*ValueFromVar(var.get())));
+    }
+    return std::move(ret);
+  }
+
+  return std::make_unique<base::Value>();
+}
+
+std::unique_ptr<base::Value> ValueFromVarDictionary(const PP_Var& var) {
+  if (var.type == PP_VARTYPE_DICTIONARY) {
+    scoped_refptr<DictionaryVar> dict =
+        scoped_refptr<DictionaryVar>(DictionaryVar::FromPPVar(var));
+    if (!dict) {
+      return std::make_unique<base::Value>();
+    }
+    ScopedPPVar keys_var(ScopedPPVar::PassRef(), dict->GetKeys());
+    scoped_refptr<ArrayVar> keys =
+        scoped_refptr<ArrayVar>(ArrayVar::FromPPVar(keys_var.get()));
+    if (!keys) {
+      return std::make_unique<base::Value>();
+    }
+
+    auto ret = std::make_unique<base::DictionaryValue>();
+    for (size_t i = 0; i < keys->GetLength(); ++i) {
+      ScopedPPVar var_k(ScopedPPVar::PassRef(), keys->Get(i));
+      scoped_refptr<StringVar> key =
+          scoped_refptr<StringVar>(StringVar::FromPPVar(var_k.get()));
+      if (!key) {
+        continue;
+      }
+      std::string key_string = key->value();
+
+      ScopedPPVar var_v(ScopedPPVar::PassRef(), dict->Get(var_k.get()));
+      // SetWithoutPathExpansion is used instead of Set here to allow
+      // e.g. URLs to be used as keys. Set method treats '.' as keys separator.
+      ret->SetKey(key_string, std::move(*ValueFromVar(var_v.get())));
+    }
+    return std::move(ret);
+  }
+
+  return std::make_unique<base::Value>();
+}
+
+ScopedPPVar VarFromValueArray(const base::Value* value) {
+  if (!value)
+    return ScopedPPVar();
+
+  if (value->type() == base::Value::Type::LIST) {
+    scoped_refptr<ArrayVar> ret(new ArrayVar);
+    const base::ListValue* list = static_cast<const base::ListValue*>(value);
+       size_t size = list->GetList().size();
+    ret->SetLength(size);
+    for (size_t i = 0; i < size; ++i) {
+      const base::Value* val;
+      val = const_cast<base::Value*>(&(list->GetList().operator[](i)));
+      ScopedPPVar var = VarFromValue(val);
+      ret->Set(i, var.get());
+    }
+
+    return ScopedPPVar(ScopedPPVar::PassRef(), ret->GetPPVar());
+  }
+
+  return ScopedPPVar();
+}
+
+ScopedPPVar VarFromValueDictionary(const base::Value* value) {
+  if (!value)
+    return ScopedPPVar();
+
+  if (value->type() == base::Value::Type::DICTIONARY) {
+    scoped_refptr<DictionaryVar> ret(new DictionaryVar);
+    const base::DictionaryValue* dict;
+    value->GetAsDictionary(&dict);
+    base::detail::const_dict_iterator it = dict->DictItems().begin();
+    while (it!=dict->DictItems().end()) {
+      ScopedPPVar var_k(ScopedPPVar::PassRef(),
+                        StringVar::StringToPPVar(it->first));
+      ScopedPPVar var_v = VarFromValue(&(it->second));
+      ret->Set(var_k.get(), var_v.get());
+      it++;
+    }
+    return ScopedPPVar(ScopedPPVar::PassRef(), ret->GetPPVar());
+  }
+
+  return ScopedPPVar();
+}
+
+}  // namespace
+
+std::unique_ptr<base::Value> ValueFromVar(const PP_Var& var) {
+  switch (var.type) {
+    case PP_VARTYPE_BOOL:
+      return std::make_unique<base::Value>(PP_ToBool(var.value.as_bool));
+    case PP_VARTYPE_INT32:
+      return std::make_unique<base::Value>(var.value.as_int);
+    case PP_VARTYPE_DOUBLE:
+      return std::make_unique<base::Value>(var.value.as_double);
+    case PP_VARTYPE_STRING: {
+      StringVar* str = StringVar::FromPPVar(var);
+      if (!str)
+        return std::make_unique<base::Value>();
+      return std::make_unique<base::Value>(str->value());
+    }
+    case PP_VARTYPE_ARRAY:
+      return ValueFromVarArray(var);
+    case PP_VARTYPE_DICTIONARY:
+      return ValueFromVarDictionary(var);
+    default:
+      return std::make_unique<base::Value>();
+  }
+}
+
+ScopedPPVar VarFromValue(const base::Value* value) {
+  if (!value)
+    return ScopedPPVar();
+
+  switch (value->type()) {
+    case base::Value::Type::BOOLEAN: {
+      bool val = value->GetBool();
+      return ScopedPPVar(ScopedPPVar::PassRef(), PP_MakeBool(PP_FromBool(val)));
+    }
+    case base::Value::Type::INTEGER: {
+      int val = value->GetInt();
+      return ScopedPPVar(ScopedPPVar::PassRef(), PP_MakeInt32(val));
+    }
+    case base::Value::Type::DOUBLE: {
+      double val = value->GetDouble();
+      return ScopedPPVar(ScopedPPVar::PassRef(), PP_MakeDouble(val));
+    }
+    case base::Value::Type::STRING: {
+      const std::string& val = value->GetString();
+      return ScopedPPVar(ScopedPPVar::PassRef(), StringVar::StringToPPVar(val));
+    }
+    case base::Value::Type::LIST:
+      return VarFromValueArray(value);
+    case base::Value::Type::DICTIONARY:
+      return VarFromValueDictionary(value);
+    default:
+      return ScopedPPVar();
+  }
+}
+
+}  // namespace proxy
+}  // namespace ppapi
diff --git a/ppapi/proxy/var_value_converter.h b/ppapi/proxy/var_value_converter.h
new file mode 100644 (file)
index 0000000..4457723
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2016 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 PPAPI_PROXY_VAR_VALUE_CONVERTER_H_
+#define PPAPI_PROXY_VAR_VALUE_CONVERTER_H_
+
+#include "base/values.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+
+namespace ppapi {
+namespace proxy {
+
+// TODO(m.majczak) Implement cycle detection in vars and values.
+// Currentely value/var with cycle will result in an application crash.
+
+/**
+ * Converts PP_Var to base::Value, passes the ownership of the created value.
+ *
+ * @param var Reference to an object of type PP_Var that will be converted to
+ * base::Value. The ownership of the var is not passed.
+ *
+ * @return scoped_ptr pointing to newly created base::Value.
+ */
+std::unique_ptr<base::Value> ValueFromVar(const PP_Var& var);
+
+/**
+ * Converts base::Value to PP_Var.
+ *
+ * @param value Pointer to an object of type base::Value that will be converted
+ * to PP_Var. The ownership of the value is not passed.
+ *
+ * @return ScopedPPVar that was creted from the value
+ */
+ScopedPPVar VarFromValue(const base::Value* value);
+
+}  // namespace proxy
+}  // namespace ppapi
+
+#endif  // PPAPI_PROXY_VAR_VALUE_CONVERTER_H_
diff --git a/ppapi/proxy/var_value_converter_unittest.cc b/ppapi/proxy/var_value_converter_unittest.cc
new file mode 100644 (file)
index 0000000..67ea7ef
--- /dev/null
@@ -0,0 +1,489 @@
+// Copyright 2016 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 "ppapi/proxy/var_value_converter.h"
+
+#include <limits>
+#include <random>
+#include <sstream>
+#include <string>
+
+#include "base/message_loop/message_loop.h"
+#include "ppapi/shared_impl/array_var.h"
+#include "ppapi/shared_impl/dictionary_var.h"
+#include "ppapi/shared_impl/test_globals.h"
+#include "ppapi/shared_impl/var.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+template <typename T, size_t N>
+size_t ArraySize(T (&)[N]) {
+  return N;
+}
+
+namespace {
+
+std::string RandomStr() {
+  static std::random_device rd;
+  static std::mt19937 gen(rd());
+  static std::uniform_int_distribution<> len_gen(1, 129);
+  static std::uniform_int_distribution<> char_gen(32, 125);
+
+  int length = len_gen(gen);
+  std::stringstream ss;
+  for (int i = 0; i < length; ++i) {
+    // generate random printable character
+    ss << static_cast<char>(char_gen(gen));
+  }
+  return ss.str();
+}
+
+std::string test_keys[] = {"bool_key",   "int_key",   "double_key",
+                           "string_key", "array_key", "dictionary_key"};
+
+enum TestKeysTypes {
+  BOOL_KEY,
+  INT_KEY,
+  DOUBLE_KEY,
+  STRING_KEY,
+  ARRAY_KEY,
+  DICT_KEY,
+  KEY_COUNT
+};
+
+enum ArrayValueTypes {
+  BOOL_IDX,
+  INT_IDX,
+  DOUBLE_IDX,
+  STRING_IDX,
+  ARRAY_IDX,
+  IDX_COUNT
+};
+
+// This is required to assert size of nested containers in array test.
+// If adding more POD types, please add them just after the last POD type.
+const size_t kArrayPODIdxCount = STRING_IDX;
+// This value defines size of the tested array in ArrayVarValueConversionTest.
+const size_t kArrayTestSize = IDX_COUNT;
+
+// This is required to assert size of nested containers in dictionary test.
+// If adding more POD types, please add them just after the last POD type.
+const size_t kPODKeysCount = STRING_KEY;
+
+void SetAndForget(scoped_refptr<ppapi::ArrayVar> arr, int idx, PP_Var var) {
+  arr->Set(idx, var);
+  ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var);
+}
+
+void SetAndForget(scoped_refptr<ppapi::DictionaryVar> dict,
+                  const ppapi::ScopedPPVar& key,
+                  PP_Var var) {
+  dict->Set(key.get(), var);
+  ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var);
+}
+
+}  // namespace
+
+namespace ppapi {
+namespace proxy {
+
+class VarValueConverterTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    // check if initial var count is 0
+    EXPECT_EQ(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().size(), 0u);
+  }
+  void TearDown() override {
+    // check if everything is freed properely
+    EXPECT_EQ(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().size(), 0u);
+  }
+
+ private:
+  base::MessageLoop message_loop_;  // required to instantiate globals
+  TestGlobals globals_;             // required for var management
+};
+
+TEST_F(VarValueConverterTest, BoolVarValueConversionTest) {
+  bool b;
+  // to value
+  ScopedPPVar var1(ScopedPPVar::PassRef(), PP_MakeBool(PP_TRUE));
+  std::unique_ptr<base::Value> value1 = ValueFromVar(var1.get());
+  EXPECT_EQ(value1->GetType(), base::Value::Type::BOOLEAN);
+  ASSERT_TRUE(value1->GetAsBoolean(&b));
+  EXPECT_EQ(b, PP_ToBool(var1.get().value.as_bool));
+
+  ScopedPPVar var2(ScopedPPVar::PassRef(), PP_MakeBool(PP_FALSE));
+  std::unique_ptr<base::Value> value2 = ValueFromVar(var2.get());
+  EXPECT_EQ(value1->GetType(), base::Value::Type::BOOLEAN);
+  ASSERT_TRUE(value2->GetAsBoolean(&b));
+  EXPECT_EQ(b, PP_ToBool(var2.get().value.as_bool));
+
+  // to var
+  ScopedPPVar result1 = VarFromValue(value1.get());
+  ASSERT_TRUE(value1->GetAsBoolean(&b));
+  EXPECT_EQ(b, PP_ToBool(result1.get().value.as_bool));
+
+  ScopedPPVar result2 = VarFromValue(value2.get());
+  ASSERT_TRUE(value2->GetAsBoolean(&b));
+  EXPECT_EQ(b, PP_ToBool(result2.get().value.as_bool));
+}
+
+TEST_F(VarValueConverterTest, IntVarValueConversionTest) {
+  for (int k = -102; k < 100; ++k) {
+    int i;
+    ScopedPPVar var;
+    switch (k) {
+      case -102:
+        var = ScopedPPVar(ScopedPPVar::PassRef(),
+                          PP_MakeInt32(std::numeric_limits<int>::min()));
+        break;
+      case -101:
+        var = ScopedPPVar(ScopedPPVar::PassRef(),
+                          PP_MakeInt32(std::numeric_limits<int>::max()));
+        break;
+      default:
+        var = ScopedPPVar(ScopedPPVar::PassRef(), PP_MakeInt32(k));
+        break;
+    }
+
+    // to value
+    std::unique_ptr<base::Value> value = ValueFromVar(var.get());
+    EXPECT_EQ(value->GetType(), base::Value::Type::INTEGER);
+    ASSERT_TRUE(value->GetAsInteger(&i));
+    EXPECT_EQ(i, var.get().value.as_int);
+
+    // to var
+    ScopedPPVar result = VarFromValue(value.get());
+    EXPECT_EQ(i, result.get().value.as_int);
+  }
+}
+
+TEST_F(VarValueConverterTest, DoubleVarValueConversionTest) {
+  for (int k = -104; k < 100; ++k) {
+    // prepare test data
+    double d;
+    ScopedPPVar var;
+    // Warning!! NaN, Inf and -Inf cannot be tested as base::Value doesn't
+    // support them, they are represented as 0 upon conversion to base::Value.
+    // This is due to JSON serialization requirements.
+    switch (k) {
+      case -103:
+        var = ScopedPPVar(ScopedPPVar::PassRef(),
+                          PP_MakeDouble(std::numeric_limits<double>::min()));
+        break;
+      case -102:
+        var = ScopedPPVar(ScopedPPVar::PassRef(),
+                          PP_MakeDouble(-std::numeric_limits<double>::max()));
+        break;
+      case -101:
+        var = ScopedPPVar(ScopedPPVar::PassRef(),
+                          PP_MakeDouble(std::numeric_limits<double>::max()));
+        break;
+      default:
+        var = ScopedPPVar(ScopedPPVar::PassRef(),
+                          PP_MakeDouble(static_cast<double>(k) * M_PI));
+        break;
+    }
+
+    // to value
+    std::unique_ptr<base::Value> value = ValueFromVar(var.get());
+    EXPECT_EQ(value->GetType(), base::Value::Type::DOUBLE);
+    ASSERT_TRUE(value->GetAsDouble(&d));
+    EXPECT_EQ(d, var.get().value.as_double);
+
+    // to var
+    ScopedPPVar result = VarFromValue(value.get());
+    EXPECT_EQ(d, result.get().value.as_double);
+  }
+}
+
+TEST_F(VarValueConverterTest, StringVarValueConversionTest) {
+  for (int k = 0; k < 100; ++k) {
+    // prepare test data
+    std::string s;
+    std::string str = RandomStr();
+    ScopedPPVar var(ScopedPPVar::PassRef(), StringVar::StringToPPVar(str));
+
+    // to value
+    std::unique_ptr<base::Value> value = ValueFromVar(var.get());
+    ASSERT_TRUE(value != NULL);
+    EXPECT_EQ(value->GetType(), base::Value::Type::STRING);
+    ASSERT_TRUE(value->GetAsString(&s));
+    EXPECT_STREQ(str.c_str(), s.c_str());
+
+    // to var
+    ScopedPPVar result = VarFromValue(value.get());
+    scoped_refptr<StringVar> str_var =
+        scoped_refptr<StringVar>(StringVar::FromPPVar(result.get()));
+    ASSERT_TRUE(str_var != NULL);
+    EXPECT_STREQ(str_var->value().c_str(), s.c_str());
+  }
+}
+
+TEST_F(VarValueConverterTest, ArrayVarValueConversionTest) {
+  for (int k = 0; k < 100; ++k) {
+    // prepare test data
+    bool b = ((k % 2) == 0);
+    int i = k;
+    double d = k;
+    std::string str = RandomStr();
+    bool b2;
+    int i2;
+    double d2;
+    std::string str2;
+
+    scoped_refptr<ArrayVar> nested_array =
+        scoped_refptr<ArrayVar>(new ArrayVar());
+    nested_array->SetLength(kArrayPODIdxCount);
+    size_t current_idx = BOOL_IDX;
+    SetAndForget(nested_array, current_idx++, PP_MakeBool(PP_FromBool(b)));
+    SetAndForget(nested_array, current_idx++, PP_MakeInt32(i));
+    SetAndForget(nested_array, current_idx++, PP_MakeDouble(d));
+    ASSERT_EQ(current_idx, kArrayPODIdxCount);
+
+    scoped_refptr<ArrayVar> array = scoped_refptr<ArrayVar>(new ArrayVar());
+    array->SetLength(kArrayTestSize);
+    current_idx = BOOL_IDX;
+    SetAndForget(array, current_idx++, PP_MakeBool(PP_FromBool(b)));
+    SetAndForget(array, current_idx++, PP_MakeInt32(i));
+    SetAndForget(array, current_idx++, PP_MakeDouble(d));
+    SetAndForget(array, current_idx++, StringVar::StringToPPVar(str));
+    SetAndForget(array, current_idx++, nested_array->GetPPVar());
+    ASSERT_EQ(current_idx, kArrayTestSize);
+
+    // convert to value
+    ScopedPPVar var(ScopedPPVar::PassRef(), array->GetPPVar());
+    std::unique_ptr<base::Value> value = ValueFromVar(var.get());
+
+    ASSERT_TRUE(value != NULL);
+    EXPECT_EQ(value->GetType(), base::Value::Type::LIST);
+    base::ListValue* list = nullptr;
+    ASSERT_TRUE(value->GetAsList(&list));
+    ASSERT_TRUE(list != NULL);
+    EXPECT_EQ(list->GetSize(), kArrayTestSize);
+
+    ASSERT_TRUE(list->GetBoolean(BOOL_IDX, &b2));
+    EXPECT_EQ(b, b2);
+    ASSERT_TRUE(list->GetInteger(INT_IDX, &i2));
+    EXPECT_EQ(i, i2);
+    ASSERT_TRUE(list->GetDouble(DOUBLE_IDX, &d2));
+    EXPECT_EQ(d, d2);
+    ASSERT_TRUE(list->GetString(STRING_IDX, &str2));
+    EXPECT_STREQ(str.c_str(), str2.c_str());
+
+    base::ListValue* nested_list = nullptr;
+    ASSERT_TRUE(list->GetList(ARRAY_IDX, &nested_list));
+    ASSERT_TRUE(nested_list != NULL);
+    EXPECT_EQ(nested_list->GetSize(), kArrayPODIdxCount);
+
+    ASSERT_TRUE(nested_list->GetBoolean(BOOL_IDX, &b2));
+    EXPECT_EQ(b, b2);
+    ASSERT_TRUE(nested_list->GetInteger(INT_IDX, &i2));
+    EXPECT_EQ(i, i2);
+    ASSERT_TRUE(nested_list->GetDouble(DOUBLE_IDX, &d2));
+    EXPECT_EQ(d, d2);
+
+    // convert back to var
+    var = VarFromValue(value.get());
+    ASSERT_EQ(var.get().type, PP_VARTYPE_ARRAY);
+    scoped_refptr<ArrayVar> result =
+        scoped_refptr<ArrayVar>(ArrayVar::FromPPVar(var.get()));
+
+    ASSERT_TRUE(result != NULL);
+    EXPECT_EQ(result->GetLength(), kArrayTestSize);
+
+    var = ScopedPPVar(ScopedPPVar::PassRef(), result->Get(BOOL_IDX));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_BOOL);
+    EXPECT_EQ(var.get().value.as_bool, PP_FromBool(b));
+    var = ScopedPPVar(ScopedPPVar::PassRef(), result->Get(INT_IDX));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_INT32);
+    EXPECT_EQ(var.get().value.as_int, i);
+    var = ScopedPPVar(ScopedPPVar::PassRef(), result->Get(DOUBLE_IDX));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_DOUBLE);
+    EXPECT_EQ(var.get().value.as_double, d);
+    var = ScopedPPVar(ScopedPPVar::PassRef(), result->Get(STRING_IDX));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_STRING);
+    scoped_refptr<StringVar> str_var =
+        scoped_refptr<StringVar>(StringVar::FromPPVar(var.get()));
+    ASSERT_TRUE(str_var != NULL);
+    EXPECT_STREQ(str.c_str(), str_var->value().c_str());
+
+    var = ScopedPPVar(ScopedPPVar::PassRef(), result->Get(ARRAY_IDX));
+    ASSERT_EQ(var.get().type, PP_VARTYPE_ARRAY);
+    scoped_refptr<ArrayVar> nested_var =
+        scoped_refptr<ArrayVar>(ArrayVar::FromPPVar(var.get()));
+    ASSERT_TRUE(nested_var != NULL);
+    EXPECT_EQ(nested_var->GetLength(), kArrayPODIdxCount);
+    var = ScopedPPVar(ScopedPPVar::PassRef(), nested_var->Get(BOOL_IDX));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_BOOL);
+    EXPECT_EQ(var.get().value.as_bool, PP_FromBool(b));
+    var = ScopedPPVar(ScopedPPVar::PassRef(), nested_var->Get(INT_IDX));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_INT32);
+    EXPECT_EQ(var.get().value.as_int, i);
+    var = ScopedPPVar(ScopedPPVar::PassRef(), nested_var->Get(DOUBLE_IDX));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_DOUBLE);
+    EXPECT_EQ(var.get().value.as_double, d);
+  }
+}
+
+TEST_F(VarValueConverterTest, DictionaryVarValueConversionTest) {
+  ScopedPPVar key_vars[] = {
+      ScopedPPVar(ScopedPPVar::PassRef(),
+                  StringVar::StringToPPVar(test_keys[BOOL_KEY])),
+      ScopedPPVar(ScopedPPVar::PassRef(),
+                  StringVar::StringToPPVar(test_keys[INT_KEY])),
+      ScopedPPVar(ScopedPPVar::PassRef(),
+                  StringVar::StringToPPVar(test_keys[DOUBLE_KEY])),
+      ScopedPPVar(ScopedPPVar::PassRef(),
+                  StringVar::StringToPPVar(test_keys[STRING_KEY])),
+      ScopedPPVar(ScopedPPVar::PassRef(),
+                  StringVar::StringToPPVar(test_keys[ARRAY_KEY])),
+      ScopedPPVar(ScopedPPVar::PassRef(),
+                  StringVar::StringToPPVar(test_keys[DICT_KEY]))};
+
+  for (int k = 0; k < 100; ++k) {
+    // prepare test data
+
+    bool b = ((k % 2) == 0);
+    int i = k;
+    double d = k;
+    std::string str = RandomStr();
+    bool b2;
+    int i2;
+    double d2;
+    std::string str2;
+
+    scoped_refptr<ArrayVar> nested_array =
+        scoped_refptr<ArrayVar>(new ArrayVar());
+    nested_array->SetLength(kArrayPODIdxCount);
+    size_t current_idx = BOOL_IDX;
+    SetAndForget(nested_array, current_idx++, PP_MakeBool(PP_FromBool(b)));
+    SetAndForget(nested_array, current_idx++, PP_MakeInt32(i));
+    SetAndForget(nested_array, current_idx++, PP_MakeDouble(d));
+    ASSERT_EQ(current_idx, kArrayPODIdxCount);
+
+    scoped_refptr<DictionaryVar> nested_dict =
+        scoped_refptr<DictionaryVar>(new DictionaryVar());
+    SetAndForget(nested_dict, key_vars[BOOL_KEY], PP_MakeBool(PP_FromBool(b)));
+    SetAndForget(nested_dict, key_vars[INT_KEY], PP_MakeInt32(i));
+    SetAndForget(nested_dict, key_vars[DOUBLE_KEY], PP_MakeDouble(d));
+
+    scoped_refptr<DictionaryVar> dict =
+        scoped_refptr<DictionaryVar>(new DictionaryVar());
+    SetAndForget(dict, key_vars[BOOL_KEY], PP_MakeBool(PP_FromBool(b)));
+    SetAndForget(dict, key_vars[INT_KEY], PP_MakeInt32(i));
+    SetAndForget(dict, key_vars[DOUBLE_KEY], PP_MakeDouble(d));
+    SetAndForget(dict, key_vars[STRING_KEY], StringVar::StringToPPVar(str));
+    SetAndForget(dict, key_vars[ARRAY_KEY], nested_array->GetPPVar());
+    SetAndForget(dict, key_vars[DICT_KEY], nested_dict->GetPPVar());
+
+    // convert to value
+    ScopedPPVar var = ScopedPPVar(ScopedPPVar::PassRef(), dict->GetPPVar());
+    std::unique_ptr<base::Value> value = ValueFromVar(var.get());
+    ASSERT_TRUE(value != NULL);
+    EXPECT_EQ(value->GetType(), base::Value::Type::DICTIONARY);
+    base::DictionaryValue* dict_val = nullptr;
+    ASSERT_TRUE(value->GetAsDictionary(&dict_val));
+    ASSERT_TRUE(dict_val != NULL);
+    EXPECT_EQ(dict_val->size(), ArraySize(key_vars));
+
+    ASSERT_TRUE(dict_val->GetBoolean(test_keys[BOOL_KEY], &b2));
+    EXPECT_EQ(b, b2);
+    ASSERT_TRUE(dict_val->GetInteger(test_keys[INT_KEY], &i2));
+    EXPECT_EQ(i, i2);
+    ASSERT_TRUE(dict_val->GetDouble(test_keys[DOUBLE_KEY], &d2));
+    EXPECT_EQ(d, d2);
+    ASSERT_TRUE(dict_val->GetString(test_keys[STRING_KEY], &str2));
+    EXPECT_STREQ(str.c_str(), str2.c_str());
+
+    base::ListValue* nested_list = nullptr;
+    ASSERT_TRUE(dict_val->GetList(test_keys[ARRAY_KEY], &nested_list));
+    ASSERT_TRUE(nested_list != NULL);
+    EXPECT_EQ(nested_list->GetSize(), kPODKeysCount);
+
+    ASSERT_TRUE(nested_list->GetBoolean(BOOL_IDX, &b2));
+    EXPECT_EQ(b, b2);
+    ASSERT_TRUE(nested_list->GetInteger(INT_IDX, &i2));
+    EXPECT_EQ(i, i2);
+    ASSERT_TRUE(nested_list->GetDouble(DOUBLE_IDX, &d2));
+    EXPECT_EQ(d, d2);
+
+    base::DictionaryValue* nested_dict_val = nullptr;
+    ASSERT_TRUE(dict_val->GetDictionary(test_keys[DICT_KEY], &nested_dict_val));
+    ASSERT_TRUE(nested_dict_val != NULL);
+    EXPECT_EQ(nested_dict_val->size(), kPODKeysCount);
+
+    ASSERT_TRUE(nested_dict_val->GetBoolean(test_keys[BOOL_KEY], &b2));
+    EXPECT_EQ(b, b2);
+    ASSERT_TRUE(nested_dict_val->GetInteger(test_keys[INT_KEY], &i2));
+    EXPECT_EQ(i, i2);
+    ASSERT_TRUE(nested_dict_val->GetDouble(test_keys[DOUBLE_KEY], &d2));
+    EXPECT_EQ(d, d2);
+
+    // convert back to var
+    var = VarFromValue(value.get());
+    ASSERT_EQ(var.get().type, PP_VARTYPE_DICTIONARY);
+    scoped_refptr<DictionaryVar> result =
+        scoped_refptr<DictionaryVar>(DictionaryVar::FromPPVar(var.get()));
+    ASSERT_TRUE(result != NULL);
+
+    var = ScopedPPVar(ScopedPPVar::PassRef(),
+                      result->Get(key_vars[BOOL_KEY].get()));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_BOOL);
+    EXPECT_EQ(var.get().value.as_bool, PP_FromBool(b));
+    var = ScopedPPVar(ScopedPPVar::PassRef(),
+                      result->Get(key_vars[INT_KEY].get()));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_INT32);
+    EXPECT_EQ(var.get().value.as_int, i);
+    var = ScopedPPVar(ScopedPPVar::PassRef(),
+                      result->Get(key_vars[DOUBLE_KEY].get()));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_DOUBLE);
+    EXPECT_EQ(var.get().value.as_double, d);
+    var = ScopedPPVar(ScopedPPVar::PassRef(),
+                      result->Get(key_vars[STRING_KEY].get()));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_STRING);
+    scoped_refptr<StringVar> str_var =
+        scoped_refptr<StringVar>(StringVar::FromPPVar(var.get()));
+    ASSERT_TRUE(str_var != NULL);
+    EXPECT_STREQ(str.c_str(), str_var->value().c_str());
+
+    var = ScopedPPVar(ScopedPPVar::PassRef(),
+                      result->Get(key_vars[ARRAY_KEY].get()));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_ARRAY);
+    scoped_refptr<ArrayVar> nested_var =
+        scoped_refptr<ArrayVar>(ArrayVar::FromPPVar(var.get()));
+    ASSERT_TRUE(nested_var != NULL);
+    EXPECT_EQ(nested_var->GetLength(), kPODKeysCount);
+    var = ScopedPPVar(ScopedPPVar::PassRef(), nested_var->Get(BOOL_IDX));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_BOOL);
+    EXPECT_EQ(var.get().value.as_bool, PP_FromBool(b));
+    var = ScopedPPVar(ScopedPPVar::PassRef(), nested_var->Get(INT_IDX));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_INT32);
+    EXPECT_EQ(var.get().value.as_int, i);
+    var = ScopedPPVar(ScopedPPVar::PassRef(), nested_var->Get(DOUBLE_IDX));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_DOUBLE);
+    EXPECT_EQ(var.get().value.as_double, d);
+
+    var = ScopedPPVar(ScopedPPVar::PassRef(),
+                      result->Get(key_vars[DICT_KEY].get()));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_DICTIONARY);
+    scoped_refptr<DictionaryVar> nested_var2 =
+        scoped_refptr<DictionaryVar>(DictionaryVar::FromPPVar(var.get()));
+    ASSERT_TRUE(nested_var2 != NULL);
+    var = ScopedPPVar(ScopedPPVar::PassRef(),
+                      nested_var2->Get(key_vars[BOOL_KEY].get()));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_BOOL);
+    EXPECT_EQ(var.get().value.as_bool, PP_FromBool(b));
+    var = ScopedPPVar(ScopedPPVar::PassRef(),
+                      nested_var2->Get(key_vars[INT_KEY].get()));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_INT32);
+    EXPECT_EQ(var.get().value.as_int, i);
+    var = ScopedPPVar(ScopedPPVar::PassRef(),
+                      nested_var2->Get(key_vars[DOUBLE_KEY].get()));
+    EXPECT_EQ(var.get().type, PP_VARTYPE_DOUBLE);
+    EXPECT_EQ(var.get().value.as_double, d);
+  }
+}
+
+}  // namespace proxy
+}  // namespace ppapi
index d9b7429..bdb079b 100644 (file)
@@ -31,6 +31,7 @@
   F(PPB_CameraDevice_API)               \
   F(PPB_DeviceRef_API)                  \
   F(PPB_Ext_CrxFileSystem_Private_API)  \
+  F(PPB_ExtensionSystem_API)            \
   F(PPB_FileChooser_API)                \
   F(PPB_FileIO_API)                     \
   F(PPB_FileRef_API)                    \
@@ -51,6 +52,7 @@
   F(PPB_NetworkMonitor_API)             \
   F(PPB_NetworkProxy_API)               \
   F(PPB_Printing_API)                   \
+  F(PPB_RemoteController_API)           \
   F(PPB_Scrollbar_API)                  \
   F(PPB_TCPServerSocket_Private_API)    \
   F(PPB_TCPSocket_API)                  \
index 3ded9e6..1934bd7 100644 (file)
@@ -11,9 +11,11 @@ namespace ppapi {
 // PPB_Instance_API.GetSingletonResource.
 enum SingletonResourceID {
   BROWSER_FONT_SINGLETON_ID,
+  EXTENSION_SYSTEM_SINGLETON_ID,
   GAMEPAD_SINGLETON_ID,
   ISOLATED_FILESYSTEM_SINGLETON_ID,
   NETWORK_PROXY_SINGLETON_ID,
+  REMOTE_CONTROLLER_SINGLETON_ID,
   UMA_SINGLETON_ID,
 };
 
index 8eedff1..22dc6db 100644 (file)
 #include "ppapi/c/private/ppp_instance_private.h"
 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "ppapi/c/samsung/ppb_extension_system_samsung.h"
+#endif /* defined(TIZEN_PEPPER_EXTENSIONS) */
+
 #endif  /* PPAPI_TESTS_ALL_C_INCLUDES_H_ */
index 0fd6e0a..4a7e090 100644 (file)
 #include "ppapi/utility/threading/lock.h"
 #include "ppapi/utility/threading/simple_thread.h"
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "ppapi/cpp/samsung/extension_system_samsung.h"
+#include "ppapi/cpp/samsung/extension_system_samsung_tizen.h"
+#include "ppapi/cpp/samsung/extension_system_samsung_wrt.h"
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+
 #endif  // PPAPI_TESTS_ALL_CPP_INCLUDES_H_
index 87d788d..d2f00d4 100644 (file)
@@ -5,6 +5,9 @@
 import("//ppapi/buildflags/buildflags.gni")
 
 assert(enable_ppapi)
+if (is_tizen) {
+  import("//tizen_src/build/config/tizen_features.gni")
+}
 
 source_set("headers") {
   visibility = [
@@ -180,6 +183,15 @@ source_set("thunk") {
     ]
   }
 
+  if (is_tizen) {
+    if (tizen_pepper_extensions) {
+      sources += [
+        "ppb_extension_system_samsung_thunk.cc",
+        "ppb_remote_controller_samsung_thunk.cc",
+      ]
+    }
+  }
+
   configs += [
     "//ppapi/shared_impl:export_shared_impl_and_thunk",
     "//build/config:precompiled_headers",
diff --git a/ppapi/thunk/interfaces_ppb_samsung.h b/ppapi/thunk/interfaces_ppb_samsung.h
new file mode 100644 (file)
index 0000000..a1da47f
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2016 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.
+
+// Please see inteface_ppb_public_stable for the documentation on the format of
+// this file.
+
+#include "ppapi/thunk/interfaces_preamble.h"
+
+#if !defined(OS_NACL)
+PROXIED_IFACE(PPB_EXTENSIONSYSTEM_SAMSUNG_INTERFACE_0_1,
+              PPB_ExtensionSystem_Samsung_0_1)
+PROXIED_IFACE(PPB_REMOTECONTROLLER_SAMSUNG_INTERFACE_0_1,
+              PPB_RemoteController_Samsung_0_1)
+#endif  // !defined(OS_NACL)
+
+#include "ppapi/thunk/interfaces_postamble.h"
diff --git a/ppapi/thunk/ppb_extension_system_samsung_api.h b/ppapi/thunk/ppb_extension_system_samsung_api.h
new file mode 100644 (file)
index 0000000..c20cb1e
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2016 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 PPAPI_THUNK_PPB_EXTENSION_SYSTEM_SAMSUNG_API_H_
+#define PPAPI_THUNK_PPB_EXTENSION_SYSTEM_SAMSUNG_API_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/shared_impl/singleton_resource_id.h"
+#include "ppapi/thunk/ppapi_thunk_export.h"
+
+namespace ppapi {
+namespace thunk {
+
+class PPAPI_THUNK_EXPORT PPB_ExtensionSystem_API {
+ public:
+  virtual ~PPB_ExtensionSystem_API() {}
+
+  virtual PP_Var GetEmbedderName() = 0;
+  virtual PP_Var GetCurrentExtensionInfo() = 0;
+  virtual int32_t GenericSyncCall(PP_Var operation_name,
+                                  PP_Var operation_data,
+                                  PP_Var* operation_result) = 0;
+
+  static const SingletonResourceID kSingletonResourceID =
+      EXTENSION_SYSTEM_SINGLETON_ID;
+};
+
+}  // namespace thunk
+}  // namespace ppapi
+
+#endif  // PPAPI_THUNK_PPB_EXTENSION_SYSTEM_SAMSUNG_API_H_
diff --git a/ppapi/thunk/ppb_extension_system_samsung_thunk.cc b/ppapi/thunk/ppb_extension_system_samsung_thunk.cc
new file mode 100644 (file)
index 0000000..9af4a5d
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2016 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 "base/logging.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_instance_api.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+#include "ppapi/c/samsung/ppb_extension_system_samsung.h"
+#include "ppapi/thunk/ppb_extension_system_samsung_api.h"
+
+namespace ppapi {
+namespace thunk {
+
+namespace {
+
+PP_Var GetEmbedderName(PP_Instance instance) {
+  EnterInstanceAPI<PPB_ExtensionSystem_API> enter(instance);
+  if (enter.failed())
+    return PP_MakeUndefined();
+  return enter.functions()->GetEmbedderName();
+}
+
+PP_Var GetCurrentExtensionInfo(PP_Instance instance) {
+  EnterInstanceAPI<PPB_ExtensionSystem_API> enter(instance);
+  if (enter.failed())
+    return PP_MakeUndefined();
+  return enter.functions()->GetCurrentExtensionInfo();
+}
+
+int32_t GenericSyncCall(PP_Instance instance,
+                        PP_Var operation_name,
+                        PP_Var operation_data,
+                        PP_Var* operation_result) {
+  EnterInstanceAPI<PPB_ExtensionSystem_API> enter(instance);
+  if (enter.failed())
+    return enter.retval();
+  return enter.SetResult(enter.functions()->GenericSyncCall(
+      operation_name, operation_data, operation_result));
+}
+
+const PPB_ExtensionSystem_Samsung_0_1 g_ppb_extensionsystem_samsung_thunk_0_1 =
+    {&GetEmbedderName, &GetCurrentExtensionInfo, &GenericSyncCall};
+
+}  // namespace
+
+const PPB_ExtensionSystem_Samsung_0_1*
+GetPPB_ExtensionSystem_Samsung_0_1_Thunk() {
+  return &g_ppb_extensionsystem_samsung_thunk_0_1;
+}
+
+}  // namespace thunk
+}  // namespace ppapi
diff --git a/ppapi/thunk/ppb_remote_controller_samsung_api.h b/ppapi/thunk/ppb_remote_controller_samsung_api.h
new file mode 100644 (file)
index 0000000..122075f
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2016 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 PPAPI_THUNK_PPB_REMOTE_CONTROLLER_SAMSUNG_API_H_
+#define PPAPI_THUNK_PPB_REMOTE_CONTROLLER_SAMSUNG_API_H_
+
+#include "ppapi/c/samsung/ppb_remote_controller_samsung.h"
+#include "ppapi/shared_impl/singleton_resource_id.h"
+#include "ppapi/thunk/ppapi_thunk_export.h"
+
+namespace ppapi {
+
+namespace thunk {
+
+class PPAPI_THUNK_EXPORT PPB_RemoteController_API {
+ public:
+  virtual ~PPB_RemoteController_API() {}
+
+  virtual int32_t RegisterKeys(PP_Instance instance,
+                               uint32_t key_count,
+                               const char* keys[]) = 0;
+  virtual int32_t UnRegisterKeys(PP_Instance instance,
+                                 uint32_t key_count,
+                                 const char* keys[]) = 0;
+
+  static const SingletonResourceID kSingletonResourceID =
+      REMOTE_CONTROLLER_SINGLETON_ID;
+};
+
+}  // namespace thunk
+}  // namespace ppapi
+
+#endif  // PPAPI_THUNK_PPB_REMOTE_CONTROLLER_SAMSUNG_API_H_
diff --git a/ppapi/thunk/ppb_remote_controller_samsung_thunk.cc b/ppapi/thunk/ppb_remote_controller_samsung_thunk.cc
new file mode 100644 (file)
index 0000000..8b97e91
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright 2016 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.
+
+// From samsung/ppb_remote_controller_samsung.idl modified Tue Jul 12 15:37:43
+// 2016.
+#include "base/logging.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/samsung/ppb_remote_controller_samsung.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppapi_thunk_export.h"
+#include "ppapi/thunk/ppb_remote_controller_samsung_api.h"
+
+namespace ppapi {
+namespace thunk {
+
+namespace {
+
+int32_t RegisterKeys(PP_Instance instance,
+                     uint32_t key_count,
+                     const char* keys[]) {
+  VLOG(4) << "PPB_RemoteController_Samsung::RegisterKeys()";
+  EnterInstanceAPI<PPB_RemoteController_API> enter(instance);
+  if (enter.failed())
+    return enter.retval();
+  return enter.functions()->RegisterKeys(instance, key_count, keys);
+}
+
+int32_t UnRegisterKeys(PP_Instance instance,
+                       uint32_t key_count,
+                       const char* keys[]) {
+  VLOG(4) << "PPB_RemoteController_Samsung::UnRegisterKeys()";
+  EnterInstanceAPI<PPB_RemoteController_API> enter(instance);
+  if (enter.failed())
+    return enter.retval();
+  return enter.functions()->UnRegisterKeys(instance, key_count, keys);
+}
+
+const PPB_RemoteController_Samsung_0_1
+    g_ppb_remotecontroller_samsung_thunk_0_1 = {&RegisterKeys, &UnRegisterKeys};
+
+}  // namespace
+
+PPAPI_THUNK_EXPORT const PPB_RemoteController_Samsung_0_1*
+GetPPB_RemoteController_Samsung_0_1_Thunk() {
+  return &g_ppb_remotecontroller_samsung_thunk_0_1;
+}
+
+}  // namespace thunk
+}  // namespace ppapi
index aa7f1c4..a7e3030 100644 (file)
@@ -22,6 +22,9 @@
 #include "ppapi/thunk/interfaces_ppb_private_no_permissions.h"
 #include "ppapi/thunk/interfaces_ppb_public_dev.h"
 #include "ppapi/thunk/interfaces_ppb_public_dev_channel.h"
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "ppapi/thunk/interfaces_ppb_samsung.h"
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
 #include "ppapi/thunk/interfaces_ppb_public_socket.h"
 #include "ppapi/thunk/interfaces_ppb_public_stable.h"
 #undef PROXIED_IFACE
index 4cd2957..95ee245 100644 (file)
@@ -61,6 +61,10 @@ namespace policy {
 
 namespace {
 
+#if defined(OS_TIZEN_TV_PRODUCT)
+const char kVDToolsLibName[] = "libvdtools.so";
+#endif
+
 void LogSandboxStarted(const std::string& sandbox_name) {
   const std::string process_type =
       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
@@ -79,6 +83,19 @@ bool IsRunningTSAN() {
 #endif
 }
 
+#if defined(OS_TIZEN_TV_PRODUCT)
+// TODO(d.sura): Find better solution to detect if we are running DUMA/DML
+bool IsRunningDUMADML() {
+  char* env = getenv("LD_PRELOAD");
+  if (!env)
+    return false;
+  std::string str_env(env);
+  if (str_env.find(kVDToolsLibName) == std::string::npos)
+    return false;
+  return true;
+}
+#endif
+
 // Get a file descriptor to /proc. Either duplicate |proc_fd| or try to open
 // it by using the filesystem directly.
 // TODO(jln): get rid of this ugly interface.
@@ -354,6 +371,12 @@ bool SandboxLinux::InitializeSandbox(sandbox::mojom::Sandbox sandbox_type,
     if (IsRunningTSAN())
       return false;
 
+#if defined(OS_TIZEN_TV_PRODUCT)
+    // The same as TSAN above. The DUMA/DML is spawning additional thread.
+    if (IsRunningDUMADML())
+      return false;
+#endif
+
     // The GPU process is allowed to call InitializeSandbox() with threads.
     bool sandbox_failure_fatal = process_type != switches::kGpuProcess;
     // This can be disabled with the '--gpu-sandbox-failures-fatal' flag.
index b921ac9..b0cc409 100644 (file)
@@ -111,7 +111,12 @@ class SANDBOX_POLICY_EXPORT SandboxLinux {
     // Enables the CHECK for open directories. The open directory check is only
     // useful for the chroot jail (from the semantic layer of the sandbox), and
     // can safely be disabled if we are only enabling the seccomp-BPF layer.
+#if defined(OS_TIZEN_TV_PRODUCT)
+    //To fix smack issue in InitializeSandbox
+    bool check_for_open_directories = false;
+#else
     bool check_for_open_directories = true;
+#endif
   };
 
   // Callers can provide this hook to run code right before the policy
index a6dd04b..4853132 100755 (executable)
@@ -81,6 +81,7 @@ Build non gbs version of chromium-efl
 OPTIONS:
    -h, --help            Show this message
    --build-ewk-unittests Build ewk unittests
+   --enable-pepper-extensions    Enable Tizen Pepper Extensions
    --ccache              Configure ccache installed in your system
    --clang               Use chromium's clang compiler to build the sources
    --debug               Build debug version of chromium-efl (out.${host_arch}/Debug instead of out.${host_arch}/Release)
@@ -113,6 +114,7 @@ function parseHostBuildScriptParams() {
   export BUILD_CHROME=0
   export BUILD_SUBDIRECTORY=Release
   export COMPONENT_BUILD=0
+  export ENABLE_PEPPER_EXTENSIONS=0
 
   local platform="$1"
   shift
@@ -151,6 +153,9 @@ function parseHostBuildScriptParams() {
       --component-build)
         export COMPONENT_BUILD=1
         ;;
+      --enable-pepper-extensions)
+        export ENABLE_PEPPER_EXTENSIONS=1
+        ;;
       -j*)
         export JOBS="$1"
         ;;
@@ -167,12 +172,17 @@ function hostGnChromiumEfl() {
   if [[ $SKIP_GN != 1 ]]; then
     local XWALK_ARG=""
     local COMPONENT_ARG=""
+    local PEPPER_EXTENSIONS_ARG=""
     if [[ $COMPONENT_BUILD == 1 ]]; then
       COMPONENT_ARG="component=shared_library"
     fi
+    if [[ $ENABLE_PEPPER_EXTENSIONS == 1 ]]; then
+      PEPPER_EXTENSIONS_ARG="tizen_pepper_extensions=true"
+    fi
     ${TOPDIR}/tizen_src/build/gn_chromiumefl.sh \
       $XWALK_ARG \
       $COMPONENT_ARG \
+      $PEPPER_EXTENSIONS_ARG \
       $@
   fi
 }
index f86bfd2..59b1f6e 100644 (file)
@@ -88,4 +88,9 @@ config("tizen_feature_flags") {
       "WRT_JS_BRINGUP",
     ]
   }
+  if (tizen_pepper_extensions) {
+    defines += [
+      "TIZEN_PEPPER_EXTENSIONS"
+    ]
+  }
 }
index b6f6222..b32bbeb 100755 (executable)
@@ -170,6 +170,7 @@ add_tizen_flags() {
   ADDITIONAL_GN_PARAMETERS+="is_tizen=true
                              use_zygote_handle=true
                              gcc_ver=\"$(getGccVersion)\"
+                             enable_plugins=true
                              python_ver=\"$(getPythonVersion)\"
                              is_official_build=true
                              enable_nacl=false
@@ -226,6 +227,11 @@ add_tizen_flags() {
                              tizen_tbm_support=true
                              tizen_video_hole=true
                             "
+
+  if [ "$tizen_product_tv" == "true" ]; then
+    ADDITIONAL_GN_PARAMETERS+="tizen_pepper_extensions=true
+                              "
+  fi
 }
 
 add_wayland_flags() {
index 158df51..34548a0 100644 (file)
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/features.gni")
 import("//tizen_src/build/config/tizen_features.gni")
+import("//ppapi/buildflags/buildflags.gni")
 
 ##############################################################################
 # Configs
@@ -159,6 +161,21 @@ if (tizen_multimedia) {
   ]
 }
 
+if (tizen_pepper_extensions && enable_plugins) {
+  external_content_browser_efl_sources += [
+    "//tizen_src/chromium_impl/content/browser/renderer_host/pepper/browser_pepper_host_factory_efl.h",
+    "//tizen_src/chromium_impl/content/browser/renderer_host/pepper/browser_pepper_host_factory_efl.cc",
+    "//tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_extension_system_host.cc",
+    "//tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_extension_system_host.h",
+    "//tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_remote_controller_host.cc",
+    "//tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_remote_controller_host.h",
+    "//tizen_src/chromium_impl/content/browser/renderer_host/pepper/remote_controller_wrt.cc",
+    "//tizen_src/chromium_impl/content/browser/renderer_host/pepper/remote_controller_wrt.h",
+    "//tizen_src/chromium_impl/content/public/browser/extension_system_delegate.cc",
+    "//tizen_src/chromium_impl/content/public/browser/extension_system_delegate.h",
+  ]
+}
+
 if (tizen_web_speech_recognition) {
   external_content_browser_efl_sources += [
     "//tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc",
diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/pepper/browser_pepper_host_factory_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/pepper/browser_pepper_host_factory_efl.cc
new file mode 100644 (file)
index 0000000..24050a2
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2016 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 "content/browser/renderer_host/pepper/browser_pepper_host_factory_efl.h"
+
+#include <memory>
+
+#include "build/build_config.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/host/resource_host.h"
+#include "ppapi/proxy/ppapi_message_utils.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "content/browser/renderer_host/pepper/pepper_extension_system_host.h"
+#include "content/browser/renderer_host/pepper/pepper_remote_controller_host.h"
+#endif
+
+using ppapi::UnpackMessage;
+using ppapi::host::ResourceHost;
+
+BrowserPepperHostFactoryEfl::BrowserPepperHostFactoryEfl(
+    content::BrowserPpapiHost* host)
+    : host_(host) {}
+
+BrowserPepperHostFactoryEfl::~BrowserPepperHostFactoryEfl() {}
+
+std::unique_ptr<ResourceHost> BrowserPepperHostFactoryEfl::CreateResourceHost(
+    ppapi::host::PpapiHost* host,
+    PP_Resource resource,
+    PP_Instance instance,
+    const IPC::Message& message) {
+  DCHECK(host == host_->GetPpapiHost());
+
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+  if (message.type() == PpapiHostMsg_ExtensionSystem_Create::ID) {
+    return std::make_unique<content::PepperExtensionSystemHost>(host_, instance,
+                                                                resource);
+  }
+
+  if (message.type() == PpapiHostMsg_RemoteController_Create::ID) {
+    return std::make_unique<content::PepperRemoteControllerHost>(
+        host_, instance, resource);
+  }
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+
+  return std::unique_ptr<ResourceHost>();
+}
diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/pepper/browser_pepper_host_factory_efl.h b/tizen_src/chromium_impl/content/browser/renderer_host/pepper/browser_pepper_host_factory_efl.h
new file mode 100644 (file)
index 0000000..53b34c8
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2016 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 BROWSER_PEPPER_HOST_FACTORY_EFL_H_
+#define BROWSER_PEPPER_HOST_FACTORY_EFL_H_
+
+#include "base/compiler_specific.h"
+#include "ppapi/host/host_factory.h"
+
+namespace content {
+class BrowserPpapiHost;
+}  // namespace content
+
+class BrowserPepperHostFactoryEfl : public ppapi::host::HostFactory {
+ public:
+  // Non-owning pointer to the filter must outlive this class.
+  explicit BrowserPepperHostFactoryEfl(content::BrowserPpapiHost* host);
+  ~BrowserPepperHostFactoryEfl() override;
+
+  std::unique_ptr<ppapi::host::ResourceHost> CreateResourceHost(
+      ppapi::host::PpapiHost* host,
+      PP_Resource resource,
+      PP_Instance instance,
+      const IPC::Message& message) override;
+
+ private:
+  // Non-owning pointer.
+  content::BrowserPpapiHost* host_;
+};
+
+#endif  // BROWSER_PEPPER_HOST_FACTORY_EFL_H_
diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_extension_system_host.cc b/tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_extension_system_host.cc
new file mode 100644 (file)
index 0000000..ec69ac9
--- /dev/null
@@ -0,0 +1,250 @@
+// Copyright 2016 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 "content/browser/renderer_host/pepper/pepper_extension_system_host.h"
+
+#include <memory>
+
+#include "base/json/json_string_value_serializer.h"
+#include "base/logging.h"
+#include "base/task/thread_pool.h"
+#include "base/task/task_runner.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "ewk/efl_integration/ewk_privilege_checker.h"
+#include "ppapi/cpp/samsung/extension_system_samsung_tizen.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace content {
+
+namespace {
+const char kCheckPrivilegeOperationName[] = "check_ace_privilege";
+const char kGetWindowIdOperationName[] = "get_window_id";
+
+std::tuple<bool, std::string> GetEmbedderName(
+    ExtensionSystemDelegateManager::RenderFrameID render_frame_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  ExtensionSystemDelegate* delegate =
+      ExtensionSystemDelegateManager::GetInstance()->GetDelegateForFrame(
+          render_frame_id);
+  if (delegate)
+    return std::make_tuple(true, delegate->GetEmbedderName());
+  return std::make_tuple(false, "");
+}
+
+std::tuple<bool, std::string> GetExtensionInfo(
+    ExtensionSystemDelegateManager::RenderFrameID render_frame_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  ExtensionSystemDelegate* delegate =
+      ExtensionSystemDelegateManager::GetInstance()->GetDelegateForFrame(
+          render_frame_id);
+  std::string result;
+  if (delegate) {
+    std::unique_ptr<base::Value> res_ptr = delegate->GetExtensionInfo();
+    if (!res_ptr)
+      return std::make_tuple(false, "");
+
+    JSONStringValueSerializer json_serializer(&result);
+    if (!json_serializer.Serialize(*res_ptr))
+      return std::make_tuple(false, "");
+  }
+  return std::make_tuple(true, result);
+}
+
+std::tuple<bool, std::string> HandleGenericSyncCall(
+    ExtensionSystemDelegateManager::RenderFrameID render_frame_id,
+    const std::string operation_name,
+    base::Value* raw_pointer_data) {
+  std::unique_ptr<base::Value> data(raw_pointer_data);
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  std::string result;
+  ExtensionSystemDelegate* delegate =
+      ExtensionSystemDelegateManager::GetInstance()->GetDelegateForFrame(
+          render_frame_id);
+  if (delegate) {
+    std::unique_ptr<base::Value> res_ptr =
+        delegate->GenericSyncCall(operation_name, *data);
+    if (!res_ptr)
+      return std::make_tuple(false, "");
+
+    JSONStringValueSerializer json_serializer(&result);
+    if (!json_serializer.Serialize(*res_ptr))
+      return std::make_tuple(false, "");
+  }
+  return std::make_tuple(true, result);
+}
+}  // namespace
+
+PepperExtensionSystemHost::PepperExtensionSystemHost(BrowserPpapiHost* host,
+                                                     PP_Instance instance,
+                                                     PP_Resource resource)
+    : ResourceHost(host->GetPpapiHost(), instance, resource) {
+  host->GetRenderFrameIDsForInstance(instance,
+                                     &render_frame_id_.render_process_id,
+                                     &render_frame_id_.render_frame_id);
+  extension_function_handlers_[kGetWindowIdOperationName] =
+      [this](const base::Value& data) { return GetWindowId(data); };
+  extension_function_handlers_[kCheckPrivilegeOperationName] =
+      [this](const base::Value& data) { return CheckPrivilege(data); };
+}
+
+PepperExtensionSystemHost::~PepperExtensionSystemHost() {}
+
+int32_t PepperExtensionSystemHost::OnResourceMessageReceived(
+    const IPC::Message& msg,
+    ppapi::host::HostMessageContext* context) {
+  PPAPI_BEGIN_MESSAGE_MAP(PepperExtensionSystemHost, msg)
+  PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+      PpapiHostMsg_ExtensionSystem_GetEmbedderName, OnHostMsgGetEmbedderName)
+  PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+      PpapiHostMsg_ExtensionSystem_GetCurrentExtensionInfo,
+      OnHostMsgGetCurrentExtensionInfo)
+  PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+      PpapiHostMsg_ExtensionSystem_GenericSyncCall, OnHostMsgGenericSyncCall)
+  PPAPI_END_MESSAGE_MAP()
+  return PP_ERROR_FAILED;
+}
+
+int32_t PepperExtensionSystemHost::OnHostMsgGetEmbedderName(
+    ppapi::host::HostMessageContext* context) {
+  GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult(
+      FROM_HERE, 
+      base::BindOnce(&GetEmbedderName, render_frame_id_),
+      base::BindOnce(&PepperExtensionSystemHost::DidGetEmbedderName, AsWeakPtr(),
+                 context->MakeReplyMessageContext()));
+  return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperExtensionSystemHost::OnHostMsgGetCurrentExtensionInfo(
+    ppapi::host::HostMessageContext* context) {
+  GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult(
+      FROM_HERE,
+      base::BindOnce(&GetExtensionInfo, render_frame_id_),
+      base::BindOnce(&PepperExtensionSystemHost::DidGetExtensionInfo, AsWeakPtr(),
+                 context->MakeReplyMessageContext()));
+  return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperExtensionSystemHost::OnHostMsgGenericSyncCall(
+    ppapi::host::HostMessageContext* context,
+    const std::string& operation_name,
+    const std::string& operation_data) {
+  base::StringPiece data_str(operation_data);
+  JSONStringValueDeserializer json_deserializer(data_str);
+
+  std::unique_ptr<base::Value> data(
+      json_deserializer.Deserialize(nullptr, nullptr));
+  if (!data) {
+    LOG(ERROR) << "Couldn`t deserialize data";
+    return PP_ERROR_FAILED;
+  }
+
+  bool is_handled;
+  std::unique_ptr<base::Value> res_ptr =
+      TryHandleInternally(operation_name, *data, &is_handled);
+  if (!is_handled) {
+    GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult(
+        FROM_HERE,
+        base::BindOnce(&HandleGenericSyncCall, render_frame_id_, operation_name,
+                   data.release()),
+        base::BindOnce(&PepperExtensionSystemHost::DidHandledGenericSyncCall,
+                   AsWeakPtr(), context->MakeReplyMessageContext()));
+    return PP_OK_COMPLETIONPENDING;
+  }
+
+  if (!res_ptr) {
+    LOG(ERROR);
+    return PP_ERROR_FAILED;
+  }
+
+  std::string result;
+  JSONStringValueSerializer json_serializer(&result);
+  if (!json_serializer.Serialize(*res_ptr)) {
+    LOG(WARNING) << "Couldn`t serialize result of GenericSyncCall";
+    return PP_ERROR_FAILED;
+  }
+
+  context->reply_msg =
+      PpapiPluginMsg_ExtensionSystem_GenericSyncCallReply(result);
+  return PP_OK;
+}
+
+void PepperExtensionSystemHost::DidGetEmbedderName(
+    ppapi::host::ReplyMessageContext reply_context,
+    std::tuple<bool, std::string> embedder_name) {
+  if (std::get<0>(embedder_name))
+    reply_context.params.set_result(PP_OK);
+  else
+    reply_context.params.set_result(PP_ERROR_FAILED);
+  host()->SendReply(reply_context,
+                    PpapiPluginMsg_ExtensionSystem_GetEmbedderNameReply(
+                        std::get<1>(embedder_name)));
+}
+
+void PepperExtensionSystemHost::DidGetExtensionInfo(
+    ppapi::host::ReplyMessageContext reply_context,
+    std::tuple<bool, std::string> serialized_data) {
+  if (std::get<0>(serialized_data))
+    reply_context.params.set_result(PP_OK);
+  else
+    reply_context.params.set_result(PP_ERROR_FAILED);
+  host()->SendReply(reply_context,
+                    PpapiPluginMsg_ExtensionSystem_GetCurrentExtensionInfoReply(
+                        std::get<1>(serialized_data)));
+}
+
+void PepperExtensionSystemHost::DidHandledGenericSyncCall(
+    ppapi::host::ReplyMessageContext reply_context,
+    std::tuple<bool, std::string> operation_result) {
+  if (std::get<0>(operation_result))
+    reply_context.params.set_result(PP_OK);
+  else
+    reply_context.params.set_result(PP_ERROR_FAILED);
+  host()->SendReply(reply_context,
+                    PpapiPluginMsg_ExtensionSystem_GenericSyncCallReply(
+                        std::get<1>(operation_result)));
+}
+
+std::unique_ptr<base::Value> PepperExtensionSystemHost::TryHandleInternally(
+    const std::string& operation_name,
+    const base::Value& data,
+    bool* was_handled) {
+  *was_handled = false;
+
+  auto it = extension_function_handlers_.find(operation_name);
+  if (it == extension_function_handlers_.end())
+    return std::make_unique<base::Value>();
+  *was_handled = true;
+  return it->second(data);
+}
+
+std::unique_ptr<base::Value> PepperExtensionSystemHost::GetWindowId(
+    const base::Value& data) {
+  int id = -1;
+  ExtensionSystemDelegate* delegate =
+      ExtensionSystemDelegateManager::GetInstance()->GetDelegateForFrame(
+          render_frame_id_);
+  if (delegate)
+    id = delegate->GetWindowId();
+  return std::unique_ptr<base::Value>(new base::Value(id));
+}
+
+std::unique_ptr<base::Value> PepperExtensionSystemHost::CheckPrivilege(
+    const base::Value& data) {
+  const std::string* privilege = data.GetIfString();
+  if (!privilege) {
+    LOG(ERROR) << "Provided data for checking privilege is not a string!";
+    return std::make_unique<base::Value>(false);
+  }
+
+  bool result = EwkPrivilegeChecker::GetInstance()->CheckPrivilege(*privilege);
+  LOG_IF(WARNING, !result) << "Privilege " << *privilege << " is not granted";
+  return std::make_unique<base::Value>(result);
+}
+
+}  // namespace content
diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_extension_system_host.h b/tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_extension_system_host.h
new file mode 100644 (file)
index 0000000..3c410d9
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright 2016 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 CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_EXTENSION_SYSTEM_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_EXTENSION_SYSTEM_HOST_H_
+
+#include <functional>
+#include <string>
+#include <tuple>
+#include <unordered_map>
+
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/extension_system_delegate.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/resource_host.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace content {
+
+class BrowserPpapiHost;
+
+class PepperExtensionSystemHost
+    : public ppapi::host::ResourceHost,
+      public base::SupportsWeakPtr<PepperExtensionSystemHost> {
+ public:
+  PepperExtensionSystemHost(BrowserPpapiHost* host,
+                            PP_Instance instance,
+                            PP_Resource resource);
+  ~PepperExtensionSystemHost() override;
+
+ protected:
+  // ppapi::host::ResourceHost override.
+  int32_t OnResourceMessageReceived(
+      const IPC::Message& msg,
+      ppapi::host::HostMessageContext* context) override;
+
+ private:
+  int32_t OnHostMsgGenericSyncCall(ppapi::host::HostMessageContext* context,
+                                   const std::string& operation_name,
+                                   const std::string& operation_data);
+  int32_t OnHostMsgGetEmbedderName(ppapi::host::HostMessageContext* context);
+  int32_t OnHostMsgGetCurrentExtensionInfo(
+      ppapi::host::HostMessageContext* context);
+
+  void DidGetEmbedderName(ppapi::host::ReplyMessageContext,
+                          std::tuple<bool, std::string> embedder_name);
+  void DidGetExtensionInfo(ppapi::host::ReplyMessageContext,
+                           std::tuple<bool, std::string> serialized_data);
+  void DidHandledGenericSyncCall(
+      ppapi::host::ReplyMessageContext,
+      std::tuple<bool, std::string> operation_result);
+
+  std::unique_ptr<base::Value> TryHandleInternally(
+      const std::string& operation_name,
+      const base::Value& data,
+      bool* was_handled);
+  std::unique_ptr<base::Value> GetWindowId(const base::Value& data);
+  std::unique_ptr<base::Value> CheckPrivilege(const base::Value& data);
+
+  using FunctionHandler =
+      std::function<std::unique_ptr<base::Value>(const base::Value&)>;
+  std::unordered_map<std::string, FunctionHandler> extension_function_handlers_;
+
+  ExtensionSystemDelegateManager::RenderFrameID render_frame_id_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_EXTENSION_SYSTEM_HOST_H_
diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_remote_controller_host.cc b/tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_remote_controller_host.cc
new file mode 100644 (file)
index 0000000..a44fbc8
--- /dev/null
@@ -0,0 +1,109 @@
+// Copyright 2016 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 "content/browser/renderer_host/pepper/pepper_remote_controller_host.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+#if defined(OS_TIZEN_TV_PRODUCT)
+#include "content/browser/renderer_host/pepper/remote_controller_wrt.h"
+#include "ewk/efl_integration/common/application_type.h"
+#endif
+
+namespace content {
+
+PepperRemoteControllerHost::PepperRemoteControllerHost(BrowserPpapiHost* host,
+                                                       PP_Instance instance,
+                                                       PP_Resource resource)
+    : ResourceHost(host->GetPpapiHost(), instance, resource), host_(host) {}
+
+PepperRemoteControllerHost::~PepperRemoteControllerHost() = default;
+
+int32_t PepperRemoteControllerHost::OnResourceMessageReceived(
+    const IPC::Message& msg,
+    ppapi::host::HostMessageContext* context) {
+  PPAPI_BEGIN_MESSAGE_MAP(PepperRemoteControllerHost, msg)
+  PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_RemoteController_RegisterKeys,
+                                    OnHostMsgRegisterKeys)
+  PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+      PpapiHostMsg_RemoteController_UnRegisterKeys, OnHostMsgUnRegisterKeys)
+  PPAPI_END_MESSAGE_MAP()
+  LOG(ERROR) << "Resource message unresolved";
+  return PP_ERROR_FAILED;
+}
+
+int32_t PepperRemoteControllerHost::OnHostMsgRegisterKeys(
+    ppapi::host::HostMessageContext* context,
+    const std::vector<std::string>& keys) {
+  auto delegate = GetPlatformDelegate();
+  if (!delegate) {
+    LOG(ERROR) << "Invalid delegate";
+    return PP_ERROR_NOTSUPPORTED;
+  }
+
+//  auto cb = base::BindOnce(&PepperRemoteControllerHost::DidRegisterKeys,
+//                       AsWeakPtr(), context->MakeReplyMessageContext());
+  delegate->RegisterKeys(keys,
+  base::BindOnce(&PepperRemoteControllerHost::DidRegisterKeys,
+                       AsWeakPtr(), context->MakeReplyMessageContext()));
+  return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperRemoteControllerHost::OnHostMsgUnRegisterKeys(
+    ppapi::host::HostMessageContext* context,
+    const std::vector<std::string>& keys) {
+  auto delegate = GetPlatformDelegate();
+  if (!delegate) {
+    LOG(ERROR) << "Invalid delegate";
+    return PP_ERROR_NOTSUPPORTED;
+  }
+
+//  auto cb = base::BindOnce(&PepperRemoteControllerHost::DidUnRegisterKeys,
+ //                      AsWeakPtr(), context->MakeReplyMessageContext());
+  delegate->UnRegisterKeys(keys,
+  base::BindOnce(&PepperRemoteControllerHost::DidUnRegisterKeys,
+                       AsWeakPtr(), context->MakeReplyMessageContext()));
+  return PP_OK_COMPLETIONPENDING;
+}
+
+void PepperRemoteControllerHost::DidRegisterKeys(
+    ppapi::host::ReplyMessageContext reply_context,
+    int32_t result) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  reply_context.params.set_result(result);
+  host()->SendReply(reply_context,
+                    PpapiHostMsg_RemoteController_RegisterKeysReply());
+}
+
+void PepperRemoteControllerHost::DidUnRegisterKeys(
+    ppapi::host::ReplyMessageContext reply_context,
+    int32_t result) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  reply_context.params.set_result(result);
+  host()->SendReply(reply_context,
+                    PpapiHostMsg_RemoteController_UnRegisterKeysReply());
+}
+
+PepperRemoteControllerHost::PlatformDelegate*
+PepperRemoteControllerHost::GetPlatformDelegate() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (delegate_)
+    return delegate_.get();
+#if defined(OS_TIZEN_TV_PRODUCT)
+  if (IsTIZENWRT())
+    delegate_ = CreateRemoteControllerWRT(pp_instance(), host_);
+#endif
+  return delegate_.get();
+}
+
+}  // namespace content
diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_remote_controller_host.h b/tizen_src/chromium_impl/content/browser/renderer_host/pepper/pepper_remote_controller_host.h
new file mode 100644 (file)
index 0000000..a0b64d5
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2016 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 CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_REMOTE_CONTROLLER_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_REMOTE_CONTROLLER_HOST_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/samsung/ppb_remote_controller_samsung.h"
+#include "ppapi/host/resource_host.h"
+
+namespace content {
+
+class BrowserPpapiHost;
+
+class PepperRemoteControllerHost
+    : public ppapi::host::ResourceHost,
+      public base::SupportsWeakPtr<PepperRemoteControllerHost> {
+ public:
+  PepperRemoteControllerHost(BrowserPpapiHost* host,
+                             PP_Instance instance,
+                             PP_Resource resource);
+
+  ~PepperRemoteControllerHost() override;
+
+  // Interface for Platform Remote Controller implementation
+  class PlatformDelegate {
+   public:
+    virtual ~PlatformDelegate() {}
+
+    virtual void RegisterKeys(const std::vector<std::string>& keys,
+                              const base::OnceCallback<void(int32_t)> cb) = 0;
+
+    virtual void UnRegisterKeys(const std::vector<std::string>& keys,
+                                const base::OnceCallback<void(int32_t)> cb) = 0;
+  };
+
+ protected:
+  // ppapi::host::ResourceHost override.
+  int32_t OnResourceMessageReceived(
+      const IPC::Message& msg,
+      ppapi::host::HostMessageContext* context) override;
+
+ private:
+  int32_t OnHostMsgRegisterKeys(ppapi::host::HostMessageContext* context,
+                                const std::vector<std::string>& keys);
+
+  int32_t OnHostMsgUnRegisterKeys(ppapi::host::HostMessageContext* context,
+                                  const std::vector<std::string>& keys);
+
+  void DidRegisterKeys(ppapi::host::ReplyMessageContext reply_context,
+                       int32_t result);
+
+  void DidUnRegisterKeys(ppapi::host::ReplyMessageContext reply_context,
+                         int32_t result);
+
+  // Used to lazy initialize delegate_
+  PlatformDelegate* GetPlatformDelegate();
+
+  BrowserPpapiHost* host_;
+  std::unique_ptr<PlatformDelegate> delegate_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_REMOTE_CONTROLLER_HOST_H_
diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/pepper/remote_controller_wrt.cc b/tizen_src/chromium_impl/content/browser/renderer_host/pepper/remote_controller_wrt.cc
new file mode 100644 (file)
index 0000000..6b1845b
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright 2016 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 "remote_controller_wrt.h"
+
+#include <tuple>
+#include <unordered_map>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/task/thread_pool.h"
+#include "base/task/task_runner.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/extension_system_delegate.h"
+#include "ppapi/c/pp_errors.h"
+
+namespace content {
+
+namespace {
+
+static const char kOperationNameRegister[] = "RegisterKey";
+static const char kOperationNameUnRegister[] = "UnRegisterKey";
+
+class RemoteControllerWRT
+    : public content::PepperRemoteControllerHost::PlatformDelegate {
+ public:
+  RemoteControllerWRT(int render_process_id, int render_frame_id);
+  ~RemoteControllerWRT() override = default;
+
+  void RegisterKeys(const std::vector<std::string>& keys,
+                    base::OnceCallback<void(int32_t)> cb) override;
+
+  void UnRegisterKeys(const std::vector<std::string>& keys,
+                      base::OnceCallback<void(int32_t)> cb) override;
+
+ private:
+  // Class which will execute requests on UI Thread
+  class TaskExecutor;
+  scoped_refptr<TaskExecutor> executor_;
+};
+
+class RemoteControllerWRT::TaskExecutor
+    : public base::RefCountedThreadSafe<TaskExecutor> {
+ public:
+  TaskExecutor(int render_process_id, int render_frame_id);
+
+  int32_t RegisterKeys(const std::vector<std::string>& keys);
+
+  int32_t UnRegisterKeys(const std::vector<std::string>& keys);
+
+ private:
+  friend class base::RefCountedThreadSafe<TaskExecutor>;
+  ~TaskExecutor() = default;
+
+  int32_t DispatchToGenericSyncCall(const std::string& operation_name,
+                                    const std::vector<std::string>& keys);
+
+  ExtensionSystemDelegateManager::RenderFrameID render_frame_id_;
+};
+
+RemoteControllerWRT::TaskExecutor::TaskExecutor(int render_process_id,
+                                                int render_frame_id) {
+  render_frame_id_.render_frame_id = render_frame_id;
+  render_frame_id_.render_process_id = render_process_id;
+}
+
+int32_t RemoteControllerWRT::TaskExecutor::RegisterKeys(
+    const std::vector<std::string>& keys) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  int32_t ret = DispatchToGenericSyncCall(kOperationNameRegister, keys);
+  LOG_IF(ERROR, ret != PP_OK) << "Registering keys failed";
+  return ret;
+}
+
+int32_t RemoteControllerWRT::TaskExecutor::UnRegisterKeys(
+    const std::vector<std::string>& keys) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  int32_t ret = DispatchToGenericSyncCall(kOperationNameUnRegister, keys);
+  LOG_IF(ERROR, ret != PP_OK) << "UnRegistering Keys failed";
+  return ret;
+}
+
+int32_t RemoteControllerWRT::TaskExecutor::DispatchToGenericSyncCall(
+    const std::string& operation_name,
+    const std::vector<std::string>& keys) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  ExtensionSystemDelegate* delegate =
+      ExtensionSystemDelegateManager::GetInstance()->GetDelegateForFrame(
+          render_frame_id_);
+  if (!delegate) {
+    LOG(ERROR) << "Failed to acquire delegate can`t perform " << operation_name;
+    return PP_ERROR_FAILED;
+  }
+
+  // We can`t tell if key that we try to (Un)Register have failed because
+  // it have been already (Un)Registered. So if at least one key have
+  // been successfully processed, we assume that other keys that failed have
+  // been already registered before the call.
+  // This logic will fail when WRT removes support for specific key and we
+  // try to register on it. But this can be quickly checked basing on printed
+  // below log and looking in to sources of
+  // (crosswalk_tizen)/runtime/browser/input_device_manager.cc
+  bool registered_any_key = false;
+  for (const std::string& key_platform_name : keys) {
+    if (key_platform_name.empty()) {
+      LOG(ERROR) << "Key platform name is empty.";
+      return PP_ERROR_BADARGUMENT;
+    }
+    std::unique_ptr<base::Value> key_name =
+        std::make_unique<base::Value>(key_platform_name);
+    std::unique_ptr<base::Value> res_ptr =
+        delegate->GenericSyncCall(operation_name, *key_name);
+    auto sync_call_result = res_ptr->GetIfBool();
+    if (sync_call_result) {
+      registered_any_key = true;
+    } else {
+      LOG(WARNING) << "Result of " << operation_name << ": "
+                   << key_platform_name << ", returned false. Either "
+                   << operation_name << " failed or Key have been already "
+                   << "processed before call. Continuing...";
+    }
+  }
+  return (registered_any_key ? PP_OK : PP_ERROR_FAILED);
+}
+
+RemoteControllerWRT::RemoteControllerWRT(int render_process_id,
+                                         int render_frame_id)
+    : executor_{new TaskExecutor(render_process_id, render_frame_id)} {}
+
+void RemoteControllerWRT::RegisterKeys(
+    const std::vector<std::string>& keys,
+    base::OnceCallback<void(int32_t)> cb) {
+  GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult(
+      FROM_HERE,
+      base::BindOnce(&RemoteControllerWRT::TaskExecutor::RegisterKeys, executor_,
+                 keys),
+      std::move(cb));
+}
+
+void RemoteControllerWRT::UnRegisterKeys(
+    const std::vector<std::string>& keys,
+    base::OnceCallback<void(int32_t)> cb) {
+  GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult(
+      FROM_HERE,
+      base::BindOnce(&RemoteControllerWRT::TaskExecutor::UnRegisterKeys, executor_,
+                 keys),
+      std::move(cb));
+}
+
+}  // namespace
+
+std::unique_ptr<PepperRemoteControllerHost::PlatformDelegate>
+CreateRemoteControllerWRT(PP_Instance instance,
+                          content::BrowserPpapiHost* host) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  int render_process_id, render_frame_id;
+  if (!host->GetRenderFrameIDsForInstance(instance, &render_process_id,
+                                          &render_frame_id)) {
+    LOG(ERROR) << "Can't get process_id and frame_id";
+    return {};
+  }
+
+  return std::make_unique<RemoteControllerWRT>(render_process_id,
+                                               render_frame_id);
+}
+
+}  // namespace content
diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/pepper/remote_controller_wrt.h b/tizen_src/chromium_impl/content/browser/renderer_host/pepper/remote_controller_wrt.h
new file mode 100644 (file)
index 0000000..035ce57
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2016 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 CONTENT_BROWSER_RENDERER_HOST_PEPPER_REMOTE_CONTROLLER_WRT_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_REMOTE_CONTROLLER_WRT_H_
+
+#include <memory>
+
+#include "content/browser/renderer_host/pepper/pepper_remote_controller_host.h"
+
+namespace content {
+class BrowserPpapiHost;
+
+// Factory method
+std::unique_ptr<content::PepperRemoteControllerHost::PlatformDelegate>
+CreateRemoteControllerWRT(PP_Instance instance,
+                          content::BrowserPpapiHost* host);
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_PEPPER_REMOTE_CONTROLLER_WRT_H_
diff --git a/tizen_src/chromium_impl/content/public/browser/extension_system_delegate.cc b/tizen_src/chromium_impl/content/public/browser/extension_system_delegate.cc
new file mode 100644 (file)
index 0000000..b983a86
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright 2016 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 "content/public/browser/extension_system_delegate.h"
+
+#include "base/hash/hash.h"
+#include "base/memory/singleton.h"
+
+namespace content {
+
+ExtensionSystemDelegateManager::~ExtensionSystemDelegateManager() = default;
+
+ExtensionSystemDelegateManager* ExtensionSystemDelegateManager::GetInstance() {
+  return base::Singleton<ExtensionSystemDelegateManager>::get();
+}
+
+ExtensionSystemDelegate* ExtensionSystemDelegateManager::GetDelegateForFrame(
+    const ExtensionSystemDelegateManager::RenderFrameID& id) {
+  auto found_it = delegates_.find(id);
+  if (found_it != delegates_.end()) {
+    return found_it->second.get();
+  }
+
+  // Find delegate with lowest frame_id for given pid.
+  // Such situation might happen when plugin is loaded in <iframe> element
+  for (auto it = delegates_.begin(); it != delegates_.end(); ++it) {
+    if (it->first.render_process_id != id.render_process_id)
+      continue;
+
+    if (found_it == delegates_.end() ||
+        it->first.render_frame_id < found_it->first.render_frame_id) {
+      found_it = it;
+    }
+  }
+
+  if (found_it != delegates_.end())
+    return found_it->second.get();
+
+  return nullptr;
+}
+
+void ExtensionSystemDelegateManager::RegisterDelegate(
+    const ExtensionSystemDelegateManager::RenderFrameID& id,
+    std::unique_ptr<ExtensionSystemDelegate> delegate) {
+  delegates_[id] = std::move(delegate);
+}
+
+bool ExtensionSystemDelegateManager::UnregisterDelegate(
+    const ExtensionSystemDelegateManager::RenderFrameID& id) {
+  return delegates_.erase(id) > 0;
+}
+
+bool ExtensionSystemDelegateManager::RenderFrameID::operator==(
+    const ExtensionSystemDelegateManager::RenderFrameID& rhs) const {
+  return render_process_id == rhs.render_process_id &&
+         render_frame_id == rhs.render_frame_id;
+}
+
+std::size_t ExtensionSystemDelegateManager::RenderFrameIDHasher::operator()(
+    const ExtensionSystemDelegateManager::RenderFrameID& k) const {
+  return base::HashInts32(k.render_process_id, k.render_frame_id);
+}
+
+ExtensionSystemDelegateManager::ExtensionSystemDelegateManager() = default;
+
+}  // namespace content
diff --git a/tizen_src/chromium_impl/content/public/browser/extension_system_delegate.h b/tizen_src/chromium_impl/content/public/browser/extension_system_delegate.h
new file mode 100644 (file)
index 0000000..9579af3
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright 2016 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 CONTENT_PUBLIC_BROWSER_EXTENSION_SYSTEM_DELEGATE_H_
+#define CONTENT_PUBLIC_BROWSER_EXTENSION_SYSTEM_DELEGATE_H_
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "base/values.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}
+
+namespace content {
+
+/*
+ * ExtensionSystemDelegate is an interface for communication with the EWebView
+ */
+class ExtensionSystemDelegate {
+ public:
+  virtual ~ExtensionSystemDelegate() {}
+  virtual std::string GetEmbedderName() const = 0;
+  virtual std::unique_ptr<base::Value> GetExtensionInfo() const = 0;
+  virtual std::unique_ptr<base::Value> GenericSyncCall(
+      const std::string& name,
+      const base::Value& data) = 0;
+  virtual int GetWindowId() const = 0;
+};
+
+/*
+ * ExtensionSystemDelegateManager is a singleton for accessing the
+ * ExtensionSystemDelegate interfaces that were registered by the EWebView
+ */
+class ExtensionSystemDelegateManager {
+ public:
+  // Struct that acts as a key for the interfaces map
+  struct RenderFrameID {
+    int render_process_id;
+    int render_frame_id;
+    bool operator==(const RenderFrameID& rhs) const;
+  };
+
+  static ExtensionSystemDelegateManager* GetInstance();
+
+  // This function is called by the Host, it returns weak_ptr to the interface
+  ExtensionSystemDelegate* GetDelegateForFrame(const RenderFrameID& id);
+
+  // This set of functions should be accessed only by the EWebView
+  // in order to manage the interface life
+  void RegisterDelegate(const RenderFrameID& id,
+                        std::unique_ptr<ExtensionSystemDelegate> delegate);
+  bool UnregisterDelegate(const RenderFrameID& id);
+
+ private:
+  struct RenderFrameIDHasher {
+    std::size_t operator()(const RenderFrameID& k) const;
+  };
+
+  friend struct base::DefaultSingletonTraits<ExtensionSystemDelegateManager>;
+
+  ExtensionSystemDelegateManager();
+  ~ExtensionSystemDelegateManager();
+
+  std::unordered_map<RenderFrameID,
+                     std::unique_ptr<ExtensionSystemDelegate>,
+                     RenderFrameIDHasher>
+      delegates_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_EXTENSION_SYSTEM_DELEGATE_H_
index 87210fc..a5601cc 100755 (executable)
@@ -5,6 +5,8 @@
 import("//base/allocator/allocator.gni")
 import("//build/config/features.gni")
 import("//printing/buildflags/buildflags.gni")
+import("//testing/test.gni")
+import("//ppapi/buildflags/buildflags.gni")
 
 # Components used to auto generate CHROMIUM_VERSION preprocessor define.
 version_file = "//chrome/VERSION"
@@ -20,6 +22,16 @@ group("libchromium-ewk") {
   }
 }
 
+component("chromium_ewk_component") {
+  include_dirs = [
+    ".",
+  ]
+
+  deps = [
+    "//base:base_static",
+  ]
+}
+
 shared_library("chromium-ewk") {
   testonly = true
   if (enable_ewk_interface) {
@@ -93,6 +105,7 @@ shared_library("chromium-ewk") {
     "//third_party/leveldatabase",
     "//third_party/sqlite",
     "//tizen_src/chromium_impl/efl:efl-init",
+    "//tizen_src/ewk/efl_integration:chromium_ewk_component",
     "//tizen_src/ewk/po_tizen:locale_efl",
     "//tizen_src/ewk/po_tizen:packed_locales_efl",
     "//ui/compositor",
@@ -156,6 +169,12 @@ shared_library("chromium-ewk") {
     ]
   }
 
+  if (tizen_pepper_extensions) {
+    configs += [ "//tizen_src/build:cynara-client" ]
+    configs += [ "//tizen_src/build:wayland-client" ]
+    configs += [ "//tizen_src/build:tizen-extension-client" ]
+  }
+
   # TODO : Below dependency is set in chromium/device/battery_tizen.gypi,
   # but since m47 it failed to get properly "injected"
   # to device_battery target due to the new nesting
@@ -555,8 +574,6 @@ shared_library("chromium-ewk") {
     "public/ewk_tracing_internal.h",
     "public/ewk_user_media.cc",
     "public/ewk_user_media_internal.h",
-    "public/ewk_value.cc",
-    "public/ewk_value_product.h",
     "public/ewk_view.cc",
     "public/ewk_view.h",
     "public/ewk_view_internal.h",
@@ -674,6 +691,28 @@ shared_library("chromium-ewk") {
     ]
   }
 
+  if (tizen_pepper_extensions) {
+    sources += [
+      "renderer/pepper/pepper_helper.cc",
+      "renderer/pepper/pepper_helper.h",
+      "renderer/pepper/pepper_shared_memory_message_filter.cc",
+      "renderer/pepper/pepper_shared_memory_message_filter.h",
+      "common/trusted_pepper_plugin_info_cache.cc",
+      "common/trusted_pepper_plugin_info_cache.h",
+      "common/trusted_pepper_plugin_util.cc",
+      "common/trusted_pepper_plugin_util.h",
+      "ewk_extension_system_delegate.cc",
+      "ewk_extension_system_delegate.h",
+      "ewk_privilege_checker.cc",
+      "ewk_privilege_checker.h",
+      "private/ewk_value_private.cc",
+      "private/ewk_value_private.h",
+      "public/ewk_value.cc",
+      "public/ewk_value_product.h",
+      "public/ewk_value_type.h",
+    ]
+  }
+
   sources -= exclude_source_set
 
   # FIXME: Followings are guarded just for bringup.
@@ -705,6 +744,48 @@ executable("efl_webprocess") {
   }
 }
 
+test("efl_integration_unittests") {
+ deps = [
+    "//base/test:test_support",
+    "//ipc",
+    "//ipc:run_all_unittests",
+ ]
+
+ libs = [ "dlog" ]
+
+ include_dirs = [
+    ".",
+    "test"
+ ]
+
+ cflags = [
+   # Treat warning as error for this target.
+   # It needs to be included by means of pattern list because '-Werror' cflag
+   # will be excluded in chromium side (src/build/common.gypi), and GYP
+   # processes pattern lists after exclusion lists.
+   # (ref: https://gyp.gsrc.io/docs/InputFormatReference.md#Processing-Order)
+   "-Werror"
+ ]
+
+ if (tizen_pepper_extensions && enable_plugins) {
+   sources = [
+     "common/trusted_pepper_plugin_info_cache_unittest.cc",
+     "common/trusted_pepper_plugin_info_cache.cc",
+     "common/trusted_pepper_plugin_info_cache.h",
+     "../../../content/public/common/pepper_plugin_info.cc",
+     "../../../content/public/common/pepper_plugin_info.h",
+     "../../../content/public/common/webplugininfo.cc",
+     "../../../content/public/common/webplugininfo.h",
+     "../../../base/logging.cc",
+     "../../../base/logging.h",
+   ]
+   deps += [
+     "//net:net",
+     "//url:url"
+   ]
+}
+}
+
 copy("launch_exec_script") {
   sources = [ "launch_exec.sh" ]
   outputs = [ "$root_out_dir/{{source_file_part}}" ]
index 7dd5a2d..0797537 100644 (file)
@@ -5,8 +5,28 @@
 #include "common/content_client_efl.h"
 
 #include "ipc/ipc_message.h"
+#include "ppapi/buildflags/buildflags.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
+#if BUILDFLAG(ENABLE_PLUGINS)
+#include "content/public/common/content_plugin_info.h"
+#endif
+#if BUILDFLAG(ENABLE_PLUGINS) && defined(TIZEN_PEPPER_EXTENSIONS)
+#include "base/command_line.h"
+#include "common/trusted_pepper_plugin_info_cache.h"
+#include "common/trusted_pepper_plugin_util.h"
+#include "content/public/common/content_switches.h"
+#endif
+
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+namespace {
+inline bool IsPepperPluginProcess() {
+  auto& command_line = *base::CommandLine::ForCurrentProcess();
+  auto type = command_line.GetSwitchValueASCII(switches::kProcessType);
+  return type == switches::kPpapiPluginProcess;
+}
+}  // namespace
+#endif
 
 std::u16string ContentClientEfl::GetLocalizedString(int message_id) {
   // TODO(boliu): Used only by WebKit, so only bundle those resources for
@@ -46,3 +66,11 @@ bool ContentClientEfl::CanSendWhileSwappedOut(const IPC::Message* message) {
   // Because of this we should never drop any synchronous IPC replies.
   return message->type() == IPC_REPLY_ID;
 }
+void ContentClientEfl::AddPlugins(
+    std::vector<content::ContentPluginInfo>* plugins) {
+#if BUILDFLAG(ENABLE_PLUGINS) && defined(TIZEN_PEPPER_EXTENSIONS)
+  DCHECK(plugins);
+  if (!IsPepperPluginProcess() && !pepper::AreTrustedPepperPluginsDisabled())
+    pepper::TrustedPepperPluginInfoCache::GetInstance()->GetPlugins(plugins);
+#endif
+}
index cfc3651..a1f0750 100644 (file)
@@ -24,6 +24,8 @@ class ContentClientEfl : public content::ContentClient {
   std::string GetDataResourceString(int resource_id) override;
   gfx::Image& GetNativeImageNamed(int resource_id) override;
   bool CanSendWhileSwappedOut(const IPC::Message* message);
+  void AddPlugins(
+    std::vector<content::ContentPluginInfo>* plugins) override;
 };
 
 #endif  // CONTENT_CLIENT_EFL_H_
index 96605e6..f401f44 100644 (file)
@@ -37,6 +37,11 @@ const char kWidgetEncodedBundle[] = "widget-encoded-bundle";
 const char kEwkEnableMobileFeaturesForDesktop[] =
     "ewk-enable-mobile-features-for-desktop";
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+const char kEnableTrustedPepperPlugins[] = "enable-trusted-pepper-plugins";
+const char kTrustedPepperPluginsSearchPaths[] =
+    "trusted-pepper-plugins-search-paths";
+#endif
 // Don't dump stuff here, follow the same order as the header.
 
 }  // namespace switches
index 6bb1a84..a070dbb 100644 (file)
@@ -42,6 +42,16 @@ CONTENT_EXPORT extern const char kWidgetEncodedBundle[];
 // similar set of features that mobile build has.
 CONTENT_EXPORT extern const char kEwkEnableMobileFeaturesForDesktop[];
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+// Allow Trusted Pepper Plugins to be loaded in WebBrowser/ubrowser,
+// which is used for development purposes.
+CONTENT_EXPORT extern const char kEnableTrustedPepperPlugins[];
+
+// Additional Trusted Pepper Plugins search paths.
+// Useful for development purposes. Multiple files can be used by separating
+// them with a semicolon (;).
+CONTENT_EXPORT extern const char kTrustedPepperPluginsSearchPaths[];
+#endif
 // DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
 // alphabetical order, or in one of the ifdefs (also in order in each section).
 
diff --git a/tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_info_cache.cc b/tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_info_cache.cc
new file mode 100644 (file)
index 0000000..a184aab
--- /dev/null
@@ -0,0 +1,461 @@
+// Copyright 2016 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 "common/trusted_pepper_plugin_info_cache.h"
+
+#include <iterator>
+#include <unordered_set>
+
+#include "base/command_line.h"
+#include "base/files/file.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/strings/string_split.h"
+#include "base/values.h"
+#include "common/content_switches_efl.h"
+#include "content/public/common/content_plugin_info.h"
+#include "net/base/mime_util.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
+#include "url/gurl.h"
+
+#define PARSING_ERROR(pmf) \
+  LOG(WARNING) << "Malformed PMF: " << pmf.LossyDisplayName() << ": "
+using base::FilePath;
+using content::ContentPluginInfo;
+using content::WebPluginMimeType;
+
+namespace pepper {
+
+namespace {
+
+// TODO(a.bujalski, d.sura):
+// Path for TrustedPepperPlugins providing TV specific WebAPIs.
+// Currently we don`t have tizen environment which defines TrustedPepperPlugins
+// paths ("/opt/usr/apps/pepper" and "/usr/lib/pepper"), thus we use hardcoded
+// values. We should use proper environment variable as soon as specific
+// variable is added for TrustedPepperPlugins.
+// Our environment variable should be registered in Tizen3.0 Multi-user
+// Platform Metadata. See:
+// https://wiki.tizen.org/wiki/Multi-user_Platform_Metadata
+const FilePath::CharType* kPepperPluginsPaths[] = {
+    // "/opt/usr/apps/pepper" is mount point for squash-fs archive contating
+    // Pepper Plugins providing implementation for TV specific WebAPIs.
+    // This archive is bundled together with Tizen TV image. Additionally
+    // this archive can be updated without full platform update.
+    // Updates are downloaded from Samsung servers.
+    FILE_PATH_LITERAL("/opt/usr/apps/pepper"),
+    FILE_PATH_LITERAL("/usr/lib/pepper")};
+
+const FilePath::CharType kPepperPluginManifestExtension[] =
+    FILE_PATH_LITERAL(".pmf");
+const FilePath::CharType kPepperPluginExtension[] = FILE_PATH_LITERAL(".so");
+const char kPepperManifestNameKey[] = "name";
+const char kPepperManifestProgramKey[] = "program";
+const char kPepperManifestUrlKey[] = "url";
+const char kPepperManifestVersionKey[] = "version";
+const char kPepperManifestDescriptionKey[] = "description";
+const char kPepperManifestTypeKey[] = "type";
+const char kPepperManifestTypePepper[] = "pepper";
+const char kPepperManifestMimesKey[] = "mimes";
+const char kPepperManifestMimesTypeKey[] = "type";
+const char kPepperManifestMimesDescriptionKey[] = "description";
+const char kPepperManifestMimesExtensionsKey[] = "extensions";
+
+using Hash = std::hash<FilePath>;
+using FilesContainer = std::unordered_set<FilePath, Hash>;
+
+bool GetStringValue(const base::DictionaryValue* dict,
+                    const std::string& key,
+                    std::string* out_value) {
+  const std::string* val = dict->FindStringPath(key);
+  if (nullptr != val && !val->empty()) {
+    *out_value = *val;
+    return true;
+  }
+
+  return false;
+}
+
+bool GetStringValue(const base::ListValue* list,
+                    size_t i,
+                    std::string* out_value) {
+  std::string val = list->GetList().operator[](i).GetString();
+  if (!val.empty()) {
+    *out_value = val;
+    return true;
+  }
+
+  return false;
+}
+
+bool GetListValue(const base::DictionaryValue* dict,
+                  const std::string& key,
+                  const base::ListValue** out_value) {
+  const base::ListValue* val = static_cast<const base::ListValue*>(dict->FindListKey(key));
+  if (val) {
+    *out_value = val;
+    return true;
+  }
+
+  return false;
+}
+
+bool GetDictionaryValue(const base::DictionaryValue* dict,
+                        const std::string& key,
+                        const base::DictionaryValue** out_value) {
+  const base::DictionaryValue* val = static_cast<const base::DictionaryValue*>(dict->FindDictKey(key));
+  if (val) {
+    *out_value = val;
+    return true;
+  }
+
+  return false;
+}
+
+bool GetDictionaryValue(const base::ListValue* list,
+                        size_t i,
+                        const base::DictionaryValue** out_value) {
+  const base::Value* val;
+  val = const_cast<base::Value*>(&(list->GetList().operator[](i)));
+  
+  if(val && val->is_dict()) {
+    *out_value = static_cast<const base::DictionaryValue*>(val);
+       return true;
+  }
+  return false;
+}
+
+void GetMimeTypeExtensions(const base::DictionaryValue* dict,
+                           std::vector<std::string>* out_exensions) {
+  const base::ListValue* list;
+  std::string val;
+  if (GetListValue(dict, kPepperManifestMimesExtensionsKey, &list)) {
+       size_t size = list->GetList().size();
+    for (size_t i = 0; i < size; ++i)
+      if (GetStringValue(list, i, &val))
+        out_exensions->push_back(val);
+  } else if (GetStringValue(dict, kPepperManifestMimesExtensionsKey, &val)) {
+    out_exensions->push_back(val);
+  }
+}
+
+bool GetWebPluginMimeType(const FilePath& pmf,
+                          const base::ListValue* mimes,
+                          size_t i,
+                          WebPluginMimeType* plugin_mime) {
+  std::string type;
+  std::string description;
+  std::vector<std::string> extensions;
+
+  const base::DictionaryValue* dict = nullptr;
+  if (GetDictionaryValue(mimes, i, &dict)) {
+    // "type" : (mandatory)
+    if (!GetStringValue(dict, kPepperManifestMimesTypeKey, &type)) {
+      PARSING_ERROR(pmf) << "MIME type attribute not found";
+      return false;
+    }
+
+    GetStringValue(dict, kPepperManifestMimesDescriptionKey, &description);
+    GetMimeTypeExtensions(dict, &extensions);
+  } else {  // The MIME list item is not a dictionary.
+    // We allow the MIME to be just a string type,
+    // without the description and extensions.
+    if (GetStringValue(mimes, i, &type)) {
+      PARSING_ERROR(pmf) << "The MIME has no type entry";
+      return false;
+    }
+  }
+
+  *plugin_mime = WebPluginMimeType(type, "", description);
+  plugin_mime->file_extensions = extensions;
+  return true;
+}
+
+bool GetPuginMimeTypes(const FilePath& pmf,
+                       const base::ListValue* mimes_list,
+                       std::vector<WebPluginMimeType>* mime_types) {
+  if (mimes_list->type() != base::Value::Type::LIST) {
+    PARSING_ERROR(pmf) << "The mimes must be a list";
+    return false;
+  }
+
+  size_t size = mimes_list->GetList().size();
+  for (size_t i = 0; i < size; ++i) {
+    WebPluginMimeType mime_type;
+    if (GetWebPluginMimeType(pmf, mimes_list, i, &mime_type))
+      mime_types->push_back(mime_type);
+  }
+
+  return true;
+}
+
+bool ReadPluginMimeTypes(const FilePath& pmf,
+                         const base::DictionaryValue* dict,
+                         ContentPluginInfo* info) {
+  // Get the MIME types.
+  const base::ListValue* mimes_list = nullptr;
+  if (!GetListValue(dict, kPepperManifestMimesKey, &mimes_list)) {
+    PARSING_ERROR(pmf) << "Can't read the MIME types list";
+    return false;
+  }
+
+  std::vector<WebPluginMimeType> mime_types;
+  if (!GetPuginMimeTypes(pmf, mimes_list, &mime_types)) {
+    PARSING_ERROR(pmf) << "Can't parse MIME types";
+    return false;
+  }
+
+  if (mime_types.empty()) {
+    PARSING_ERROR(pmf) << " no mime types defined for the plugin";
+    return false;
+  }
+
+  info->mime_types = mime_types;
+  return true;
+}
+
+bool ReadPluginPath(const FilePath& pmf,
+                    const base::DictionaryValue* dict,
+                    ContentPluginInfo* info) {
+  // Path to the plugin. The url attribute has higher priority
+  // than the manifest name.
+  const base::DictionaryValue* program_dict;
+  if (!GetDictionaryValue(dict, kPepperManifestProgramKey, &program_dict)) {
+       auto key = dict->FindKey(kPepperManifestProgramKey);
+       bool has_key = (key != nullptr ? true:false);
+       
+    if (has_key) {
+      PARSING_ERROR(pmf) << "invalid \"program\" key present:"
+                         << " not a dictionary";
+      return false;
+    }
+
+    // No program key present.
+    // Path to manifest is:     /pepper/plugins_dir/my_plugin.pmf
+    // Path to plugin will be:  /pepper/plugins_dir/my_plugin.so
+    info->path = pmf.RemoveExtension().AddExtension(kPepperPluginExtension);
+    return true;
+  }
+
+  std::string val;
+  if (GetStringValue(program_dict, kPepperManifestUrlKey, &val)) {
+    FilePath plugin_path(val);
+    if (plugin_path.IsAbsolute())
+      info->path = plugin_path;
+    else
+      info->path = pmf.DirName().Append(val);
+  } else {
+    PARSING_ERROR(pmf) << "\"program\" key present but it does not contain"
+                          " \"url\" entry";
+    return false;
+  }
+  return true;
+}
+
+bool ValidatePluginType(const FilePath& pmf,
+                        const base::DictionaryValue* dict) {
+  std::string val;
+  if (!GetStringValue(dict, kPepperManifestTypeKey, &val)) {
+    PARSING_ERROR(pmf) << "No type attribute in the PMF file";
+    return false;
+  }
+
+  if (val != kPepperManifestTypePepper) {
+    PARSING_ERROR(pmf) << "Unknown plugin type: " << val;
+    return false;
+  }
+
+  return true;
+}
+
+bool ValidatePepperPluginInfo(const FilePath& pmf,
+                              const ContentPluginInfo& info) {
+  if (!PathExists(info.path)) {
+    PARSING_ERROR(pmf) << " invalid plugin path: "
+                       << info.path.LossyDisplayName();
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+TrustedPepperPluginInfoCache* TrustedPepperPluginInfoCache::GetInstance() {
+  return base::Singleton<TrustedPepperPluginInfoCache>::get();
+}
+
+TrustedPepperPluginInfoCache::TrustedPepperPluginInfoCache(
+    const std::vector<base::FilePath>& paths) {
+
+  for (const auto& path : paths)
+  {
+        AddPluginsFromDirectory(path);
+  }
+
+}
+
+TrustedPepperPluginInfoCache::~TrustedPepperPluginInfoCache() {}
+
+void TrustedPepperPluginInfoCache::GetPlugins(
+    std::vector<ContentPluginInfo>* plugins) const {
+  if (plugins->empty()) {
+    plugins->reserve(plugins_.size());
+    std::for_each(plugins_.cbegin(), plugins_.cend(),
+                  [plugins](const PluginEntry& element) {
+                    plugins->push_back(*(element.second));
+                  });
+  } else {
+    FilesContainer plugins_not_to_add;
+    for (const auto& plugin : *plugins)
+      plugins_not_to_add.insert(plugin.path);
+
+    for (const auto& plugin : plugins_) {
+      if (!plugins_not_to_add.count(plugin.second->path))
+        plugins->push_back(*(plugin.second));
+    }
+  }
+}
+
+bool TrustedPepperPluginInfoCache::FindPlugin(
+    std::string mime_type,
+    const GURL& url,
+    ContentPluginInfo* found_plugin) const {
+  if (mime_type.empty()) {
+    // Try to guess the MIME type based on the extension.
+    auto filename = url.ExtractFileName();
+    auto extension_pos = filename.rfind('.');
+    if (extension_pos != std::string::npos) {
+      auto extension = filename.substr(extension_pos + 1);
+      net::GetWellKnownMimeTypeFromExtension(extension, &mime_type);
+    }
+
+    if (mime_type.empty())
+      return false;
+  }
+
+  auto it = mime_map_.find(mime_type);
+  if (it != mime_map_.cend()) {
+    *found_plugin = *(it->second);
+    return true;
+  }
+
+  return false;
+}
+
+TrustedPepperPluginInfoCache::TrustedPepperPluginInfoCache() {
+  for (const auto& path : kPepperPluginsPaths)
+    AddPluginsFromDirectory(base::FilePath(path));
+
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kTrustedPepperPluginsSearchPaths)) {
+    const std::string value = command_line->GetSwitchValueASCII(
+        switches::kTrustedPepperPluginsSearchPaths);
+    std::vector<std::string> paths = base::SplitString(
+        value, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+    for (const auto& path : paths)
+      AddPluginsFromDirectory(base::FilePath(path));
+  }
+}
+
+void TrustedPepperPluginInfoCache::AddPluginsFromDirectory(
+    const FilePath& dir) {
+  if (!base::PathExists(dir))
+    return;
+
+  base::FileEnumerator it(dir, true, base::FileEnumerator::FILES);
+  for (FilePath name = it.Next(); !name.empty(); name = it.Next()) {
+    if (name.Extension() != kPepperPluginManifestExtension)
+      continue;
+
+    std::unique_ptr<ContentPluginInfo> info{new ContentPluginInfo};
+    if (!FillPepperPluginInfoFromManifest(name, info.get()))
+      continue;
+
+    for (const auto& plugin_mime : info->mime_types) {
+      if (mime_map_.count(plugin_mime.mime_type)) {
+        LOG(WARNING)
+            << "mime_type: " << plugin_mime.mime_type
+            << " is already handled by plugin: "
+            << mime_map_[plugin_mime.mime_type]->path.LossyDisplayName();
+        continue;
+      }
+
+      mime_map_[plugin_mime.mime_type] = info.get();
+    }
+
+    plugins_.emplace_back(name, std::move(info));
+  }
+}
+
+bool ParsePepperPluginManifest(const FilePath& pmf,
+                               const std::string& contents,
+                               ContentPluginInfo* out_info) {
+  auto root = base::JSONReader::ReadAndReturnValueWithError(contents);
+  if (!root.has_value()) {
+    PARSING_ERROR(pmf) << "Ill formatted PMF file: not a proper JSON.";
+    return false;
+  }
+
+  if (root.value().type() != base::Value::Type::DICTIONARY) {
+    PARSING_ERROR(pmf) << "Ill formatted PMF file: "
+                       << "the root node is not an object.";
+    return false;
+  }
+
+  base::DictionaryValue* dict = 0;
+  if (!root.value().GetAsDictionary(&dict) || !dict) {
+    PARSING_ERROR(pmf) << "Can't to get the root node as an object.";
+    return false;
+  }
+
+  if (!ValidatePluginType(pmf, dict))
+    return false;
+
+  // Let's set the default values for the info in case they are not present
+  // in the manifest.
+  ContentPluginInfo info;
+  info.is_out_of_process = true;
+  info.is_internal = false;
+  // Trusted Pepper Plugins have all possible permissions
+  info.permissions = ppapi::Permission::PERMISSION_ALL_BITS;
+
+  GetStringValue(dict, kPepperManifestNameKey, &(info.name));
+  GetStringValue(dict, kPepperManifestDescriptionKey, &(info.description));
+  GetStringValue(dict, kPepperManifestVersionKey, &(info.version));
+
+  if (!ReadPluginMimeTypes(pmf, dict, &info))
+    return false;
+
+  if (!ReadPluginPath(pmf, dict, &info))
+    return false;
+
+  *out_info = info;
+  return true;
+}
+
+bool FillPepperPluginInfoFromManifest(const FilePath& pmf,
+                                      ContentPluginInfo* out_info) {
+  std::string contents;
+  if (!base::ReadFileToString(pmf, &contents)) {
+    PARSING_ERROR(pmf) << "Could not read manifest file ";
+    return false;
+  }
+
+  ContentPluginInfo info;
+  if (!ParsePepperPluginManifest(pmf, contents, &info))
+    return false;
+
+  if (!ValidatePepperPluginInfo(pmf, info))
+    return false;
+
+  *out_info = info;
+  return true;
+}
+
+}  // namespace pepper
diff --git a/tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_info_cache.h b/tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_info_cache.h
new file mode 100644 (file)
index 0000000..bdd8b98
--- /dev/null
@@ -0,0 +1,172 @@
+// Copyright 2016 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_EFL_INTEGRATION_COMMON_TRUSTED_PEPPER_PLUGIN_INFO_CACHE_H_
+#define EWK_EFL_INTEGRATION_COMMON_TRUSTED_PEPPER_PLUGIN_INFO_CACHE_H_
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+//#include "base/containers/hash_tables.h"
+#include "base/files/file_path.h"
+#include "content/public/common/content_plugin_info.h"
+#include "url/gurl.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}
+
+namespace pepper {
+
+// Class holding (caching) discovered plugins in given directories.
+// Plugin needs to have manifest file pmf which descibes it.
+//
+// See |ParsePepperPluginManifest| for Plugin Manifest File (pmf) specification.
+class TrustedPepperPluginInfoCache {
+ public:
+  // Gets singleton of representing cache built for predefined directories.
+  static TrustedPepperPluginInfoCache* GetInstance();
+
+  // Special constructor only used during unit testing:
+  explicit TrustedPepperPluginInfoCache(
+      const std::vector<base::FilePath>& paths);
+
+  ~TrustedPepperPluginInfoCache();
+
+  // Adds all the plugins present in the cache to the |plugins| vector.
+  //
+  // If the plugins vector is empty then adds all plugins present currently
+  // in the cache to the vector.
+  //
+  // If the plugins vector is not empty then adds only those plugins that
+  // are present in the cache, but are not present in the vector.
+  //
+  // |plugins| is *non-null* pointer to vector which will be filled
+  void GetPlugins(std::vector<content::ContentPluginInfo>* plugins) const;
+
+  // Searches cached pepper plugins whether there is plugin which supports
+  // given |mime_type| or |url|. If |mime_type| is empty, method tries to find
+  // plugin basing on |url| extension.
+  //
+  // If plugin was found function returns true and sets |found_plugin|
+  // information for plugin found. Otherwise function returns false and
+  // doesn't touch |found_plugin| argument.
+  //
+  // |found_plugin| must be *non-null* pointer
+  bool FindPlugin(std::string mime_type,
+                  const GURL& url,
+                  content::ContentPluginInfo* found_plugin) const;
+
+ private:
+  friend struct base::DefaultSingletonTraits<TrustedPepperPluginInfoCache>;
+
+  // Builds plugin cache based on predefined directories.
+  TrustedPepperPluginInfoCache();
+
+  // Discover plugins in given directory by scanning it recursively
+  // and adds their descriptions to the cache.
+  void AddPluginsFromDirectory(const base::FilePath& dir);
+
+  using PluginEntry =
+      std::pair<base::FilePath, std::unique_ptr<content::ContentPluginInfo>>;
+
+  // cached plugin infos
+  std::vector<PluginEntry> plugins_;
+
+  // ContentPluginInfo is non owning pointer to plugins element
+  std::unordered_map<std::string, content::ContentPluginInfo*> mime_map_;
+};
+
+// Exposed in header for UnitTesting:
+//
+// Parses Plugin Manifest File (PMF) provided as string |contents|
+// and fills properly |out_info|.
+//
+// |pmf| is path from which PMF was loaded from and its used to fill
+// |ContentPluginInfo::path| field if such information is not present in the PMF.
+//
+// This function does not performs any operation on filesystem.
+//
+// Sample PMFs:
+//
+// libsample_plugin.pmf:
+// {
+//   "type" : "pepper",
+//   "name" : "Sample Trusted Plugin",
+//   "version" : "1.0",
+//   "description" : "Example Pepper Trusted Plugin",
+//   "mimes" : [
+//      {
+//        "type" : "application/x-ppapi-example",
+//        "description" : "Example Ppapi",
+//        "extensions" : [ ".ext1", ".ext2" ]
+//      },
+//      {
+//          "type" : "application/x-ppapi-example2"
+//      }
+//   ]
+// }
+//
+// test_plugin.pmf:
+// {
+//   "type" : "pepper",
+//   "name" : "Test Trusted Plugin",
+//   "version" : "1.2",
+//   "description" : "Test Trusted Pepper Plugin",
+//   "mimes": [ { type: "application/x-ppapi-test" } ],
+//   "program": { "url": "libtest_plugin.so" }
+// }
+//
+// PMF is a JSON wich have following fields:
+// - type (mandatory)
+//     type of the plugin, must be set to "pepper'
+// - name (optional)
+//     plugin name, value for |ContentPluginInfo::name|
+// - description (optional)
+//     plugin description, value for |ContentPluginInfo::description|
+// - version (optional)
+//     plugin version, value for |ContentPluginInfo::version|
+// - mimes (mandatory)
+//     provides list of mime types, value for |ContentPluginInfo::mime_types|
+// - mimes/type (mandatory)
+//     defines mime_type itself, value for |WebPluginMimeType::mime_type|
+// - mimes/description (optional)
+//     defines mime_type description, value for |WebPluginMimeType::description|
+// - mimes/extensions (optional)
+//     defines list of the file extensions for this mime type,
+//     value for |WebPluginMimeType::file_extensions|
+// - program (optional)
+//     provides path for pepper plugin shared library, value for
+//     |ContentPluginInfo::path|. If value is not present in the manifest,
+//     then path is deduced from |pmf|, by replacing .pmf extension form the
+//     manifest to platform dependent library extension (.so on POSIX systems).
+// - program/url (mandatory if program argument is present)
+//     provides relative or absolute path to pepper plugin shared library.
+//
+// Following fields are not present in PMF and are set to given values:
+// - ContentPluginInfo::is_internal is set to |false|
+// - ContentPluginInfo::is_out_of_process is set to |true|
+//
+// Function returns true if manifest is parsed and follows specification
+// given above.
+bool ParsePepperPluginManifest(const base::FilePath& pmf,
+                               const std::string& contents,
+                               content::ContentPluginInfo* out_info);
+
+// Exposed in header for UnitTesting:
+//
+// Reads plugin manifest from |pmf| path, parses it and validates
+// whether plugin path (|ContentPluginInfo::path|) is valid (exsists).
+//
+// See |ParsePepperPluginManifest| for Plugin Manifest File (pmf) specification.
+bool FillPepperPluginInfoFromManifest(const base::FilePath& pmf,
+                                      content::ContentPluginInfo* out_info);
+
+}  // namespace pepper
+
+#endif  // EWK_EFL_INTEGRATION_COMMON_TRUSTED_PEPPER_PLUGIN_INFO_CACHE_H_
diff --git a/tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_info_cache_unittest.cc b/tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_info_cache_unittest.cc
new file mode 100644 (file)
index 0000000..822b5e7
--- /dev/null
@@ -0,0 +1,844 @@
+// Copyright 2016 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 "common/trusted_pepper_plugin_info_cache.h"
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "content/public/common/content_plugin_info.h"
+
+using base::FilePath;
+using content::ContentPluginInfo;
+using content::WebPluginMimeType;
+
+namespace pepper {
+
+namespace {
+
+enum PluginFilesWriteOptions { PMF_ONLY, PMF_AND_LIBRARY };
+
+const std::vector<std::string> kNonExistingMimes = {
+    "application/x-invalid-mime", "invalid/invalid",
+    "test/x-test-invalid-mime"};
+
+FilePath AddLibrarySuffix(const FilePath& path) {
+  return path.AddExtension(FILE_PATH_LITERAL(".so"));
+}
+
+bool EqualPluginMimeType(const WebPluginMimeType& lhs,
+                         const WebPluginMimeType& rhs);
+
+template <class T>
+bool EqualVectors(const std::vector<T>& lhs, const std::vector<T>& rhs) {
+  if (lhs.size() != rhs.size())
+    return false;
+
+  return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
+}
+
+bool EqualVectors(const std::vector<WebPluginMimeType>& lhs,
+                  const std::vector<WebPluginMimeType>& rhs) {
+  if (lhs.size() != rhs.size())
+    return false;
+
+  return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(),
+                    EqualPluginMimeType);
+}
+
+bool EqualPluginMimeType(const WebPluginMimeType& lhs,
+                         const WebPluginMimeType& rhs) {
+  return lhs.mime_type == rhs.mime_type &&
+         EqualVectors(lhs.file_extensions, rhs.file_extensions) &&
+         lhs.description == rhs.description &&
+         EqualVectors(lhs.additional_param_names, rhs.additional_param_names) &&
+         EqualVectors(lhs.additional_param_values, rhs.additional_param_values);
+}
+
+bool EqualPepperPluginInfo(const ContentPluginInfo& lhs,
+                           const ContentPluginInfo& rhs) {
+  return lhs.is_internal == rhs.is_internal &&
+         lhs.is_out_of_process == rhs.is_out_of_process &&
+         lhs.path == rhs.path && lhs.name == rhs.name &&
+         lhs.description == rhs.description && lhs.version == rhs.version &&
+         EqualVectors(lhs.mime_types, rhs.mime_types) &&
+         lhs.permissions == rhs.permissions;
+}
+
+ContentPluginInfo GetTestPlugin1() {
+  ContentPluginInfo plugin;
+
+  plugin.is_internal = false;
+  plugin.is_out_of_process = true;
+  plugin.name = "plugin1";
+  plugin.description = "Test Plugin1";
+  plugin.version = "1.0";
+  plugin.mime_types.emplace_back("plugin1/mime1", ".ext1", "mime1");
+  plugin.mime_types.emplace_back("plugin1/mime2", ".ext2", "mime2");
+  plugin.permissions = ppapi::Permission::PERMISSION_ALL_BITS;
+
+  return plugin;
+}
+
+ContentPluginInfo GetTestPlugin2() {
+  WebPluginMimeType plugin_mime;
+  plugin_mime.mime_type = "plugin2/mime";
+
+  ContentPluginInfo plugin;
+  plugin.is_internal = false;
+  plugin.is_out_of_process = true;
+  plugin.name = "plugin2";
+  plugin.description = "Test Plugin2";
+  plugin.version = "1.1";
+  plugin.mime_types.push_back(plugin_mime);
+  plugin.permissions = ppapi::Permission::PERMISSION_ALL_BITS;
+
+  return plugin;
+}
+
+ContentPluginInfo GetTestPlugin3() {
+  ContentPluginInfo plugin;
+
+  plugin.is_internal = false;
+  plugin.is_out_of_process = true;
+  plugin.name = "plugin3";
+  plugin.description = "Test Plugin3";
+  plugin.version = "1.0";
+  plugin.mime_types.emplace_back("plugin3/mime1", ".e1", "mime1");
+  plugin.mime_types.emplace_back("plugin3/mime2", ".e2", "mime2");
+  plugin.permissions = ppapi::Permission::PERMISSION_ALL_BITS;
+
+  return plugin;
+}
+
+ContentPluginInfo GetTestPlugin4() {
+  ContentPluginInfo plugin;
+
+  plugin.is_internal = false;
+  plugin.is_out_of_process = true;
+  plugin.name = "plugin4";
+  plugin.description = "Test Plugin4";
+  plugin.version = "4.0";
+  plugin.mime_types.emplace_back("plugin4/mime1", ".f1", "mime1");
+  plugin.mime_types.emplace_back("plugin4/mime2", ".f2", "mime2");
+  plugin.permissions = ppapi::Permission::PERMISSION_ALL_BITS;
+
+  return plugin;
+}
+
+ContentPluginInfo GetTestPlugin5() {
+  ContentPluginInfo plugin;
+
+  plugin.is_internal = false;
+  plugin.is_out_of_process = true;
+  plugin.name = "plugin5";
+  plugin.description = "Test Plugin5";
+  plugin.version = "1.10";
+  plugin.mime_types.emplace_back("plugin5/mime1", ".p1", "mime1");
+  plugin.mime_types.emplace_back("plugin5/mime2", ".p2", "mime2");
+  plugin.permissions = ppapi::Permission::PERMISSION_ALL_BITS;
+
+  return plugin;
+}
+
+ContentPluginInfo GetTestPlugin6() {
+  ContentPluginInfo plugin;
+
+  plugin.is_internal = false;
+  plugin.is_out_of_process = true;
+  plugin.name = "plugin6";
+  plugin.description = "Test Plugin6";
+  plugin.version = "1.10";
+  plugin.mime_types.emplace_back("application/x-shockwave-flash", ".swf",
+                                 "mime1");
+  plugin.permissions = ppapi::Permission::PERMISSION_ALL_BITS;
+
+  return plugin;
+}
+
+std::string PluginMimesToJSON(const ContentPluginInfo& plugin) {
+  std::ostringstream oss;
+
+  for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
+    if (i > 0)
+      oss << ",\n";
+
+    const auto& mime = plugin.mime_types[i];
+    oss << "    {"
+        << "       \"type\" : \"" << mime.mime_type << "\"";
+
+    if (!mime.description.empty()) {
+      oss << ",\n"
+          << "       \"description\" : \"" << mime.description << "\"";
+    }
+
+    if (!mime.file_extensions.empty()) {
+      oss << ",\n"
+          << "       \"extensions\" : [ ";
+
+      for (size_t j = 0; j < mime.file_extensions.size(); ++j) {
+        if (j > 0)
+          oss << ", ";
+
+        oss << "\"" << mime.file_extensions[j] << "\"";
+      }
+
+      oss << " ]";
+    }
+
+    oss << "    }";
+  }
+
+  return oss.str();
+}
+
+std::string GeneratePMF(const ContentPluginInfo& plugin) {
+  std::ostringstream pmf_stream;
+  pmf_stream << "{"
+             << "  \"type\": \"pepper\",\n"
+             << "  \"name\": \"" << plugin.name << "\",\n"
+             << "  \"description\": \"" << plugin.description << "\",\n"
+             << "  \"version\": \"" << plugin.version << "\",\n"
+             << "  \"mimes\": [\n"
+             << PluginMimesToJSON(plugin) << "\n"
+             << "  ],\n"
+             << "  \"program\": { \n"
+             << "    \"url\": \"" << plugin.path.AsUTF8Unsafe() << "\"\n"
+             << "  }\n"
+             << "}";
+
+  return pmf_stream.str();
+}
+
+// uses |ContentPluginInfo.name| as file paths.
+void WritePluginFiles(const FilePath& plugin_dir,
+                      PluginFilesWriteOptions files_to_write,
+                      ContentPluginInfo* plugin) {
+  FilePath base_path = plugin_dir.AppendASCII(plugin->name);
+  plugin->path = AddLibrarySuffix(base_path);
+
+  std::string pmf = GeneratePMF(*plugin);
+  FilePath pmf_path = base_path.AddExtension(FILE_PATH_LITERAL(".pmf"));
+
+  ContentPluginInfo info;
+  ASSERT_TRUE(ParsePepperPluginManifest(pmf_path, pmf, &info));
+  ASSERT_TRUE(EqualPepperPluginInfo(*plugin, info));
+
+  int data_written = base::WriteFile(pmf_path, pmf.c_str(), pmf.size());
+  ASSERT_GE(data_written, 0);
+  ASSERT_EQ(pmf.size(), static_cast<size_t>(data_written));
+
+  if (files_to_write == PMF_AND_LIBRARY) {
+    std::string plugin_lib = plugin->name;
+    int plugin_data_written =
+        base::WriteFile(plugin->path, plugin_lib.c_str(), plugin_lib.size());
+    ASSERT_GE(plugin_data_written, 0);
+    ASSERT_EQ(plugin_lib.size(), static_cast<size_t>(plugin_data_written));
+  }
+
+  bool fill_plugin_res = FillPepperPluginInfoFromManifest(pmf_path, &info);
+  if (files_to_write == PMF_AND_LIBRARY) {
+    ASSERT_TRUE(fill_plugin_res);
+    ASSERT_TRUE(EqualPepperPluginInfo(*plugin, info));
+  } else {
+    ASSERT_FALSE(fill_plugin_res);
+  }
+}
+
+class TrustedPepperPluginInfoCacheTest : public testing::Test {
+ public:
+  TrustedPepperPluginInfoCacheTest() {}
+
+  void SetUp() override {
+    InitializePluginsDir();
+    InitializeEmptyDir();
+    cache_.reset(new TrustedPepperPluginInfoCache(dir_paths_));
+    ASSERT_NE(nullptr, cache_.get());
+  }
+
+ protected:
+  // Valid plugins added to temp dir, should be present in cache
+  std::vector<ContentPluginInfo> valid_plugins_;
+
+  // Plugins with invalid manifests which shouldn't be added
+  // to the cache
+  std::vector<ContentPluginInfo> invalid_plugins_;
+
+  std::unique_ptr<TrustedPepperPluginInfoCache> cache_;
+
+ private:
+  void CreatePluginInDir(const FilePath& dir,
+                         PluginFilesWriteOptions valid,
+                         ContentPluginInfo plugin) {
+    WritePluginFiles(dir, valid, &plugin);
+    if (valid == PMF_AND_LIBRARY)
+      valid_plugins_.push_back(plugin);
+    else
+      invalid_plugins_.push_back(plugin);
+  }
+
+  void InitializePluginsDir() {
+    ASSERT_TRUE(plugins_dir_.CreateUniqueTempDir());
+    dir_paths_.push_back(plugins_dir_.GetPath());
+
+    FilePath dir1;
+    ASSERT_TRUE(
+        CreateTemporaryDirInDir(plugins_dir_.GetPath(), "plugins1_", &dir1));
+
+    CreatePluginInDir(dir1, PMF_AND_LIBRARY, GetTestPlugin1());
+    CreatePluginInDir(dir1, PMF_AND_LIBRARY, GetTestPlugin2());
+
+    FilePath dir2;
+    ASSERT_TRUE(
+        CreateTemporaryDirInDir(plugins_dir_.GetPath(), "plugins2_", &dir2));
+
+    CreatePluginInDir(dir2, PMF_AND_LIBRARY, GetTestPlugin3());
+    CreatePluginInDir(dir2, PMF_ONLY, GetTestPlugin4());
+
+    FilePath dir3;
+    ASSERT_TRUE(
+        CreateTemporaryDirInDir(plugins_dir_.GetPath(), "plugins3_", &dir3));
+    CreatePluginInDir(dir3, PMF_ONLY, GetTestPlugin5());
+    CreatePluginInDir(dir3, PMF_AND_LIBRARY, GetTestPlugin6());
+  }
+
+  void InitializeEmptyDir() {
+    ASSERT_TRUE(empty_dir_.CreateUniqueTempDir());
+    dir_paths_.push_back(empty_dir_.GetPath());
+  }
+
+  base::ScopedTempDir plugins_dir_;
+  base::ScopedTempDir empty_dir_;
+  std::vector<base::FilePath> dir_paths_;
+};
+
+TEST(ParsePepperPluginManifestTest, MinimalManifest) {
+  std::string pmfs[] = {
+      "{"
+      "  \"type\": \"pepper\","
+      "  \"mimes\": ["
+      "    { \"type\": \"application/x-ppapi-minimal-manifest\" }"
+      "  ]"
+      "}",
+
+      "{"
+      "  \"not-specified-key\": \"some value\","
+      "  \"type\": \"pepper\","
+      "  \"mimes\": ["
+      "    { \"type\": \"application/x-ppapi-minimal-manifest\" }"
+      "  ],"
+      "  \"excessive-key\": \"excessive-value\""
+      "}"};
+
+  for (const auto& pmf : pmfs) {
+    LOG(INFO) << "Parsing pmf: " << pmf;
+    FilePath path(FILE_PATH_LITERAL("minimal_test.pmf"));
+
+    ContentPluginInfo info;
+    ASSERT_TRUE(ParsePepperPluginManifest(path, pmf, &info));
+
+    EXPECT_FALSE(info.is_internal);
+    EXPECT_TRUE(info.is_out_of_process);
+    EXPECT_EQ(info.permissions, ppapi::Permission::PERMISSION_ALL_BITS);
+    EXPECT_TRUE(info.name.empty());
+    EXPECT_TRUE(info.description.empty());
+    EXPECT_TRUE(info.version.empty());
+
+    ASSERT_EQ(1u, info.mime_types.size());
+    EXPECT_EQ("application/x-ppapi-minimal-manifest",
+              info.mime_types[0].mime_type);
+    EXPECT_TRUE(info.mime_types[0].file_extensions.empty());
+
+    FilePath expected_path(AddLibrarySuffix(path.RemoveExtension()));
+    EXPECT_EQ(expected_path, info.path);
+  }
+}
+
+TEST(ParsePepperPluginManifestTest, EmptyManifest) {
+  std::string pmfs[] = {"", "{}"};
+  FilePath path(FILE_PATH_LITERAL("empty_test.pmf"));
+
+  for (const auto& pmf : pmfs) {
+    ContentPluginInfo info;
+    EXPECT_FALSE(ParsePepperPluginManifest(path, pmf, &info));
+  }
+}
+
+TEST(ParsePepperPluginManifestTest, BadPluginType) {
+  std::string pmfs[] = {
+      // missing type
+      "{"
+      "   \"mimes\": [ { \"type\": \"application/x-ppapi-bad-type\" } ]"
+      "}",
+
+      "{"
+      "   \"type\": \"bad-type\","
+      "   \"mimes\": [ { \"type\": \"application/x-ppapi-bad-type\" } ]"
+      "}",
+
+      // space before pepper
+      "{"
+      "   \"type\": \" pepper\","
+      "   \"mimes\": [ { \"type\": \"application/x-ppapi-bad-type\" } ]"
+      "}"};
+  FilePath path(FILE_PATH_LITERAL("bad_type_test.pmf"));
+
+  for (const auto& pmf : pmfs) {
+    LOG(INFO) << "Parsing pmf: " << pmf;
+
+    ContentPluginInfo info;
+    EXPECT_FALSE(ParsePepperPluginManifest(path, pmf, &info));
+  }
+}
+
+TEST(ParsePepperPluginManifestTest, BadJSON) {
+  std::string pmfs[] = {
+      // no coma
+      "{"
+      "   \"type\": \"pepper\""  // no coma
+      "   \"mimes\": [ { \"type\": \"application/x-ppapi-bad-json\" } ]"
+      "}",
+
+      // Comma after last entry
+      "{"
+      "   \"type\": \"pepper\","
+      "   \"mimes\": [ { \"type\": \"application/x-ppapi-bad-json\" } ],"
+      "}",
+
+      // no double quotes (")
+      "{"
+      "   type: pepper,"
+      "   mimes: [ { \"type\": \"application/x-ppapi-bad-json\" } ],"
+      "}",
+
+      // root object is not a dictionary
+      "["
+      "  { \"type\": \"pepper\" },"
+      "  { \"mimes\": ["
+      "    { \"type\": \"application/x-ppapi-minimal-manifest\" }"
+      "  ] }"
+      "]",
+
+      // root object is not a dictionary
+      " \"type\": \"pepper\" "};
+  FilePath path(FILE_PATH_LITERAL("bad_type_test.pmf"));
+
+  for (const auto& pmf : pmfs) {
+    LOG(INFO) << "Parsing pmf: " << pmf;
+
+    ContentPluginInfo info;
+    EXPECT_FALSE(ParsePepperPluginManifest(path, pmf, &info));
+  }
+}
+
+TEST(ParsePepperPluginManifestTest, MultipleMimes) {
+  std::string pmf =
+      "{"
+      "  \"type\" : \"pepper\","
+      "  \"name\" : \"Sample Trusted Plugin\","
+      "  \"version\" : \"1.0\","
+      "  \"description\" : \"Example Pepper Trusted Plugin\","
+      "  \"mimes\" : ["
+      "     {"
+      "       \"type\" : \"application/x-ppapi-example\","
+      "       \"description\" : \"Example Ppapi\","
+      "       \"extensions\" : [ \".ext1\", \".ext2\" ]"
+      "     },"
+      "     {"
+      "       \"type\" : \"application/x-ppapi-example2\""
+      "     }"
+      "   ]"
+      " }";
+
+  ContentPluginInfo info;
+  FilePath path(FILE_PATH_LITERAL("libsample_plugin.pmf"));
+  ASSERT_TRUE(ParsePepperPluginManifest(path, pmf, &info));
+
+  EXPECT_FALSE(info.is_internal);
+  EXPECT_TRUE(info.is_out_of_process);
+  EXPECT_EQ(info.permissions, ppapi::Permission::PERMISSION_ALL_BITS);
+  EXPECT_EQ("Sample Trusted Plugin", info.name);
+  EXPECT_EQ("Example Pepper Trusted Plugin", info.description);
+  EXPECT_EQ("1.0", info.version);
+
+  ASSERT_EQ(2u, info.mime_types.size());
+  EXPECT_EQ("application/x-ppapi-example", info.mime_types[0].mime_type);
+  EXPECT_TRUE(
+      base::EqualsASCII(info.mime_types[0].description, "Example Ppapi"));
+  ASSERT_EQ(2u, info.mime_types[0].file_extensions.size());
+  EXPECT_EQ(".ext1", info.mime_types[0].file_extensions[0]);
+  EXPECT_EQ(".ext2", info.mime_types[0].file_extensions[1]);
+
+  EXPECT_EQ("application/x-ppapi-example2", info.mime_types[1].mime_type);
+  EXPECT_TRUE(info.mime_types[1].description.empty());
+  EXPECT_TRUE(info.mime_types[1].file_extensions.empty());
+
+  FilePath expected_path(AddLibrarySuffix(path.RemoveExtension()));
+  EXPECT_EQ(info.path, expected_path);
+}
+
+TEST(ParsePepperPluginManifestTest, EmptyMimes) {
+  std::string pmfs[] = {
+      // missing mimes key
+      "{"
+      "  \"type\" : \"pepper\""
+      "}",
+
+      // no mimes at all
+      "{"
+      "  \"type\" : \"pepper\","
+      "  \"mimes\" : ["
+      "  ]"
+      "}",
+
+      // missing type
+      "{"
+      "  \"type\" : \"pepper\","
+      "  \"mimes\" : ["
+      "    {"
+      "       \"description\" : \"Example Ppapi\","
+      "       \"extensions\" : [ \".ext1\", \".ext2\" ]"
+      "    }"
+      "  ]"
+      "}",
+  };
+  FilePath path(FILE_PATH_LITERAL("libsample_plugin.pmf"));
+
+  for (const auto& pmf : pmfs) {
+    LOG(INFO) << "Parsing pmf: " << pmf;
+
+    ContentPluginInfo info;
+    EXPECT_FALSE(ParsePepperPluginManifest(path, pmf, &info));
+  }
+}
+
+TEST(ParsePepperPluginManifestTest, InvalidProgramUrlKey) {
+  std::string pmfs[] = {
+      // empty program
+      "{"
+      "  \"type\" : \"pepper\","
+      "  \"mimes\": [ { \"type\": \"application/x-ppapi-invalid-url\" } ],"
+      "  \"program\": { }"
+      "}",
+
+      // valid path but not in url key
+      "{"
+      "  \"type\" : \"pepper\","
+      "  \"mimes\": [ { \"type\": \"application/x-ppapi-invalid-url\" } ],"
+      "  \"program\": \"libtest_plugin.so\""
+      "}",
+
+      // no url key
+      "{"
+      "  \"type\" : \"pepper\","
+      "  \"mimes\": [ { \"type\": \"application/x-ppapi-invalid-url\" } ],"
+      "  \"program\": { \"path\": \"libtest_plugin.so\" }"  // not an url key
+      "}",
+
+      // empty url key
+      "{"
+      "  \"type\" : \"pepper\","
+      "  \"mimes\": [ { \"type\": \"application/x-ppapi-invalid-url\" } ],"
+      "  \"program\": { \"url\": \"\" }"
+      "}"};
+
+  FilePath path(FILE_PATH_LITERAL("plugin_manifest.pmf"));
+  for (const auto& pmf : pmfs) {
+    LOG(INFO) << "Parsing pmf: " << pmf;
+
+    ContentPluginInfo info;
+    EXPECT_FALSE(ParsePepperPluginManifest(path, pmf, &info));
+  }
+}
+
+TEST(ParsePepperPluginManifestTest, ProgramUrlPaths) {
+  FilePath path(FILE_PATH_LITERAL("/my_plugin_dir/plugin_manifest.pmf"));
+
+  std::pair<std::string, FilePath::StringType> pmf_and_path_list[] = {
+      // Relative path
+      {"{"
+       "  \"type\" : \"pepper\","
+       "  \"name\" : \"Test Trusted Plugin\","
+       "  \"version\" : \"1.2\","
+       "  \"description\" : \"Test Trusted Pepper Plugin\","
+       "  \"mimes\": [ { \"type\": \"application/x-ppapi-test\" } ],"
+       "  \"program\": { \"url\": \"libtest_plugin.so\" }"
+       "}",
+       FILE_PATH_LITERAL("/my_plugin_dir/libtest_plugin.so")},
+
+      // Absolute path
+      {"{"
+       "  \"type\" : \"pepper\","
+       "  \"name\" : \"Test Trusted Plugin\","
+       "  \"version\" : \"1.2\","
+       "  \"description\" : \"Test Trusted Pepper Plugin\","
+       "  \"mimes\": [ { \"type\": \"application/x-ppapi-test\" } ],"
+       "  \"program\": { \"url\": \"/my_lib_dir/libtest_plugin.so\" }"
+       "}",
+       FILE_PATH_LITERAL("/my_lib_dir/libtest_plugin.so")},
+
+      // Deduced path
+      {"{"
+       "  \"type\" : \"pepper\","
+       "  \"name\" : \"Test Trusted Plugin\","
+       "  \"version\" : \"1.2\","
+       "  \"description\" : \"Test Trusted Pepper Plugin\","
+       "  \"mimes\": [ { \"type\": \"application/x-ppapi-test\" } ]"
+       "}",
+       FILE_PATH_LITERAL("/my_plugin_dir/plugin_manifest.so")}};
+
+  for (const auto& entry : pmf_and_path_list) {
+    const auto& pmf = entry.first;
+    const auto& expected_path = entry.second;
+    LOG(INFO) << "Parsing pmf: " << pmf;
+
+    ContentPluginInfo info;
+    EXPECT_TRUE(ParsePepperPluginManifest(path, pmf, &info));
+
+    EXPECT_FALSE(info.is_internal);
+    EXPECT_TRUE(info.is_out_of_process);
+    EXPECT_EQ(info.permissions, ppapi::Permission::PERMISSION_ALL_BITS);
+    EXPECT_EQ("Test Trusted Plugin", info.name);
+    EXPECT_EQ("Test Trusted Pepper Plugin", info.description);
+    EXPECT_EQ("1.2", info.version);
+
+    EXPECT_EQ(1u, info.mime_types.size());
+    if (info.mime_types.size() == 1) {
+      EXPECT_EQ("application/x-ppapi-test", info.mime_types[0].mime_type);
+      EXPECT_TRUE(info.mime_types[0].description.empty());
+      EXPECT_TRUE(info.mime_types[0].file_extensions.empty());
+    }
+
+    EXPECT_EQ(FilePath(expected_path), info.path);
+  }
+}
+
+TEST(FillPepperPluginInfoFromManifestTest, InvalidManifest) {
+  std::string pmf =
+      // empty url key
+      "{"
+      "  \"type\" : \"pepper\","
+      "  \"mimes\": [ { \"type\": \"application/x-ppapi-invalid-url\" } ],"
+      "  \"program\": { \"url\": \"\" }"
+      "}";
+
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  FilePath path;
+  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &path));
+
+  int data_written = WriteFile(path, pmf.c_str(), pmf.size());
+  ASSERT_GE(data_written, 0);
+  ASSERT_EQ(pmf.size(), static_cast<size_t>(data_written));
+
+  ContentPluginInfo info;
+  EXPECT_FALSE(FillPepperPluginInfoFromManifest(path, &info));
+}
+
+TEST(FillPepperPluginInfoFromManifestTest, NonExsistingManifest) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  FilePath path;
+  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &path));
+
+  FilePath non_existing_path = path.AddExtension(".non_exsisting");
+  ASSERT_FALSE(base::PathExists(non_existing_path));
+
+  ContentPluginInfo info;
+  EXPECT_FALSE(FillPepperPluginInfoFromManifest(path, &info));
+}
+
+TEST(FillPepperPluginInfoFromManifestTest, WrongLibraryPath) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  FilePath path;
+  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &path));
+
+  FilePath non_existing_path = path.AddExtension(".non_exsisting");
+  ASSERT_FALSE(base::PathExists(non_existing_path));
+
+  std::ostringstream pmf_stream;
+  pmf_stream << "{"
+             << "  \"type\": \"pepper\","
+             << "  \"mimes\": ["
+             << "    { \"type\": \"application/x-ppapi-minimal-manifest\" }"
+             << "  ],"
+             << "  \"program\": "
+             << "    { \"url\": \"" << non_existing_path.AsUTF8Unsafe()
+             << "\" }"
+             << "}";
+  std::string pmf = pmf_stream.str();
+
+  ContentPluginInfo info;
+  ASSERT_TRUE(ParsePepperPluginManifest(path, pmf, &info));
+
+  int data_written = base::WriteFile(path, pmf.c_str(), pmf.size());
+  ASSERT_GE(data_written, 0);
+  ASSERT_EQ(pmf.size(), static_cast<size_t>(data_written));
+
+  EXPECT_FALSE(FillPepperPluginInfoFromManifest(path, &info));
+}
+
+TEST(FillPepperPluginInfoFromManifestTest, ValidManifest) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  FilePath pmf_path;
+  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &pmf_path));
+
+  FilePath plugin_path;
+  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &plugin_path));
+
+  std::ostringstream pmf_stream;
+  pmf_stream << "{"
+             << "  \"type\": \"pepper\","
+             << "  \"mimes\": ["
+             << "    { \"type\": \"application/x-ppapi-minimal-manifest\" }"
+             << "  ],"
+             << "  \"program\": "
+             << "    { \"url\": \"" << plugin_path.AsUTF8Unsafe() << "\" }"
+             << "}";
+  std::string pmf = pmf_stream.str();
+
+  ContentPluginInfo info;
+  ASSERT_TRUE(ParsePepperPluginManifest(pmf_path, pmf, &info));
+
+  int data_written = base::WriteFile(pmf_path, pmf.c_str(), pmf.size());
+  ASSERT_GE(data_written, 0);
+  ASSERT_EQ(pmf.size(), static_cast<size_t>(data_written));
+
+  EXPECT_TRUE(FillPepperPluginInfoFromManifest(pmf_path, &info));
+}
+
+TEST_F(TrustedPepperPluginInfoCacheTest, GetPlugins) {
+  // Test checks:
+  // 1. That plugins all plugins present in cache are listed
+  //    exacly once in plugins vector passed to
+  //    |TrustedPepperPluginInfoCache::GetPlugins|
+  // 2. That plugins present in vector passed to
+  //    |TrustedPepperPluginInfoCache::GetPlugins| are not added
+  //    for the 2nd time
+  // 3. Entries present in vector passed to
+  //    |TrustedPepperPluginInfoCache::GetPlugins| and not present in cache
+  //    are untouched.
+  //
+  // To acheive that:
+  // - set of all plugins present in cache and not present in cache
+  //   is build
+  // - for all subsets it is checked that passing such subset to
+  //   |TrustedPepperPluginInfoCache::GetPlugins| will result
+  //   in behavior from point 1 - 3.
+  using PluginEntry = std::tuple<ContentPluginInfo, bool, bool>;
+  std::vector<PluginEntry> all_plugins;
+
+  for (const auto& plugin : valid_plugins_)
+    all_plugins.emplace_back(plugin, true, false);
+
+  for (const auto& plugin : invalid_plugins_)
+    all_plugins.emplace_back(plugin, false, false);
+
+  // This test browses all subsets, so ensure that it won't last to long
+  ASSERT_LT(all_plugins.size(), 16u)
+      << "Too much plugins - test will lasts to long";
+
+  uint32_t subsets_count = 1 << all_plugins.size();
+  LOG(INFO) << "all_plugins.size: " << all_plugins.size();
+  LOG(INFO) << "subsets_count: " << subsets_count;
+
+  // Process all subsets of |all_plugins|
+  for (uint32_t subset = 0; subset < subsets_count; ++subset) {
+    LOG(INFO) << "processing subset: " << subset << " hex: " << std::hex
+              << subset;
+
+    // Build initial plugins vector and compute how much plugins should be
+    // added from cache to the vector.
+    std::vector<ContentPluginInfo> init_plugins;
+    size_t missing_plugins_count = valid_plugins_.size();
+    for (size_t i = 0; i < all_plugins.size(); ++i) {
+      std::get<2>(all_plugins[i]) = (subset & (1 << i));
+
+      if (std::get<1>(all_plugins[i]) && std::get<2>(all_plugins[i]))
+        --missing_plugins_count;
+
+      if (std::get<2>(all_plugins[i]))
+        init_plugins.push_back(std::get<0>(all_plugins[i]));
+    }
+    std::vector<ContentPluginInfo> plugins = init_plugins;
+
+    // Call |TrustedPepperPluginInfoCache::GetPlugins| and fill plugins vector
+    cache_->GetPlugins(&plugins);
+
+    // Test that required plugins were added to the vector
+    size_t expected_plugins_size = init_plugins.size() + missing_plugins_count;
+    EXPECT_EQ(expected_plugins_size, plugins.size());
+    EXPECT_LE(init_plugins.size(), plugins.size());
+
+    // Check that initial pluings in vector are left untouched
+    if (init_plugins.size() <= plugins.size()) {
+      EXPECT_TRUE(std::equal(init_plugins.cbegin(), init_plugins.cend(),
+                             plugins.cbegin(), EqualPepperPluginInfo));
+    }
+
+    // Check that all valid are present in |plugins| exactly once
+    for (const auto& plugin : valid_plugins_) {
+      EXPECT_EQ(1, count_if(plugins.cbegin(), plugins.cend(),
+                            [&plugin](const ContentPluginInfo& info) {
+                              return EqualPepperPluginInfo(plugin, info);
+                            }));
+    }
+  }
+}
+
+TEST_F(TrustedPepperPluginInfoCacheTest, FindValidPlugin) {
+  for (const auto& plugin : valid_plugins_) {
+    for (const auto& web_plugin_mime : plugin.mime_types) {
+      ContentPluginInfo found_plugin;
+      EXPECT_TRUE(
+          cache_->FindPlugin(web_plugin_mime.mime_type, GURL(), &found_plugin));
+      EXPECT_TRUE(EqualPepperPluginInfo(plugin, found_plugin));
+    }
+  }
+}
+
+TEST_F(TrustedPepperPluginInfoCacheTest, FindInvalidPlugin) {
+  for (const auto& plugin : invalid_plugins_) {
+    for (const auto& web_plugin_mime : plugin.mime_types) {
+      ContentPluginInfo found_plugin;
+      EXPECT_FALSE(
+          cache_->FindPlugin(web_plugin_mime.mime_type, GURL(), &found_plugin));
+    }
+  }
+}
+
+TEST_F(TrustedPepperPluginInfoCacheTest, FindNonExistingMimes) {
+  for (const auto& mime_type : kNonExistingMimes) {
+    ContentPluginInfo found_plugin;
+    EXPECT_FALSE(cache_->FindPlugin(mime_type, GURL(), &found_plugin));
+  }
+}
+
+TEST_F(TrustedPepperPluginInfoCacheTest, FindByUrl) {
+  GURL url = GURL("file:///example.swf");
+  ContentPluginInfo found_plugin;
+  EXPECT_TRUE(cache_->FindPlugin("", url, &found_plugin));
+  EXPECT_STREQ("application/x-shockwave-flash",
+               found_plugin.mime_types[0].mime_type.data());
+}
+
+}  // namespace
+}  // namespace pepper
diff --git a/tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_util.cc b/tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_util.cc
new file mode 100644 (file)
index 0000000..dd9ed5f
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2016 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 "common/trusted_pepper_plugin_util.h"
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "common/application_type.h"
+#include "common/content_switches_efl.h"
+#include "common/trusted_pepper_plugin_info_cache.h"
+#include "content/browser/plugin_service_impl.h"
+#include "content/public/common/content_plugin_info.h"
+#include "content/renderer/pepper/pepper_plugin_registry.h"
+
+using content::ContentPluginInfo;
+using content::PepperPluginRegistry;
+using content::PluginServiceImpl;
+using pepper::TrustedPepperPluginInfoCache;
+
+namespace pepper {
+
+void UpdatePluginService(Ewk_Application_Type embedder_type) {
+  // Don't need to check kEnableTrustedPepperPlugins command line switch,
+  // because in that case Trusted Pepper Plugins will be added to
+  // PluginServiceImpl at its initialization by call to
+  // ContentClientEfl::AddPepperPlugins.
+  if (embedder_type == EWK_APPLICATION_TYPE_WEBBROWSER)
+    return;
+
+  std::vector<ContentPluginInfo> plugins;
+  TrustedPepperPluginInfoCache::GetInstance()->GetPlugins(&plugins);
+  PluginServiceImpl::GetInstance()->AddPepperPlugins(plugins);
+}
+
+void UpdatePluginRegistry() {
+  // Don't need to check kEnableTrustedPepperPlugins command line switch,
+  // because in that case Trusted Pepper Plugins will be added to
+  // PepperPluginRegistry at its initialization by call to
+  // ContentClientEfl::AddPepperPlugins.
+  if (content::IsWebBrowser())
+    return;
+
+  std::vector<ContentPluginInfo> plugins;
+  TrustedPepperPluginInfoCache::GetInstance()->GetPlugins(&plugins);
+  PepperPluginRegistry::GetInstance()->AddOutOfProcessPlugins(plugins);
+}
+
+bool AreTrustedPepperPluginsDisabled() {
+  auto command_line = base::CommandLine::ForCurrentProcess();
+  return
+#if defined(OS_TIZEN_TV_PRODUCT)
+      content::IsWebBrowser() &&
+#endif
+      !command_line->HasSwitch(switches::kEnableTrustedPepperPlugins);
+}
+}  // namespace pepper
diff --git a/tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_util.h b/tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_util.h
new file mode 100644 (file)
index 0000000..71215ea
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 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 TIZEN_SRC_EWK_EFL_INTEGRATION_COMMON_TRUSTED_PEPPER_PLUGIN_UTIL_H_
+#define TIZEN_SRC_EWK_EFL_INTEGRATION_COMMON_TRUSTED_PEPPER_PLUGIN_UTIL_H_
+
+#include "tizen_src/ewk/efl_integration/public/ewk_context_product.h"
+
+namespace pepper {
+
+// Updates list of pepper plugins held by PluginServiceImpl.
+// Call this function in browser process after embedder type has been
+// properly initialized.
+void UpdatePluginService(Ewk_Application_Type embedder_type);
+
+// Update list of pepper plugins held by PepperPluginRegistry.
+// Call this function in renderer process after embedder type has been
+// properly initialized.
+void UpdatePluginRegistry();
+
+// Due to security reasons such trusted pepper plugins are disabled in
+// WebBrowser embedder, unless explicitly allowed by command line switch.
+bool AreTrustedPepperPluginsDisabled();
+}  // namespace pepper
+
+#endif  // TIZEN_SRC_EWK_EFL_INTEGRATION_COMMON_TRUSTED_PEPPER_PLUGIN_UTIL_H_
index 58b9c64..1d0d71d 100644 (file)
 
 #include "private/ewk_notification_private.h"
 
+#if BUILDFLAG(ENABLE_NACL) || \
+    (defined(TIZEN_PEPPER_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS))
+#include "content/browser/renderer_host/pepper/browser_pepper_host_factory_efl.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "ppapi/host/ppapi_host.h"
+#endif
+
 #if defined(TIZEN_WEB_SPEECH_RECOGNITION)
 #include "content/browser/speech/tizen_speech_recognition_manager_delegate.h"
 #endif
@@ -450,6 +457,15 @@ ContentBrowserClientEfl::CreateDevToolsManagerDelegate() {
 }
 /* LCOV_EXCL_STOP */
 
+#if BUILDFLAG(ENABLE_NACL) || \
+    (defined(TIZEN_PEPPER_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS))
+void ContentBrowserClientEfl::DidCreatePpapiPlugin(
+    content::BrowserPpapiHost* browser_host) {
+  browser_host->GetPpapiHost()->AddHostFactoryFilter(
+      std::make_unique<BrowserPepperHostFactoryEfl>(browser_host));
+}
+#endif
+
 std::string ContentBrowserClientEfl::GetApplicationLocale() {
   char* local_default = setlocale(LC_CTYPE, 0);
   if (!local_default)
index 5c480fc..534ea91 100644 (file)
@@ -12,6 +12,8 @@
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "third_party/blink/public/web/web_window_features.h"
 #include "tizen/system_info.h"
+#include "components/nacl/common/buildflags.h"
+#include "ppapi/buildflags/buildflags.h"
 
 namespace base {
 class CommandLine;
@@ -112,6 +114,10 @@ class ContentBrowserClientEfl : public ContentBrowserClient {
   DevToolsManagerDelegate* GetDevToolsManagerDelegate();
   std::unique_ptr<content::DevToolsManagerDelegate>
   CreateDevToolsManagerDelegate() override;
+#if BUILDFLAG(ENABLE_NACL) || \
+    (defined(TIZEN_PEPPER_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS))
+  void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;
+#endif
   std::string GetApplicationLocale() override;
   std::unique_ptr<WebContentsViewDelegate> GetWebContentsViewDelegate(
       WebContents* web_contents) override;
index ae7d827..d2b4765 100644 (file)
 #include "public/ewk_media_downloadable_font_info.h"
 #endif // OS_TIZEN_TV_PRODUCT
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "efl/window_factory.h"
+#include "ewk/efl_integration/ewk_privilege_checker.h"
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+
+#if defined(USE_WAYLAND) && defined(TIZEN_PEPPER_EXTENSIONS)
+#include <Ecore_Wayland.h>
+#endif  // defined(USE_WAYLAND)
+
 using namespace content;
 using web_contents_utils::WebViewFromWebContents;
 
@@ -375,6 +384,9 @@ void EWebView::Initialize() {
 
   scroll_detector_.reset(new ScrollDetector(this));
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+  InitializePepperExtensionSystem();
+#endif
   DCHECK(web_contents_->GetRenderViewHost());
   // Settings (content::WebPreferences) will be initalized by
   // RenderViewHostImpl::ComputeWebkitPrefs() based on command line switches.
@@ -433,6 +445,9 @@ EWebView::~EWebView() {
   cbce->RemoveAcceptLangsChangedCallback(
       std::move(accept_langs_changed_callback_));
 #endif
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+  UnregisterPepperExtensionDelegate();
+#endif
 
   evas_object_event_callback_del(native_view_, EVAS_CALLBACK_RESIZE,
                                  EWebView::NativeViewResize);
@@ -3083,6 +3098,94 @@ void EWebView::ReplyBeforeUnloadConfirmPanel(Eina_Bool result) {
   GetJavaScriptDialogManagerEfl()->ReplyBeforeUnloadConfirmPanel(result);
 }
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+void EWebView::InitializePepperExtensionSystem() {
+  RegisterPepperExtensionDelegate();
+  SetWindowId();
+}
+
+EwkExtensionSystemDelegate* EWebView::GetExtensionDelegate() {
+  RenderFrameHost* render_frame_host = web_contents_->GetPrimaryMainFrame();
+  if (!render_frame_host)
+    return nullptr;
+
+  ExtensionSystemDelegateManager::RenderFrameID id;
+  id.render_process_id = render_frame_host->GetProcess()->GetID();
+  id.render_frame_id = render_frame_host->GetRoutingID();
+  return static_cast<EwkExtensionSystemDelegate*>(
+      ExtensionSystemDelegateManager::GetInstance()->GetDelegateForFrame(id));
+}
+
+void EWebView::SetWindowId() {
+  EwkExtensionSystemDelegate* delegate = GetExtensionDelegate();
+  if (!delegate) {
+    LOG(WARNING) << "No delegate is available to set window id";
+    return;
+  }
+  Evas_Object* main_wind =
+      efl::WindowFactory::GetHostWindow(web_contents_.get());
+  if (!main_wind) {
+    LOG(ERROR) << "Can`t get main window";
+    return;
+  }
+  delegate->SetWindowId(main_wind);
+}
+
+void EWebView::SetPepperExtensionWidgetInfo(Ewk_Value widget_pepper_ext_info) {
+  EwkExtensionSystemDelegate* delegate = GetExtensionDelegate();
+  if (!delegate) {
+    LOG(WARNING) << "No delegate is available to set extension info";
+    return;
+  }
+  delegate->SetExtensionInfo(widget_pepper_ext_info);
+}
+
+void EWebView::SetPepperExtensionCallback(Generic_Sync_Call_Callback cb,
+                                          void* data) {
+  EwkExtensionSystemDelegate* delegate = GetExtensionDelegate();
+  if (!delegate) {
+    LOG(WARNING) << "No delegate is available to set generic callback";
+    return;
+  }
+  delegate->SetGenericSyncCallback(cb, data);
+}
+
+void EWebView::RegisterPepperExtensionDelegate() {
+  RenderFrameHost* render_frame_host = web_contents_->GetPrimaryMainFrame();
+  if (!render_frame_host) {
+    LOG(WARNING) << "render_frame_host is nullptr, can't register delegate";
+    return;
+  }
+
+  ExtensionSystemDelegateManager::RenderFrameID id;
+  id.render_process_id = render_frame_host->GetProcess()->GetID();
+  id.render_frame_id = render_frame_host->GetRoutingID();
+
+  EwkExtensionSystemDelegate* delegate = new EwkExtensionSystemDelegate;
+  ExtensionSystemDelegateManager::GetInstance()->RegisterDelegate(
+      id, std::unique_ptr<EwkExtensionSystemDelegate>{delegate});
+}
+
+void EWebView::UnregisterPepperExtensionDelegate() {
+  if (!web_contents_) {
+    LOG(WARNING) << "web_contents_ is nullptr, can't unregister delegate";
+    return;
+  }
+  RenderFrameHost* render_frame_host = web_contents_->GetPrimaryMainFrame();
+  if (!render_frame_host) {
+    LOG(WARNING) << "render_frame_host is nullptr, can't unregister delegate";
+    return;
+  }
+
+  ExtensionSystemDelegateManager::RenderFrameID id;
+  id.render_process_id = render_frame_host->GetProcess()->GetID();
+  id.render_frame_id = render_frame_host->GetRoutingID();
+
+  if (!ExtensionSystemDelegateManager::GetInstance()->UnregisterDelegate(id))
+    LOG(WARNING) << "Unregistering pepper extension delegate failed";
+}
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+
 void EWebView::SetExceededIndexedDatabaseQuotaCallback(
     Ewk_View_Exceeded_Indexed_Database_Quota_Callback callback,
     void* user_data) {
index 2a65608..8d78dde 100644 (file)
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/size.h"
 #include "web_contents_delegate_efl.h"
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "ewk_extension_system_delegate.h"
+#include "public/ewk_value_product.h"
+#endif
 
 namespace aura {
 namespace client {
@@ -696,6 +700,15 @@ class EWebView {
   void InitAtk();
   bool GetAtkStatus();
 #endif
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+  void InitializePepperExtensionSystem();
+  EwkExtensionSystemDelegate* GetExtensionDelegate();
+  void SetWindowId();
+  void SetPepperExtensionWidgetInfo(Ewk_Value widget_pepper_ext_info);
+  void SetPepperExtensionCallback(Generic_Sync_Call_Callback cb, void* data);
+  void RegisterPepperExtensionDelegate();
+  void UnregisterPepperExtensionDelegate();
+#endif
 
   bool ShouldIgnoreNavigation(content::NavigationHandle* navigation_handle);
 
diff --git a/tizen_src/ewk/efl_integration/ewk_extension_system_delegate.cc b/tizen_src/ewk/efl_integration/ewk_extension_system_delegate.cc
new file mode 100644 (file)
index 0000000..fdd08f6
--- /dev/null
@@ -0,0 +1,267 @@
+// Copyright 2016 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/efl_integration/ewk_extension_system_delegate.h"
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "chromium_impl/build/tizen_version.h"
+#include "ppapi/cpp/samsung/extension_system_samsung_wrt.h"
+#include "private/ewk_value_private.h"
+
+#if defined(OS_TIZEN_TV_PRODUCT) && defined(USE_WAYLAND)
+#include <Ecore_Evas.h>
+#if TIZEN_VERSION_AT_LEAST(5, 0, 0)
+#include <Ecore_Wl2.h>
+#else
+#include <Ecore_Wayland.h>
+#endif
+#include <tizen-extension-client-protocol.h>
+#endif  // defined(OS_TIZEN_TV_PRODUCT) && defined(USE_WAYLAND)
+
+namespace {
+static const char kTypeWebBrowserName[] = "WebBrowser";
+static const char kTypeTizenWrtName[] = "TizenWRT";
+static const char kTypeHbbTvName[] = "HbbTV";
+static const char kTypeUnrecognized[] = "UnrecognizedEmbedder";
+
+static base::LazyInstance<std::string>::Leaky current_embedder_name =
+    LAZY_INSTANCE_INITIALIZER;
+
+#if defined(OS_TIZEN_TV_PRODUCT) && defined(USE_WAYLAND)
+
+struct WLRegistryDestroy {
+  void operator()(void* x) const {
+    wl_registry* registry = static_cast<wl_registry*>(x);
+    wl_registry_destroy(registry);
+  }
+};
+
+struct TizenSurfaceDestroy {
+  void operator()(void* x) const {
+    tizen_surface* surface = static_cast<tizen_surface*>(x);
+    tizen_surface_destroy(surface);
+  }
+};
+
+struct TizenResourceDestroy {
+  void operator()(void* x) const {
+    tizen_resource* resource = static_cast<tizen_resource*>(x);
+    tizen_resource_destroy(resource);
+  }
+};
+
+struct WLEventQueueDestroy {
+  void operator()(void* x) const {
+    wl_event_queue* queue = static_cast<wl_event_queue*>(x);
+    wl_event_queue_destroy(queue);
+  }
+};
+
+static void HandleGlobal(void* data,
+                         wl_registry* registry,
+                         uint32_t name,
+                         const char* interface,
+                         uint32_t version) {
+  if (data && strcmp(interface, "tizen_surface") == 0) {
+    void** surface = reinterpret_cast<void**>(data);
+    *surface =
+        wl_registry_bind(registry, name, &tizen_surface_interface, version);
+  }
+}
+
+static void RemoveGlobal(void* data,
+                         struct wl_registry* wl_registry,
+                         uint32_t name) {}
+
+const struct wl_registry_listener registry_listener = {HandleGlobal,
+                                                       RemoveGlobal};
+
+void HandleResourceId(void* data, tizen_resource* tizen_resource, uint32_t id) {
+  if (data)
+    *reinterpret_cast<int*>(data) = id;
+}
+
+const struct tizen_resource_listener tz_resource_listener = {
+    HandleResourceId,
+};
+
+int GetSurfaceResourceId(wl_surface* surface, wl_display* display) {
+  using ScopedWLRegistry = std::unique_ptr<wl_registry, WLRegistryDestroy>;
+  using ScopedWLEventQueue =
+      std::unique_ptr<wl_event_queue, WLEventQueueDestroy>;
+  using ScopedTizenSurface =
+      std::unique_ptr<tizen_surface, TizenSurfaceDestroy>;
+  using ScopedTizenResource =
+      std::unique_ptr<tizen_resource, TizenResourceDestroy>;
+
+  DCHECK(surface && display);
+  if (surface == nullptr || display == nullptr)
+    return 0;
+
+  ScopedWLEventQueue event_queue(wl_display_create_queue(display));
+  DCHECK(event_queue.get());
+  if (event_queue == nullptr)
+    return 0;
+
+  ScopedWLRegistry registry(wl_display_get_registry(display));
+  DCHECK(registry.get());
+  if (registry == nullptr)
+    return 0;
+  wl_proxy_set_queue(reinterpret_cast<wl_proxy*>(registry.get()),
+                     event_queue.get());
+
+  tizen_surface* tz_surface_raw = nullptr;
+  wl_registry_add_listener(registry.get(), &registry_listener, &tz_surface_raw);
+  wl_display_dispatch_queue(display, event_queue.get());
+  wl_display_roundtrip_queue(display, event_queue.get());
+  DCHECK(tz_surface_raw);
+  if (tz_surface_raw == nullptr)
+    return 0;
+  ScopedTizenSurface tz_surface(tz_surface_raw);
+
+  ScopedTizenResource tz_resource(
+      tizen_surface_get_tizen_resource(tz_surface.get(), surface));
+  DCHECK(tz_resource.get());
+  if (tz_resource.get() == nullptr)
+    return 0;
+  wl_proxy_set_queue(reinterpret_cast<wl_proxy*>(tz_resource.get()),
+                     event_queue.get());
+
+  int wl_surface_id = 0;
+  tizen_resource_add_listener(tz_resource.get(), &tz_resource_listener,
+                              &wl_surface_id);
+  wl_display_roundtrip_queue(display, event_queue.get());
+  return wl_surface_id;
+}
+
+#if TIZEN_VERSION_AT_LEAST(5, 0, 0)
+int GetWaylandWindowId(Ecore_Wl2_Window* ew) {
+  wl_surface* surface = ecore_wl2_window_surface_get(ew);
+  Ecore_Wl2_Display* wl2_display = ecore_wl2_connected_display_get(NULL);
+  wl_display* display = ecore_wl2_display_get(wl2_display);
+  return GetSurfaceResourceId(surface, display);
+}
+#else
+int GetWaylandWindowId(Ecore_Wl_Window* ew) {
+  wl_surface* surface = ecore_wl_window_surface_get(ew);
+  wl_display* display = static_cast<wl_display*>(ecore_wl_display_get());
+  return GetSurfaceResourceId(surface, display);
+}
+#endif  // TIZEN_VERSION_AT_LEAST(5, 0, 0)
+
+#endif  // defined(OS_TIZEN_TV_PRODUCT) && defined(USE_WAYLAND)
+
+}  // namespace
+
+EwkExtensionSystemDelegate::EwkExtensionSystemDelegate()
+    : info_(nullptr), cb_(nullptr), cb_data_(nullptr), window_id_(0) {}
+
+EwkExtensionSystemDelegate::~EwkExtensionSystemDelegate() {
+  ewk_value_unref(info_);
+}
+
+std::string EwkExtensionSystemDelegate::GetEmbedderName() const {
+  return current_embedder_name.Get();
+}
+
+std::unique_ptr<base::Value> EwkExtensionSystemDelegate::GetExtensionInfo()
+    const {
+  base::AutoLock guard{access_lock_};
+  if (!info_)
+    return std::make_unique<base::Value>();
+  return static_cast<const EwkValuePrivate*>(info_)
+      ->GetValue()
+      ->CreateDeepCopy();
+}
+
+int EwkExtensionSystemDelegate::GetWindowId() const {
+  return window_id_;
+}
+
+std::unique_ptr<base::Value> EwkExtensionSystemDelegate::GenericSyncCall(
+    const std::string& name,
+    const base::Value& data) {
+  base::AutoLock guard{access_lock_};
+  if (!cb_)
+    return std::make_unique<base::Value>();
+
+  Ewk_Value arg = static_cast<Ewk_Value>(
+      new EwkValuePrivate(data.CreateDeepCopy()));
+  ewk_value_ref(arg);
+  Ewk_Value result = cb_(name.c_str(), arg, cb_data_);
+  ewk_value_unref(arg);
+  if (!result)
+    return std::make_unique<base::Value>();
+  std::unique_ptr<base::Value> ret =
+      static_cast<const EwkValuePrivate*>(result)->GetValue()->CreateDeepCopy();
+  ewk_value_unref(result);
+  return ret;
+}
+
+void EwkExtensionSystemDelegate::SetEmbedderName(
+    const Ewk_Application_Type embedder_type) {
+  switch (embedder_type) {
+    case EWK_APPLICATION_TYPE_WEBBROWSER:
+      current_embedder_name.Get() = kTypeWebBrowserName;
+      break;
+    case EWK_APPLICATION_TYPE_HBBTV:
+      current_embedder_name.Get() = kTypeHbbTvName;
+      break;
+    case EWK_APPLICATION_TYPE_TIZENWRT:
+      current_embedder_name.Get() = kTypeTizenWrtName;
+      break;
+    default:
+      current_embedder_name.Get() = kTypeUnrecognized;
+      break;
+  }
+}
+
+void EwkExtensionSystemDelegate::SetExtensionInfo(Ewk_Value info) {
+  base::AutoLock guard{access_lock_};
+
+  ewk_value_ref(info);
+  // Unref current info_, if already set
+  ewk_value_unref(info_);
+  info_ = info;
+}
+
+void EwkExtensionSystemDelegate::SetGenericSyncCallback(
+    Generic_Sync_Call_Callback cb,
+    void* data) {
+  base::AutoLock guard{access_lock_};
+  cb_ = cb;
+  cb_data_ = data;
+}
+
+void EwkExtensionSystemDelegate::SetWindowId(const Evas_Object* main_window) {
+#if defined(OS_TIZEN_TV_PRODUCT)
+  Evas* evas = evas_object_evas_get(main_window);
+  if (!evas) {
+    LOG(ERROR) << "Evas can`t be acquired for main window";
+    return;
+  }
+  const Ecore_Evas* ee = ecore_evas_ecore_evas_get(evas);
+  if (!ee) {
+    LOG(ERROR) << "Ecore_Evas can`t be acquired from main window Evas";
+    return;
+  }
+#if defined(USE_WAYLAND)&&!defined(USE_AURA)
+#if TIZEN_VERSION_AT_LEAST(5, 0, 0)
+  Ecore_Wl2_Window* ww = ecore_evas_wayland2_window_get(ee);
+#else
+  Ecore_Wl_Window* ww = ecore_evas_wayland_window_get(ee);
+#endif  // TIZEN_VERSION_AT_LEAST(5, 0, 0)
+  if (!ww) {
+    LOG(ERROR) << "Can`t get Wl window";
+    return;
+  }
+  window_id_ = GetWaylandWindowId(ww);
+#else
+  Ecore_X_Window ww = ecore_evas_gl_x11_window_get(ee);
+  window_id_ = static_cast<int>(ww);
+#endif  // defined(USE_WAYLAND)
+#endif  // defined(OS_TIZEN_TV_PRODUCT)
+}
diff --git a/tizen_src/ewk/efl_integration/ewk_extension_system_delegate.h b/tizen_src/ewk/efl_integration/ewk_extension_system_delegate.h
new file mode 100644 (file)
index 0000000..f84bec2
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2016 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 TIZEN_SRC_EWK_EFL_INTEGRATION_EWK_EXTENSION_SYSTEM_DELEGATE_H_
+#define TIZEN_SRC_EWK_EFL_INTEGRATION_EWK_EXTENSION_SYSTEM_DELEGATE_H_
+
+#include <string>
+
+#include "base/synchronization/lock.h"
+#include "content/public/browser/extension_system_delegate.h"
+#include "public/ewk_context_product.h"
+#include "public/ewk_value_product.h"
+#include "public/ewk_view_product.h"
+
+class EwkExtensionSystemDelegate : public content::ExtensionSystemDelegate {
+ public:
+  EwkExtensionSystemDelegate();
+  ~EwkExtensionSystemDelegate() override;
+
+  std::string GetEmbedderName() const override;
+  std::unique_ptr<base::Value> GetExtensionInfo() const override;
+  std::unique_ptr<base::Value> GenericSyncCall(
+      const std::string& name,
+      const base::Value& data) override;
+
+  int GetWindowId() const override;
+
+  static void SetEmbedderName(const Ewk_Application_Type embedder_type);
+  void SetExtensionInfo(Ewk_Value info);
+  void SetGenericSyncCallback(Generic_Sync_Call_Callback cb, void* data);
+
+  void SetWindowId(const Evas_Object* main_window);
+
+ private:
+  Ewk_Value info_;
+  Generic_Sync_Call_Callback cb_;
+  void* cb_data_;
+  int window_id_;
+
+  // TODO(a.bujalski) Check if it is possible to call WRT's cb on IO thread.
+  mutable base::Lock access_lock_;
+};
+
+#endif  // TIZEN_SRC_EWK_EFL_INTEGRATION_EWK_EXTENSION_SYSTEM_DELEGATE_H_
diff --git a/tizen_src/ewk/efl_integration/ewk_privilege_checker.cc b/tizen_src/ewk/efl_integration/ewk_privilege_checker.cc
new file mode 100644 (file)
index 0000000..2db385f
--- /dev/null
@@ -0,0 +1,131 @@
+// Copyright 2016 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/efl_integration/ewk_privilege_checker.h"
+
+#if defined(OS_TIZEN)
+#include <app_manager.h>
+#include <cynara-client.h>
+#include <pkgmgr-info.h>
+#include <unistd.h>
+#endif  // defined(OS_TIZEN)
+
+#include <fstream>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+
+#if defined(OS_TIZEN)
+namespace {
+bool GetPkgApiVersion(std::string* api_version) {
+  char* app_id = nullptr;
+  char* pkgid = nullptr;
+  // api_ver memory is released by pkgmgrinfo_pkginfo_destroy_pkginfo method
+  char* api_ver = nullptr;
+  app_info_h app_handle = nullptr;
+  pkgmgrinfo_pkginfo_h pkginfo_handle = nullptr;
+
+  pid_t pid = getpid();
+  int ret = app_manager_get_app_id(pid, &app_id);
+  if (ret != APP_MANAGER_ERROR_NONE) {
+    LOG(ERROR) << "Can`t get app_id";
+    return false;
+  }
+
+  ret = app_info_create(app_id, &app_handle);
+  free(app_id);
+  if (ret != APP_MANAGER_ERROR_NONE) {
+    LOG(ERROR) << "Can`t get app_handle";
+    return false;
+  }
+
+  ret = app_info_get_package(app_handle, &pkgid);
+  app_info_destroy(app_handle);
+  if (ret != APP_MANAGER_ERROR_NONE || pkgid == nullptr) {
+    LOG(ERROR) << "Can`t get pkgid";
+    return false;
+  }
+
+  ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, getuid(), &pkginfo_handle);
+  free(pkgid);
+  if (ret != PMINFO_R_OK) {
+    LOG(ERROR) << "Can`t get pkginfo_handle";
+    return false;
+  }
+
+  ret = pkgmgrinfo_pkginfo_get_api_version(pkginfo_handle, &api_ver);
+  if (ret != PMINFO_R_OK) {
+    LOG(ERROR) << "Can`t get api_ver";
+    return false;
+  }
+
+  *api_version = api_ver;
+  pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_handle);
+  return true;
+}
+
+}  // namespace
+#endif  // defined(OS_TIZEN)
+
+namespace content {
+
+// static
+EwkPrivilegeChecker* EwkPrivilegeChecker::GetInstance() {
+  return base::Singleton<EwkPrivilegeChecker>::get();
+}
+
+bool EwkPrivilegeChecker::CheckPrivilege(const std::string& privilege_name) {
+#if defined(OS_TIZEN)
+  static constexpr char kSmackLabelFilePath[] = "/proc/self/attr/current";
+
+  int ret;
+  cynara* p_cynara = nullptr;
+  ret = cynara_initialize(&p_cynara, 0);
+  if (ret != CYNARA_API_SUCCESS) {
+    LOG(ERROR) << "Couldn`t initialize Cynara";
+    return false;
+  }
+
+  auto cynara_deleter = [](cynara* p) { cynara_finish(p); };
+  auto cynara_holder = std::unique_ptr<cynara, decltype(cynara_deleter)>{
+      p_cynara, cynara_deleter};
+
+  std::string uid = std::to_string(getuid());
+
+  // Get smack label
+  std::ifstream file(kSmackLabelFilePath);
+  if (!file.is_open()) {
+    LOG(ERROR) << "Failed to open " << kSmackLabelFilePath;
+    return false;
+  }
+
+  std::string smack_label{std::istreambuf_iterator<char>(file),
+                          std::istreambuf_iterator<char>()};
+
+  // Get widget api version, which is needed to resolve older privileges from
+  // previous platforms. Api version is set inside of config.xml in widget.
+  std::string api_version;
+  if (!GetPkgApiVersion(&api_version)) {
+    LOG(ERROR) << "Failed to acquire api version. "
+               << "Can`t resolve properly privilege mapping!";
+    return false;
+  }
+
+  ret = cynara_check(p_cynara, smack_label.c_str(), "", uid.c_str(),
+                     privilege_name.c_str());
+  if (ret != CYNARA_API_ACCESS_ALLOWED) {
+    LOG(ERROR) << "Failed to acquire mapping for privilege: "
+               << privilege_name.c_str();
+    return false;
+  }
+  return true;
+#else  // defined(OS_TIZEN)
+  ALLOW_UNUSED_LOCAL(privilege_name);
+  return false;
+#endif
+}
+}  // namespace content
diff --git a/tizen_src/ewk/efl_integration/ewk_privilege_checker.h b/tizen_src/ewk/efl_integration/ewk_privilege_checker.h
new file mode 100644 (file)
index 0000000..df10e73
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2016 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 TIZEN_SRC_EWK_EFL_INTEGRATION_EWK_PRIVILEGE_CHECKER_H_
+#define TIZEN_SRC_EWK_EFL_INTEGRATION_EWK_PRIVILEGE_CHECKER_H_
+
+#include <string>
+
+#include "base/memory/singleton.h"
+
+namespace content {
+
+/*
+ * EwkPrivilegeChecker is an implementation for resolving access for given
+ * privilege
+ */
+class EwkPrivilegeChecker {
+ public:
+  static EwkPrivilegeChecker* GetInstance();
+  bool CheckPrivilege(const std::string& privilege_name);
+
+ private:
+  EwkPrivilegeChecker() = default;
+  friend struct base::DefaultSingletonTraits<EwkPrivilegeChecker>;
+};
+
+}  // namespace content
+
+#endif  // TIZEN_SRC_EWK_EFL_INTEGRATION_EWK_PRIVILEGE_CHECKER_H_
diff --git a/tizen_src/ewk/efl_integration/private/ewk_value_private.cc b/tizen_src/ewk/efl_integration/private/ewk_value_private.cc
new file mode 100644 (file)
index 0000000..649d487
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2016 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_value_private.h"
+
+EwkValuePrivate::EwkValuePrivate() = default;
+
+EwkValuePrivate::EwkValuePrivate(bool value) : value_(new base::Value(value)) {}
+
+EwkValuePrivate::EwkValuePrivate(int value) : value_(new base::Value(value)) {}
+
+EwkValuePrivate::EwkValuePrivate(double value)
+    : value_(new base::Value(value)) {}
+
+EwkValuePrivate::EwkValuePrivate(const std::string& value)
+    : value_(new base::Value(value)) {}
+
+EwkValuePrivate::EwkValuePrivate(std::unique_ptr<base::Value> value)
+    : value_(std::move(value)) {}
+
+base::Value::Type EwkValuePrivate::GetType() const {
+  if (!value_)
+    return base::Value::Type::NONE;
+
+  return value_->type();
+}
+
+base::Value* EwkValuePrivate::GetValue() const {
+  return value_.get();
+}
+
+EwkValuePrivate::~EwkValuePrivate() = default;
diff --git a/tizen_src/ewk/efl_integration/private/ewk_value_private.h b/tizen_src/ewk/efl_integration/private/ewk_value_private.h
new file mode 100644 (file)
index 0000000..523d5d5
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2016 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_EFL_INTEGRATION_PRIVATE_EWK_VALUE_PRIVATE_H_
+#define EWK_EFL_INTEGRATION_PRIVATE_EWK_VALUE_PRIVATE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/values.h"
+
+class EwkValuePrivate : public base::RefCountedThreadSafe<EwkValuePrivate> {
+ public:
+  EwkValuePrivate();
+  explicit EwkValuePrivate(bool value);
+  explicit EwkValuePrivate(int value);
+  explicit EwkValuePrivate(double value);
+  explicit EwkValuePrivate(const std::string& value);
+  explicit EwkValuePrivate(std::unique_ptr<base::Value> value);
+
+  // disable constructor from raw pointer because of implicit conversion
+  // of pointer types to bool
+  explicit EwkValuePrivate(base::Value* value) = delete;
+
+  base::Value::Type GetType() const;
+  base::Value* GetValue() const;
+
+ private:
+  friend class base::RefCountedThreadSafe<EwkValuePrivate>;
+  ~EwkValuePrivate();
+
+  std::unique_ptr<base::Value> value_;
+};
+
+#endif  // EWK_EFL_INTEGRATION_PRIVATE_EWK_VALUE_PRIVATE_H_
index 77e6450..3df8af5 100644 (file)
@@ -50,9 +50,12 @@ using content::ContentMainDelegateEfl;
 
 #if BUILDFLAG(IS_TIZEN)
 #include <app_control.h>
-
 #include "browser/notification/notification_controller_efl.h"
 #endif
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "common/trusted_pepper_plugin_util.h"
+#include "ewk_extension_system_delegate.h"
+#endif
 
 namespace {
 ContentBrowserClientEfl* GetContentBrowserClient() {
@@ -1062,6 +1065,12 @@ void ewk_context_application_type_set(
   EINA_SAFETY_ON_NULL_RETURN(ewkContext);
   LOG(INFO) << "Set current application type: " << applicationType;
   ewkContext->SetApplicationType(applicationType);
+
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+  EwkExtensionSystemDelegate::SetEmbedderName(applicationType);
+  pepper::UpdatePluginService(applicationType);
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+
 #else
   LOG_EWK_API_MOCKUP("Only for Tizen TV");
 #endif
index 4b1b6a5..fb025b2 100644 (file)
-/*
- * Copyright (C) 2016 Samsung Electronics. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY SAMSUNG ELECTRONICS. AND ITS CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SAMSUNG ELECTRONICS. OR ITS
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "ewk_value_product.h"
-#include "private/ewk_private.h"
+// Copyright 2016 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 "public/ewk_value_product.h"
+#include "private/ewk_value_private.h"
+
+#include <memory>
+#include <sstream>
+#include <string>
+
+namespace {
+
+inline Eina_Bool Eina_FromBool(bool v) {
+  return v ? EINA_TRUE : EINA_FALSE;
+}
+
+inline bool Eina_ToBool(Eina_Bool v) {
+  return (v == EINA_FALSE) ? false : true;
+}
+
+inline const EwkValuePrivate* EwkValueCast(Ewk_Value value) {
+  return static_cast<const EwkValuePrivate*>(value);
+}
+
+}  // namespace
+
+#define EWK_VALUE_TYPE_CHECK_RETURN_VAL(value, type, retval) \
+    EINA_SAFETY_ON_FALSE_RETURN_VAL((type) == ewk_value_type_get(value), \
+                                    (retval))
 
 Ewk_Value ewk_value_ref(Ewk_Value value) {
-  LOG_EWK_API_MOCKUP();
-  return NULL;
+  EINA_SAFETY_ON_NULL_RETURN_VAL(value, NULL);
+  EwkValueCast(value)->AddRef();
+  return value;
 }
 
 void ewk_value_unref(Ewk_Value value) {
-  LOG_EWK_API_MOCKUP();
+  EINA_SAFETY_ON_NULL_RETURN(value);
+  EwkValueCast(value)->Release();
 }
 
 Ewk_Value_Type ewk_value_null_type_get() {
-  LOG_EWK_API_MOCKUP();
-  return 0;
+  return static_cast<Ewk_Value_Type>(base::Value::Type::NONE);
 }
 
 Ewk_Value_Type ewk_value_type_get(Ewk_Value value) {
-  LOG_EWK_API_MOCKUP();
-  return 0;
+  EINA_SAFETY_ON_NULL_RETURN_VAL(
+      value, static_cast<Ewk_Value_Type>(base::Value::Type::NONE));
+  return static_cast<Ewk_Value_Type>(EwkValueCast(value)->GetType());
 }
 
 Ewk_Value ewk_value_boolean_new(Eina_Bool initial_value) {
-  LOG_EWK_API_MOCKUP();
-  return NULL;
+  Ewk_Value val =
+      static_cast<Ewk_Value>(new EwkValuePrivate(Eina_ToBool(initial_value)));
+  return ewk_value_ref(val);
 }
 
 Ewk_Value_Type ewk_value_boolean_type_get() {
-  LOG_EWK_API_MOCKUP();
-  return 0;
+  return static_cast<Ewk_Value_Type>(base::Value::Type::BOOLEAN);
 }
 
 Eina_Bool ewk_value_boolean_value_get(Ewk_Value value, Eina_Bool* dst) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(value, ewk_value_boolean_type_get(),
+                                  EINA_FALSE);
+  EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
+
+  auto val = EwkValueCast(value)->GetValue()->GetIfBool();
+  *dst = Eina_FromBool(static_cast<bool>(val));
+  return EINA_TRUE;
 }
 
 Ewk_Value ewk_value_double_new(double initial_value) {
-  LOG_EWK_API_MOCKUP();
-  return NULL;
+  Ewk_Value val = static_cast<Ewk_Value>(new EwkValuePrivate(initial_value));
+  return ewk_value_ref(val);
 }
 
 Ewk_Value_Type ewk_value_double_type_get() {
-  LOG_EWK_API_MOCKUP();
-  return 0;
+  return static_cast<Ewk_Value_Type>(base::Value::Type::DOUBLE);
 }
 
 Eina_Bool ewk_value_double_value_get(Ewk_Value value, double* dst) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(value, ewk_value_double_type_get(),
+                                  EINA_FALSE);
+  EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
+  *dst = EwkValueCast(value)->GetValue()->GetDouble();
+  return EINA_TRUE;
 }
 
 Ewk_Value ewk_value_int_new(int initial_value) {
-  LOG_EWK_API_MOCKUP();
-  return NULL;
+  Ewk_Value val = static_cast<Ewk_Value>(new EwkValuePrivate(initial_value));
+  return ewk_value_ref(val);
 }
 
 Ewk_Value_Type ewk_value_int_type_get() {
-  LOG_EWK_API_MOCKUP();
-  return 0;
+  return static_cast<Ewk_Value_Type>(base::Value::Type::INTEGER);
 }
 
 Eina_Bool ewk_value_int_value_get(Ewk_Value value, int* dst) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(value, ewk_value_int_type_get(), EINA_FALSE);
+  EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
+  *dst = EwkValueCast(value)->GetValue()->GetInt();
+  return EINA_TRUE;
 }
 
 Ewk_Value ewk_value_string_new(const char* initial_value) {
-  LOG_EWK_API_MOCKUP();
-  return NULL;
+  Ewk_Value val =
+      static_cast<Ewk_Value>(new EwkValuePrivate(std::string(initial_value)));
+  return ewk_value_ref(val);
 }
 
 Ewk_Value_Type ewk_value_string_type_get() {
-  LOG_EWK_API_MOCKUP();
-  return 0;
+  return static_cast<Ewk_Value_Type>(base::Value::Type::STRING);
 }
 
 Eina_Stringshare* ewk_value_string_value_get(Ewk_Value value) {
-  LOG_EWK_API_MOCKUP();
-  return NULL;
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(value, ewk_value_string_type_get(), NULL);
+  std::string* str = EwkValueCast(value)->GetValue()->GetIfString();
+  if (str) {
+    return eina_stringshare_add(str->c_str());
+  } else {
+    return NULL;
+  }
 }
 
 Ewk_Value ewk_value_array_new() {
-  LOG_EWK_API_MOCKUP();
-  return NULL;
+  Ewk_Value val = static_cast<Ewk_Value>(
+      new EwkValuePrivate(std::unique_ptr<base::Value>(new base::ListValue())));
+  return ewk_value_ref(val);
 }
 
 Ewk_Value_Type ewk_value_array_type_get() {
-  LOG_EWK_API_MOCKUP();
-  return 0;
+  return static_cast<Ewk_Value_Type>(base::Value::Type::LIST);
 }
 
 Eina_Bool ewk_value_array_is_mutable(Ewk_Value array) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(array, ewk_value_array_type_get(),
+                                  EINA_FALSE);
+  return EINA_TRUE;
 }
 
 Eina_Bool ewk_value_array_append(Ewk_Value array, Ewk_Value value) {
-  LOG_EWK_API_MOCKUP();
-
+  EINA_SAFETY_ON_FALSE_RETURN_VAL(ewk_value_array_is_mutable(array),
+                                  EINA_FALSE);
+  base::ListValue* list;
+  bool result = EwkValueCast(array)->GetValue()->is_list();
+  if (result) {
+    // TODO(m.majczak) consider a workaround for the deep copy
+       base::ListValue* list = static_cast<base::ListValue*>(EwkValueCast(array)->GetValue());
+    list->Append(std::move(*(EwkValueCast(value)->GetValue()->CreateDeepCopy())));
+    return EINA_TRUE;
+  } else {
+    return EINA_FALSE;
+  }
 }
 
 size_t ewk_value_array_count(Ewk_Value array) {
-  LOG_EWK_API_MOCKUP();
-  return 0;
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(array, ewk_value_array_type_get(), 0);
+  base::ListValue* list;
+  bool result = EwkValueCast(array)->GetValue()->is_list();
+  if (result) {
+       list = static_cast<base::ListValue*>(EwkValueCast(array)->GetValue());
+    return list->GetList().size();
+  } else {
+    return 0;
+  }
 }
 
 Eina_Bool ewk_value_array_get(Ewk_Value array,
                               size_t position,
                               Ewk_Value* dst) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EINA_SAFETY_ON_FALSE_RETURN_VAL(position < ewk_value_array_count(array),
+                                  EINA_FALSE);
+  EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
+  base::ListValue* list;
+  bool result = EwkValueCast(array)->GetValue()->is_list();
+  if (result) {
+    // TODO(m.majczak) consider a workaround for the deep copy
+       list = static_cast<base::ListValue*>(EwkValueCast(array)->GetValue());
+    base::Value* val = nullptr;
+    val = &(list->GetList().operator[](position));
+    if (!val)
+      return EINA_FALSE;
+    Ewk_Value ret = static_cast<Ewk_Value>(
+        new EwkValuePrivate(std::unique_ptr<base::Value>(val->CreateDeepCopy())));
+    // warning!!! the ownership is passed to the caller here
+    ewk_value_ref(ret);
+    *dst = ret;
+    return EINA_TRUE;
+  } else {
+    return EINA_FALSE;
+  }
 }
 
 Eina_Bool ewk_value_array_remove(Ewk_Value array, size_t position) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EINA_SAFETY_ON_FALSE_RETURN_VAL(ewk_value_array_is_mutable(array),
+                                  EINA_FALSE);
+  EINA_SAFETY_ON_FALSE_RETURN_VAL(position < ewk_value_array_count(array),
+                                  EINA_FALSE);
+  base::Value* list;
+  bool result = EwkValueCast(array)->GetValue()->is_list();
+  if (result) {
+       list = static_cast<base::Value*>(EwkValueCast(array)->GetValue());
+    base::Value::List list_storage = std::move(*list).TakeList();
+    // warning!!! value is completely deleted here
+    list_storage.erase(list_storage.begin() + position);
+    *list = base::Value(std::move(list_storage));
+    return EINA_TRUE;
+  } else {
+    return EINA_FALSE;
+  }
 }
 
 Ewk_Value ewk_value_dictionary_new() {
-  LOG_EWK_API_MOCKUP();
-  return NULL;
+  Ewk_Value val = static_cast<Ewk_Value>(new EwkValuePrivate(
+      std::unique_ptr<base::Value>(new base::DictionaryValue())));
+  return ewk_value_ref(val);
 }
 
 Ewk_Value_Type ewk_value_dictionary_type_get() {
-  LOG_EWK_API_MOCKUP();
-  return 0;
+  return static_cast<Ewk_Value_Type>(base::Value::Type::DICTIONARY);
 }
 
 Eina_Bool ewk_value_dictionary_is_mutable(Ewk_Value dictionary) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(dictionary, ewk_value_dictionary_type_get(),
+                                  EINA_FALSE);
+  return EINA_TRUE;
 }
 
 Eina_Bool ewk_value_dictionary_keys(Ewk_Value dictionary, Ewk_Value* keys) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(dictionary, ewk_value_dictionary_type_get(),
+                                  EINA_FALSE);
+  EINA_SAFETY_ON_NULL_RETURN_VAL(keys, EINA_FALSE);
+  // warning!!! This is very expensive operation.
+  base::DictionaryValue* dict;
+  bool result = EwkValueCast(dictionary)->GetValue()->GetAsDictionary(&dict);
+  if (result) {
+    *keys = ewk_value_array_new();
+    base::detail::dict_iterator it = dict->DictItems().begin();
+    while (it!=dict->DictItems().end()) {
+          Ewk_Value str = ewk_value_string_new(it->first.c_str());
+          ewk_value_array_append(*keys, str);
+          ewk_value_unref(str);
+          it++;
+    }
+    return EINA_TRUE;
+  } else {
+    return EINA_FALSE;
+  }
 }
 
 Eina_Bool ewk_value_dictionary_set(Ewk_Value dictionary,
                                    Ewk_Value key,
                                    Ewk_Value value,
                                    Eina_Bool* new_entry) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EINA_SAFETY_ON_FALSE_RETURN_VAL(ewk_value_dictionary_is_mutable(dictionary),
+                                  EINA_FALSE);
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(key, ewk_value_string_type_get(), EINA_FALSE);
+  base::DictionaryValue* dict;
+  std::string k;
+  bool result1 = EwkValueCast(dictionary)->GetValue()->is_dict();
+  bool result2 = EwkValueCast(key)->GetValue()->is_string();
+  if (result1 && result2) {
+       dict = static_cast<base::DictionaryValue*>(EwkValueCast(dictionary)->GetValue());
+       k = *(EwkValueCast(key)->GetValue()->GetIfString());
+    // TODO(m.majczak) consider a workaround for the deep copy
+       auto val = dict->FindKey(k);
+       auto haskey = (val != nullptr)?true:false;
+    *new_entry = Eina_FromBool(!haskey);
+    dict->Set(k, EwkValueCast(value)->GetValue()->CreateDeepCopy());
+    return EINA_TRUE;
+  } else {
+    return EINA_FALSE;
+  }
 }
 
 Eina_Bool ewk_value_dictionary_add(Ewk_Value dictionary,
                                    Ewk_Value key,
                                    Ewk_Value value,
                                    Eina_Bool* new_entry) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EINA_SAFETY_ON_FALSE_RETURN_VAL(ewk_value_dictionary_is_mutable(dictionary),
+                                  EINA_FALSE);
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(key, ewk_value_string_type_get(), EINA_FALSE);
+  base::DictionaryValue* dict;
+  std::string k;
+  bool result1 = EwkValueCast(dictionary)->GetValue()->GetAsDictionary(&dict);
+  bool result2 = EwkValueCast(key)->GetValue()->is_string();
+  if (result1 && result2) {
+       k = *(EwkValueCast(key)->GetValue()->GetIfString());
+       auto val = dict->FindKey(k);
+       auto haskey = (val != nullptr)?true:false;
+    if (!haskey) {
+      *new_entry = EINA_TRUE;
+      // TODO(m.majczak) consider a workaround for the deep copy
+      dict->Set(k, EwkValueCast(value)->GetValue()->CreateDeepCopy());
+      return EINA_TRUE;
+    }
+    *new_entry = EINA_FALSE;
+    return EINA_FALSE;
+  } else {
+    return EINA_FALSE;
+  }
 }
 
 Eina_Bool ewk_value_dictionary_get(Ewk_Value dictionary,
                                    Ewk_Value key,
                                    Ewk_Value* dst) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(dictionary, ewk_value_dictionary_type_get(),
+                                  EINA_FALSE);
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(key, ewk_value_string_type_get(), EINA_FALSE);
+  EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
+  base::DictionaryValue* dict;
+  std::string k;
+  bool result1 = EwkValueCast(dictionary)->GetValue()->GetAsDictionary(&dict);
+  bool result2 = EwkValueCast(key)->GetValue()->is_string();
+  if (result1 && result2) {
+       k = *(EwkValueCast(key)->GetValue()->GetIfString());
+    base::Value* val = nullptr;
+    dict->Get(k, &val);
+    if (!val)
+      return EINA_FALSE;
+    // TODO(m.majczak) consider a workaround for the deep copy
+    Ewk_Value ret = static_cast<Ewk_Value>(
+        new EwkValuePrivate(std::unique_ptr<base::Value>(val->CreateDeepCopy())));
+    // warning!!! the ownership is passed to the caller here
+    ewk_value_ref(ret);
+    *dst = ret;
+    return EINA_TRUE;
+  } else {
+    return EINA_FALSE;
+  }
 }
 
 Eina_Bool ewk_value_dictionary_remove(Ewk_Value dictionary, Ewk_Value key) {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EINA_SAFETY_ON_FALSE_RETURN_VAL(ewk_value_dictionary_is_mutable(dictionary),
+                                  EINA_FALSE);
+  EWK_VALUE_TYPE_CHECK_RETURN_VAL(key, ewk_value_string_type_get(), EINA_FALSE);
+  base::DictionaryValue* dict;
+  std::string k;
+  bool result1 = EwkValueCast(dictionary)->GetValue()->GetAsDictionary(&dict);
+  bool result2 = EwkValueCast(key)->GetValue()->is_string();
+  if (result1 && result2) {
+       k = *(EwkValueCast(key)->GetValue()->GetIfString());
+    // warning!!! value is completely deleted here
+    return Eina_FromBool(dict->RemoveKey(k));
+  } else {
+    return EINA_FALSE;
+  }
 }
index 4bf2b5a..3f51c01 100644 (file)
@@ -1503,11 +1503,23 @@ Eina_Bool ewk_view_set_support_video_hole(Evas_Object* ewkView,
 void ewk_view_set_cursor_by_client(Evas_Object* ewkView, Eina_Bool enable) {}
 
 void ewk_view_widget_pepper_extension_callback_set(Evas_Object* ewk_view, Generic_Sync_Call_Callback cb, void* user_data) {
-  LOG_EWK_API_MOCKUP();
+#if defined(TIZEN_PEPPER_EXTENSIONS) && defined(OS_TIZEN_TV_PRODUCT)
+  EWK_VIEW_IMPL_GET_OR_RETURN(ewk_view, impl);
+  impl->SetPepperExtensionCallback(cb, user_data);
+#else
+  NOTIMPLEMENTED() << "This API is only available with TIZEN_PEPPER_EXTENSIONS"
+                   << " macro on TIZEN_TV products.";
+#endif
 }
 
 void ewk_view_widget_pepper_extension_info_set(Evas_Object* ewk_view, Ewk_Value widget_pepper_ext_info) {
-  LOG_EWK_API_MOCKUP();
+#if defined(TIZEN_PEPPER_EXTENSIONS) && defined(OS_TIZEN_TV_PRODUCT)
+  EWK_VIEW_IMPL_GET_OR_RETURN(ewk_view, impl);
+  impl->SetPepperExtensionWidgetInfo(widget_pepper_ext_info);
+#else
+  NOTIMPLEMENTED() << "This API is only available with TIZEN_PEPPER_EXTENSIONS"
+                   << " macro on TIZEN_TV products.";
+#endif
 }
 
 void ewk_view_resume_network_loading(Evas_Object* ewkView)
index e54c574..63f5639 100644 (file)
@@ -20,6 +20,7 @@
 #include "content/common/locale_efl.h"
 #include "content/common/paths_efl.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/content_plugin_info.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/renderer/common_renderer_client.h"
@@ -69,6 +70,15 @@ using autofill::PasswordAutofillAgent;
 using autofill::PasswordGenerationAgent;
 #endif
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+#include "common/trusted_pepper_plugin_info_cache.h"
+#include "common/trusted_pepper_plugin_util.h"
+#endif
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+#include "renderer/pepper/pepper_helper.h"
+#endif
+
 // Chromium-efl deliberately uses a different value than
 // default_maximum_page_scale_factor (4.0) because it has shown
 // better empirical results.
@@ -79,6 +89,32 @@ static const float maximum_legible_scale = 2.0f;
 static const float minimum_page_scale_for_mobile = 0.25f;
 static const float maximum_page_scale_for_mobile = 5.f;
 
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+namespace {
+
+bool CreateTrustedPepperPlugin(content::RenderFrame* render_frame,
+                               const blink::WebPluginParams& params,
+                               blink::WebPlugin** plugin) {
+  if (pepper::AreTrustedPepperPluginsDisabled())
+    return false;
+
+  auto cache = pepper::TrustedPepperPluginInfoCache::GetInstance();
+  content::ContentPluginInfo info;
+  if (cache->FindPlugin(params.mime_type.Utf8(), params.url, &info)) {
+    *plugin =
+        render_frame->CreatePlugin(info.ToWebPluginInfo(), params);
+
+    if (*plugin)
+      return true;
+  }
+
+  return false;
+}
+
+}  // namespace
+#endif  // defined(TIZEN_PEPPER_EXTENSIONS)
+
+/* LCOV_EXCL_START */
 ContentRendererClientEfl::ContentRendererClientEfl() {}
 
 ContentRendererClientEfl::~ContentRendererClientEfl() {}
@@ -98,6 +134,9 @@ void ContentRendererClientEfl::RenderThreadStarted() {
     LOG(INFO) << "Sync application type for render thread: " << app_type;
     content::SetApplicationType(
         static_cast<content::ApplicationType>(app_type));
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+    pepper::UpdatePluginRegistry();
+#endif
   }
 #endif
 
@@ -146,6 +185,9 @@ void ContentRendererClientEfl::RenderFrameCreated(content::RenderFrame* render_f
                       registry);
   }
 #endif
+#if (defined(TIZEN_PEPPER_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS))
+  new pepper::PepperHelper(render_frame);
+#endif
 }
 
 void ContentRendererClientEfl::WebViewCreated(
@@ -165,6 +207,10 @@ bool ContentRendererClientEfl::OverrideCreatePlugin(
     content::RenderFrame* render_frame,
     const blink::WebPluginParams& params,
     blink::WebPlugin** plugin) {
+#if defined(TIZEN_PEPPER_EXTENSIONS)
+  if (CreateTrustedPepperPlugin(render_frame, params, plugin))
+    return true;
+#endif                    // TIZEN_PEPPER_EXTENSIONS
 #if defined(EWK_BRINGUP)  // FIXME: m67 bringup
   return false;
 #else
diff --git a/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.cc b/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.cc
new file mode 100644 (file)
index 0000000..f065a12
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2016 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.
+
+// Copied from chrome/renderer/pepper with minor modifications.
+
+#include "tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.h"
+
+#include "components/nacl/common/buildflags.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "ppapi/buildflags/buildflags.h"
+#include "ppapi/host/ppapi_host.h"
+#include "renderer/pepper/pepper_shared_memory_message_filter.h"
+
+#if BUILDFLAG(ENABLE_NACL)
+#include "content/renderer/pepper/renderer_pepper_host_factory_efl.h"
+#endif
+
+namespace pepper {
+
+PepperHelper::PepperHelper(content::RenderFrame* render_frame)
+    : RenderFrameObserver(render_frame) {}
+
+PepperHelper::~PepperHelper() {}
+
+void PepperHelper::DidCreatePepperPlugin(content::RendererPpapiHost* host) {
+#if BUILDFLAG(ENABLE_NACL)
+  host->GetPpapiHost()->AddHostFactoryFilter(
+      std::make_unique<RendererPepperHostFactoryEfl>(host));
+#endif
+  host->GetPpapiHost()->AddInstanceMessageFilter(
+      std::make_unique<PepperSharedMemoryMessageFilter>(host));
+}
+}  // namespace pepper
\ No newline at end of file
diff --git a/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.h b/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.h
new file mode 100644 (file)
index 0000000..7b4cafe
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2016 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 RENDERER_PEPPER_PEPPER_HELPER_H_
+#define RENDERER_PEPPER_PEPPER_HELPER_H_
+
+#include "base/compiler_specific.h"
+#include "content/public/renderer/render_frame_observer.h"
+
+// Copied from chrome/renderer/pepper with minor modifications.
+// This class listens for Pepper creation events from the RenderFrame and
+// attaches the parts required for EFL-specific plugin support.
+namespace pepper {
+
+class PepperHelper : public content::RenderFrameObserver {
+ public:
+  explicit PepperHelper(content::RenderFrame* render_frame);
+  ~PepperHelper() override;
+
+  // RenderFrameObserver.
+  void DidCreatePepperPlugin(content::RendererPpapiHost* host) override;
+
+  void OnDestruct(){};
+};
+}  // namespace pepper
+#endif  // RENDERER_PEPPER_PEPPER_HELPER_H_
diff --git a/tizen_src/ewk/efl_integration/renderer/pepper/pepper_shared_memory_message_filter.cc b/tizen_src/ewk/efl_integration/renderer/pepper/pepper_shared_memory_message_filter.cc
new file mode 100644 (file)
index 0000000..987c2c6
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2016 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.
+
+// This file is copied from chrome/renderer/pepper/
+// TODO(a.bujalski) consider moving class from chrome/ to content/
+
+#include "renderer/pepper/pepper_shared_memory_message_filter.h"
+
+#include <memory>
+
+#include "base/memory/unsafe_shared_memory_region.h"
+#include "base/process/process_handle.h"
+#include "content/public/common/content_client.h"
+#include "content/public/renderer/pepper_plugin_instance.h"
+#include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "mojo/public/cpp/base/shared_memory_utils.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/var_tracker.h"
+
+PepperSharedMemoryMessageFilter::PepperSharedMemoryMessageFilter(
+    content::RendererPpapiHost* host)
+    : InstanceMessageFilter(host->GetPpapiHost()), host_(host) {}
+
+PepperSharedMemoryMessageFilter::~PepperSharedMemoryMessageFilter() {}
+
+bool PepperSharedMemoryMessageFilter::OnInstanceMessageReceived(
+    const IPC::Message& msg) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(PepperSharedMemoryMessageFilter, msg)
+  IPC_MESSAGE_HANDLER(PpapiHostMsg_SharedMemory_CreateSharedMemory,
+                      OnHostMsgCreateSharedMemory)
+  IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+bool PepperSharedMemoryMessageFilter::Send(IPC::Message* msg) {
+  return host_->GetPpapiHost()->Send(msg);
+}
+
+void PepperSharedMemoryMessageFilter::OnHostMsgCreateSharedMemory(
+    PP_Instance instance,
+    uint32_t size,
+    int* host_handle_id,
+    ppapi::proxy::SerializedHandle* plugin_handle) {
+  plugin_handle->set_null_shmem_region();
+  *host_handle_id = -1;
+  base::UnsafeSharedMemoryRegion shm =
+      base::UnsafeSharedMemoryRegion::Create(size);
+  if (!shm.IsValid())
+    return;
+
+  plugin_handle->set_shmem_region(
+      base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
+          host_->ShareUnsafeSharedMemoryRegionWithRemote(shm)));
+
+  *host_handle_id =
+      content::PepperPluginInstance::Get(instance)
+          ->GetVarTracker()
+          ->TrackSharedMemoryRegion(instance, std::move(shm), size);
+}
diff --git a/tizen_src/ewk/efl_integration/renderer/pepper/pepper_shared_memory_message_filter.h b/tizen_src/ewk/efl_integration/renderer/pepper/pepper_shared_memory_message_filter.h
new file mode 100644 (file)
index 0000000..c425868
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2016 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.
+
+// This file is copied from chrome/renderer/pepper/
+// TODO(a.bujalski) consider moving class from chrome/ to content/
+
+#ifndef RENDERER_PEPPER_PEPPER_SHARED_MEMORY_MESSAGE_FILTER_H_
+#define RENDERER_PEPPER_PEPPER_SHARED_MEMORY_MESSAGE_FILTER_H_
+
+#include "base/compiler_specific.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/host/instance_message_filter.h"
+
+#include <stdint.h>
+
+namespace content {
+class RendererPpapiHost;
+}
+
+namespace ppapi {
+namespace proxy {
+class SerializedHandle;
+}
+}  // namespace ppapi
+
+// Implements the backend for shared memory messages from a plugin process.
+class PepperSharedMemoryMessageFilter
+    : public ppapi::host::InstanceMessageFilter {
+ public:
+  explicit PepperSharedMemoryMessageFilter(content::RendererPpapiHost* host);
+  ~PepperSharedMemoryMessageFilter() override;
+
+  // InstanceMessageFilter:
+  bool OnInstanceMessageReceived(const IPC::Message& msg) override;
+
+  bool Send(IPC::Message* msg);
+
+ private:
+  // Message handlers.
+  void OnHostMsgCreateSharedMemory(
+      PP_Instance instance,
+      uint32_t size,
+      int* host_shm_handle_id,
+      ppapi::proxy::SerializedHandle* plugin_shm_handle);
+
+  content::RendererPpapiHost* host_;
+};
+
+#endif  // RENDERER_PEPPER_PEPPER_SHARED_MEMORY_MESSAGE_FILTER_H_
diff --git a/tizen_src/ewk/efl_integration/test/run_all_unittests.cc b/tizen_src/ewk/efl_integration/test/run_all_unittests.cc
new file mode 100644 (file)
index 0000000..7ae246d
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2016 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 "base/bind.h"
+#include "base/test/launcher/unit_test_launcher.h"
+#include "base/test/test_suite.h"
+
+int main(int argc, char** argv) {
+  base::TestSuite test_suite(argc, argv);
+
+  return base::LaunchUnitTests(
+      argc, argv,
+      base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
+}
\ No newline at end of file
index 691ef67..e19c4a4 100644 (file)
@@ -399,4 +399,16 @@ test("ewk_unittests") {
       "utc_blink_ewk_home_directory_set_func.cpp",
     ]
   }
+
+  if(tizen_pepper_extensions) {
+    sources += [
+      "utc_blink_ewk_array_value.cpp",
+      "utc_blink_ewk_boolean_value.cpp",
+      "utc_blink_ewk_dictionary_value.cpp",
+      "utc_blink_ewk_double_value.cpp",
+      "utc_blink_ewk_int_value.cpp",
+      "utc_blink_ewk_string_value.cpp",
+      "utc_blink_ewk_value_compare.h",
+    ]
+  }
 }
diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_array_value.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_array_value.cpp
new file mode 100644 (file)
index 0000000..9b4bca2
--- /dev/null
@@ -0,0 +1,163 @@
+// Copyright 2016 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 <cstring>
+
+#include "ewk_value_product.h"
+#include "utc_blink_ewk_base.h"
+#include "utc_blink_ewk_value_compare.h"
+
+class utc_blink_ewk_array_value : public utc_blink_ewk_base {};
+
+/*
+Tested structure layout:
+[ bool, int, double, string, array[bool, int, double] ]
+*/
+TEST_F(utc_blink_ewk_array_value, POS_TEST) {
+  // check type
+  Ewk_Value arr = ewk_value_array_new();
+  EXPECT_EQ(ewk_value_type_get(arr), ewk_value_array_type_get());
+  ASSERT_EQ(ewk_value_array_count(arr), 0u);
+  ASSERT_EQ(ewk_value_array_is_mutable(arr), EINA_TRUE);
+
+  // add bool
+  Ewk_Value v = ewk_value_boolean_new(EINA_TRUE);
+  ewk_value_array_append(arr, v);
+  ewk_value_unref(v);
+  ASSERT_EQ(ewk_value_array_count(arr), 1u);
+
+  // add double
+  v = ewk_value_double_new(1.23f);
+  ewk_value_array_append(arr, v);
+  ewk_value_unref(v);
+  ASSERT_EQ(ewk_value_array_count(arr), 2u);
+
+  // add int
+  v = ewk_value_int_new(123);
+  ewk_value_array_append(arr, v);
+  ewk_value_unref(v);
+  ASSERT_EQ(ewk_value_array_count(arr), 3u);
+
+  // add string
+  v = ewk_value_string_new("test_string");
+  ewk_value_array_append(arr, v);
+  ewk_value_unref(v);
+  ASSERT_EQ(ewk_value_array_count(arr), 4u);
+
+  // add another array
+  Ewk_Value arr2 = ewk_value_array_new();
+  // add bool
+  v = ewk_value_boolean_new(EINA_TRUE);
+  ewk_value_array_append(arr2, v);
+  ewk_value_unref(v);
+  ASSERT_EQ(ewk_value_array_count(arr2), 1u);
+  // add double
+  v = ewk_value_double_new(1.23f);
+  ewk_value_array_append(arr2, v);
+  ewk_value_unref(v);
+  ASSERT_EQ(ewk_value_array_count(arr2), 2u);
+  // add int
+  v = ewk_value_int_new(123);
+  ewk_value_array_append(arr2, v);
+  ewk_value_unref(v);
+  ASSERT_EQ(ewk_value_array_count(arr2), 3u);
+
+  // append te second array to array
+  ewk_value_array_append(arr, arr2);
+  ewk_value_unref(arr2);
+  ASSERT_EQ(ewk_value_array_count(arr), 5u);
+
+  // check the values
+  // bool
+  ASSERT_EQ(ewk_value_array_get(arr, 0, &v), EINA_TRUE);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_boolean_type_get());
+  Eina_Bool b;
+  ASSERT_EQ(ewk_value_boolean_value_get(v, &b), EINA_TRUE);
+  EXPECT_EQ(b, EINA_TRUE);
+  ewk_value_unref(v);
+
+  // double
+  ASSERT_EQ(ewk_value_array_get(arr, 1, &v), EINA_TRUE);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_double_type_get());
+  double d;
+  ASSERT_EQ(ewk_value_double_value_get(v, &d), EINA_TRUE);
+  EXPECT_EQ(d, 1.23f);
+  ewk_value_unref(v);
+
+  // int
+  ASSERT_EQ(ewk_value_array_get(arr, 2, &v), EINA_TRUE);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_int_type_get());
+  int i;
+  ASSERT_EQ(ewk_value_int_value_get(v, &i), EINA_TRUE);
+  EXPECT_EQ(i, 123);
+  ewk_value_unref(v);
+
+  // string
+  ASSERT_EQ(ewk_value_array_get(arr, 3, &v), EINA_TRUE);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_string_type_get());
+  Eina_Stringshare* str = ewk_value_string_value_get(v);
+  ASSERT_TRUE(str != NULL);
+  EXPECT_STREQ((const char*)str, "test_string");
+  eina_stringshare_del(str);
+  ewk_value_unref(v);
+
+  // array
+  ASSERT_EQ(ewk_value_array_get(arr, 4, &arr2), EINA_TRUE);
+  EXPECT_EQ(ewk_value_type_get(arr2), ewk_value_array_type_get());
+  // check values inside the array
+  // bool
+  ASSERT_EQ(ewk_value_array_get(arr2, 0, &v), EINA_TRUE);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_boolean_type_get());
+  ASSERT_EQ(ewk_value_boolean_value_get(v, &b), EINA_TRUE);
+  EXPECT_EQ(b, EINA_TRUE);
+  ewk_value_unref(v);
+  // double
+  ASSERT_EQ(ewk_value_array_get(arr2, 1, &v), EINA_TRUE);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_double_type_get());
+  ASSERT_EQ(ewk_value_double_value_get(v, &d), EINA_TRUE);
+  EXPECT_EQ(d, 1.23f);
+  ewk_value_unref(v);
+  // int
+  ASSERT_EQ(ewk_value_array_get(arr2, 2, &v), EINA_TRUE);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_int_type_get());
+  ASSERT_EQ(ewk_value_int_value_get(v, &i), EINA_TRUE);
+  EXPECT_EQ(i, 123);
+  ewk_value_unref(v);
+  ewk_value_unref(arr2);
+
+  // remove some values
+  // try to remove out of scope
+  EXPECT_EQ(ewk_value_array_remove(arr, 10), EINA_FALSE);
+  ASSERT_EQ(ewk_value_array_count(arr), 5u);
+
+  // remove bool
+  EXPECT_EQ(ewk_value_array_remove(arr, 0), EINA_TRUE);
+  ASSERT_EQ(ewk_value_array_count(arr), 4u);
+
+  // remove int
+  EXPECT_EQ(ewk_value_array_remove(arr, 1), EINA_TRUE);
+  ASSERT_EQ(ewk_value_array_count(arr), 3u);
+
+  // check values that are left
+  // double
+  ASSERT_EQ(ewk_value_array_get(arr, 0, &v), EINA_TRUE);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_double_type_get());
+  ASSERT_EQ(ewk_value_double_value_get(v, &d), EINA_TRUE);
+  EXPECT_EQ(d, 1.23f);
+  ewk_value_unref(v);
+
+  // string
+  ASSERT_EQ(ewk_value_array_get(arr, 1, &v), EINA_TRUE);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_string_type_get());
+  str = ewk_value_string_value_get(v);
+  ASSERT_TRUE(str != NULL);
+  EXPECT_STREQ((const char*)str, "test_string");
+  eina_stringshare_del(str);
+  ewk_value_unref(v);
+
+  // try to get value out of scope
+  EXPECT_EQ(ewk_value_array_get(arr, 3, &v), EINA_FALSE);
+
+  ewk_value_unref(arr);
+}
diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_boolean_value.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_boolean_value.cpp
new file mode 100644 (file)
index 0000000..03399f8
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2016 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 <cstring>
+
+#include "ewk_value_product.h"
+#include "utc_blink_ewk_base.h"
+
+class utc_blink_ewk_boolean_value : public utc_blink_ewk_base {};
+
+TEST_F(utc_blink_ewk_boolean_value, POS_TEST) {
+  // check type
+  Ewk_Value v = ewk_value_boolean_new(EINA_TRUE);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_boolean_type_get());
+
+  // check for true
+  Eina_Bool b;
+  ASSERT_EQ(ewk_value_boolean_value_get(v, &b), EINA_TRUE);
+  EXPECT_EQ(b, EINA_TRUE);
+  ewk_value_unref(v);
+
+  // check for false
+  v = ewk_value_boolean_new(EINA_FALSE);
+  ASSERT_EQ(ewk_value_boolean_value_get(v, &b), EINA_TRUE);
+  EXPECT_EQ(b, EINA_FALSE);
+  ewk_value_unref(v);
+}
diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_dictionary_value.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_dictionary_value.cpp
new file mode 100644 (file)
index 0000000..1c4a9ba
--- /dev/null
@@ -0,0 +1,106 @@
+// Copyright 2016 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 <cstring>
+
+#include "ewk_value_product.h"
+#include "utc_blink_ewk_base.h"
+#include "utc_blink_ewk_value_compare.h"
+
+class utc_blink_ewk_dictionary_value : public utc_blink_ewk_base {};
+
+/*
+Tested structure layout:
+- bool_key -> bool
+- int_key -> int
+- double_key -> double
+- string key -> string
+- array_key -> array [bool, int, double]
+- dict_key -> dictionary
+    - bool_key -> bool
+    - int_key -> int
+    - double_key -> double
+*/
+TEST_F(utc_blink_ewk_dictionary_value, POS_TEST) {
+  Ewk_Value dict = ewk_value_dictionary_new();
+  EXPECT_EQ(ewk_value_type_get(dict), ewk_value_dictionary_type_get());
+  ASSERT_EQ(ewk_value_dictionary_is_mutable(dict), EINA_TRUE);
+
+  // prepare test keys
+  Ewk_Value test_values[ArraySize(test_keys)];
+  test_values[BOOL_KEY] = ewk_value_boolean_new(EINA_TRUE);
+  test_values[DOUBLE_KEY] = ewk_value_double_new(1.23f);
+  test_values[INT_KEY] = ewk_value_int_new(123);
+  test_values[STRING_KEY] = ewk_value_string_new("test_string");
+  test_values[ARRAY_KEY] = ewk_value_array_new();
+  ewk_value_array_append(test_values[ARRAY_KEY], test_values[BOOL_KEY]);
+  ewk_value_array_append(test_values[ARRAY_KEY], test_values[DOUBLE_KEY]);
+  ewk_value_array_append(test_values[ARRAY_KEY], test_values[INT_KEY]);
+  test_values[DICT_KEY] = ewk_value_dictionary_new();
+
+  Eina_Bool b;
+
+  // set values in the nested dictionary
+  for (size_t i = BOOL_KEY; i < STRING_KEY; ++i) {
+    Ewk_Value k = ewk_value_string_new(test_keys[i]);
+    ASSERT_EQ(
+        ewk_value_dictionary_add(test_values[DICT_KEY], k, test_values[i], &b),
+        EINA_TRUE);
+    EXPECT_EQ(b, EINA_TRUE);
+    ewk_value_unref(k);
+  }
+
+  // set all dictionary values
+  for (size_t i = BOOL_KEY; i < KEY_COUNT; ++i) {
+    Ewk_Value k = ewk_value_string_new(test_keys[i]);
+    ASSERT_EQ(ewk_value_dictionary_add(dict, k, test_values[i], &b), EINA_TRUE);
+    EXPECT_EQ(b, EINA_TRUE);
+    ewk_value_unref(k);
+  }
+
+  // get keys array
+  Ewk_Value keys;
+  ASSERT_EQ(ewk_value_dictionary_keys(dict, &keys), EINA_TRUE);
+  ASSERT_EQ(ewk_value_type_get(keys), ewk_value_array_type_get());
+  ASSERT_EQ(ewk_value_array_is_mutable(keys), EINA_TRUE);
+  ASSERT_EQ(ewk_value_array_count(keys), ArraySize(test_keys));
+
+  for (size_t i = BOOL_KEY; i < KEY_COUNT; ++i) {
+    Ewk_Value key;
+    ASSERT_EQ(ewk_value_array_get(keys, i, &key), EINA_TRUE);
+    Eina_Stringshare* key_str = ewk_value_string_value_get(key);
+
+    // get index of the key in test data
+    size_t idx;
+    for (idx = BOOL_KEY; idx < KEY_COUNT; ++idx) {
+      if (strcmp(static_cast<const char*>(key_str), test_keys[idx]) == 0)
+        break;
+    }
+
+    Ewk_Value v;
+    ASSERT_EQ(ewk_value_dictionary_get(dict, key, &v), EINA_TRUE);
+    EXPECT_TRUE(Compare(v, test_values[idx]));
+
+    ewk_value_unref(key);
+    ewk_value_unref(v);
+    eina_stringshare_del(key_str);
+  }
+
+  // try some invalid operations
+  Ewk_Value v;
+  Ewk_Value k = ewk_value_string_new("non-existent_key");
+  EXPECT_EQ(ewk_value_dictionary_get(dict, k, &v), EINA_FALSE);
+  ewk_value_unref(k);
+
+  k = ewk_value_string_new(test_keys[INT_KEY]);
+
+  EXPECT_EQ(ewk_value_dictionary_add(dict, k, test_values[INT_KEY], &b),
+            EINA_FALSE);
+  EXPECT_EQ(b, EINA_FALSE);
+
+  EXPECT_EQ(ewk_value_dictionary_set(dict, k, test_values[INT_KEY], &b),
+            EINA_TRUE);
+  EXPECT_EQ(b, EINA_FALSE);
+  ewk_value_unref(k);
+}
diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_double_value.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_double_value.cpp
new file mode 100644 (file)
index 0000000..75a86ac
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 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 <cstring>
+
+#include "tizen_src/ewk/efl_integration/public/ewk_value_product.h"
+#include "utc_blink_ewk_base.h"
+
+class utc_blink_ewk_double_value : public utc_blink_ewk_base {};
+
+TEST_F(utc_blink_ewk_double_value, POS_TEST) {
+  // check type
+  Ewk_Value v = ewk_value_double_new(0.0);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_double_type_get());
+  ewk_value_unref(v);
+
+  // check value range
+  double d;
+  for (int i = -100; i < 100; ++i) {
+    double d2 = static_cast<double>(i) * M_PI;
+    v = ewk_value_double_new(d2);
+    ASSERT_EQ(ewk_value_double_value_get(v, &d), EINA_TRUE);
+    EXPECT_EQ(d, d2);
+    ewk_value_unref(v);
+  }
+}
diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_int_value.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_int_value.cpp
new file mode 100644 (file)
index 0000000..c4d5796
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 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 <cstring>
+
+#include "ewk_value_product.h"
+#include "utc_blink_ewk_base.h"
+
+class utc_blink_ewk_int_value : public utc_blink_ewk_base {};
+
+TEST_F(utc_blink_ewk_int_value, POS_TEST) {
+  // check type
+  Ewk_Value v = ewk_value_int_new(0);
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_int_type_get());
+  ewk_value_unref(v);
+
+  // check value range
+  int n;
+  for (int i = -100; i < 100; ++i) {
+    v = ewk_value_int_new(i);
+    ASSERT_EQ(ewk_value_int_value_get(v, &n), EINA_TRUE);
+    EXPECT_EQ(n, i);
+    ewk_value_unref(v);
+  }
+}
diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_string_value.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_string_value.cpp
new file mode 100644 (file)
index 0000000..d058537
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2016 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 <cstring>
+
+#include "ewk_value_product.h"
+#include "utc_blink_ewk_base.h"
+#include "utc_blink_ewk_value_compare.h"
+
+class utc_blink_ewk_string_value : public utc_blink_ewk_base {};
+
+TEST_F(utc_blink_ewk_string_value, POS_TEST) {
+  // check type
+  Ewk_Value v = ewk_value_string_new("");
+  EXPECT_EQ(ewk_value_type_get(v), ewk_value_string_type_get());
+  ewk_value_unref(v);
+
+  // check value range
+  for (size_t i = 0; i < ArraySize(test_strings); ++i) {
+    v = ewk_value_string_new(test_strings[i]);
+    Eina_Stringshare* str = ewk_value_string_value_get(v);
+    ASSERT_TRUE(str != NULL);
+    EXPECT_STREQ((const char*)str, test_strings[i]);
+    eina_stringshare_del(str);
+    ewk_value_unref(v);
+  }
+}
diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_value_compare.h b/tizen_src/ewk/unittest/utc_blink_ewk_value_compare.h
new file mode 100644 (file)
index 0000000..85c9571
--- /dev/null
@@ -0,0 +1,153 @@
+// Copyright 2016 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 <cstring>
+
+#include "ewk_value_product.h"
+#include "utc_blink_ewk_base.h"
+
+template <typename T, size_t N>
+size_t ArraySize(T (&)[N]) {
+  return N;
+}
+
+namespace {
+
+const char* test_strings[] = {
+    "",                                   // empty
+    "a",                                  // one char
+    "    \n\n",                           // white space string
+    "testtesttest",                       // continous text string
+    "1 2 3 4 5 6 7 8 9 0",                // digits
+    "test test test 1 2 3 4 5 6 7 8 9 0"  // mixed
+};
+
+const char* test_keys[] = {"bool_key",   "double_key", "int_key",
+                           "string_key", "array_key",  "dictionary_key"};
+
+enum TestKeysTypes {
+  BOOL_KEY,
+  DOUBLE_KEY,
+  INT_KEY,
+  STRING_KEY,
+  ARRAY_KEY,
+  DICT_KEY,
+  KEY_COUNT
+};
+
+bool CompareString(Ewk_Value v1, Ewk_Value v2);
+bool CompareArray(Ewk_Value v1, Ewk_Value v2);
+bool CompareDictionary(Ewk_Value v1, Ewk_Value v2);
+
+bool Compare(Ewk_Value v1, Ewk_Value v2) {
+  if (ewk_value_type_get(v1) != ewk_value_type_get(v2))
+    return false;
+
+  if (ewk_value_type_get(v1) == ewk_value_boolean_type_get()) {
+    Eina_Bool b1, b2;
+    ewk_value_boolean_value_get(v1, &b1);
+    ewk_value_boolean_value_get(v2, &b2);
+    return b1 == b2;
+  } else if (ewk_value_type_get(v1) == ewk_value_double_type_get()) {
+    double d1, d2;
+    ewk_value_double_value_get(v1, &d1);
+    ewk_value_double_value_get(v2, &d2);
+    return d1 == d2;
+  } else if (ewk_value_type_get(v1) == ewk_value_int_type_get()) {
+    int i1, i2;
+    ewk_value_int_value_get(v1, &i1);
+    ewk_value_int_value_get(v2, &i2);
+    return i1 == i2;
+  } else if (ewk_value_type_get(v1) == ewk_value_string_type_get()) {
+    return CompareString(v1, v2);
+  } else if (ewk_value_type_get(v1) == ewk_value_array_type_get()) {
+    return CompareArray(v1, v2);
+  } else if (ewk_value_type_get(v1) == ewk_value_dictionary_type_get()) {
+    return CompareDictionary(v1, v2);
+  } else {
+    return false;
+  }
+}
+
+bool CompareString(Ewk_Value v1, Ewk_Value v2) {
+  if (ewk_value_type_get(v1) != ewk_value_string_type_get() ||
+      ewk_value_type_get(v2) != ewk_value_string_type_get())
+    return false;
+
+  Eina_Stringshare* s1 = ewk_value_string_value_get(v1);
+  Eina_Stringshare* s2 = ewk_value_string_value_get(v2);
+  bool cmp =
+      strcmp(static_cast<const char*>(s1), static_cast<const char*>(s2)) == 0;
+  eina_stringshare_del(s1);
+  eina_stringshare_del(s2);
+  return cmp;
+}
+
+bool CompareArray(Ewk_Value v1, Ewk_Value v2) {
+  if (ewk_value_type_get(v1) != ewk_value_array_type_get() ||
+      ewk_value_type_get(v2) != ewk_value_array_type_get() ||
+      ewk_value_array_is_mutable(v1) == EINA_FALSE ||
+      ewk_value_array_is_mutable(v2) == EINA_FALSE ||
+      ewk_value_array_count(v1) != ewk_value_array_count(v2))
+    return false;
+
+  size_t count = ewk_value_array_count(v1);
+  for (size_t i = 0; i < count; ++i) {
+    Ewk_Value a1, a2;
+    if (ewk_value_array_get(v1, i, &a1) == EINA_FALSE)
+      return false;
+    if (ewk_value_array_get(v2, i, &a2) == EINA_FALSE) {
+      ewk_value_unref(a1);
+      return false;
+    }
+    bool cmp = Compare(a1, a2);
+    ewk_value_unref(a1);
+    ewk_value_unref(a2);
+    if (!cmp)
+      return false;
+  }
+  return true;
+}
+
+bool CompareDictionary(Ewk_Value v1, Ewk_Value v2) {
+  if (ewk_value_type_get(v1) != ewk_value_dictionary_type_get() ||
+      ewk_value_type_get(v2) != ewk_value_dictionary_type_get() ||
+      ewk_value_dictionary_is_mutable(v1) == EINA_FALSE ||
+      ewk_value_dictionary_is_mutable(v2) == EINA_FALSE)
+    return false;
+
+  Ewk_Value k;
+  if (ewk_value_dictionary_keys(v1, &k) == EINA_FALSE)
+    return false;
+
+  size_t count = ewk_value_array_count(k);
+  for (size_t i = 0; i < count; ++i) {
+    Ewk_Value key;
+    if (ewk_value_array_get(k, i, &key) == EINA_FALSE)
+      return false;
+
+    Ewk_Value a1, a2;
+    if (ewk_value_dictionary_get(v1, key, &a1) == EINA_FALSE) {
+      ewk_value_unref(k);
+      return false;
+    }
+    if (ewk_value_dictionary_get(v2, key, &a2) == EINA_FALSE) {
+      ewk_value_unref(k);
+      ewk_value_unref(a1);
+      return false;
+    }
+
+    bool cmp = Compare(a1, a2);
+    ewk_value_unref(a1);
+    ewk_value_unref(a2);
+    if (!cmp) {
+      ewk_value_unref(k);
+      return false;
+    }
+  }
+  ewk_value_unref(k);
+  return true;
+}
+
+}  // namespace
index 798e8e1..6c39de3 100755 (executable)
@@ -4,6 +4,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "components/visitedlink/renderer/visitedlink_reader.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/content_plugin_info.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_thread.h"
 #include "electron/shell/common/options_switches.h"
@@ -33,7 +34,7 @@
 #include "tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_util.h"
 #endif
 
-#if BUILDFLAG(ENABLE_PLUGINS) && !defined(WRT_JS_BRINGUP)
+#if BUILDFLAG(ENABLE_PLUGINS)
 #include "tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.h"
 #endif
 
@@ -190,12 +191,12 @@ bool WRTRendererClient::CreateTrustedPepperPlugin(
     return false;
 
   auto cache = pepper::TrustedPepperPluginInfoCache::GetInstance();
-  content::PepperPluginInfo info;
+  content::ContentPluginInfo info;
   std::string pkg_id = ApplicationData::GetInstance().GetPackageID();
   LOG(INFO) << "WRTRendererClient::CreateTrustedPepperPlugin, plugin cache "
                "will FindPlugin(), mime "
             << params.mime_type.Utf8();
-  if (cache->FindPlugin(params.mime_type.Utf8(), params.url, &info, pkg_id)) {
+  if (cache->FindPlugin(params.mime_type.Utf8(), params.url, &info)) {
     LOG(INFO) << "plugin found! is_out_of_process " << info.is_out_of_process
               << ", path " << info.path.value() << ", name " << info.name
               << ", permissions " << info.permissions