[M108 Aura Migration][NaCl][PPFWK] Upgradable pepper plugin requirement 63/290063/2
authorXiaoshu Wei <xiaoshu.wei@samsung.com>
Mon, 20 Mar 2023 01:05:00 +0000 (09:05 +0800)
committerBot Blink <blinkbot@samsung.com>
Mon, 20 Mar 2023 07:05:03 +0000 (07:05 +0000)
Migrated from tizen 7.0:
https://review.tizen.org/gerrit/#/c/280176/

Change-Id: Iaec1fb79816bfb031e855fb87272baa142e9aba5
Signed-off-by: Xiaoshu Wei <xiaoshu.wei@samsung.com>
tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_info_cache.cc
tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_info_cache.h
wrt/src/renderer/wrt_renderer_client.cc

index a184aab..b1b7db3 100644 (file)
@@ -5,12 +5,14 @@
 #include "common/trusted_pepper_plugin_info_cache.h"
 
 #include <iterator>
+#include <tzplatform_config.h>
 #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_file_value_serializer.h"
 #include "base/json/json_reader.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
@@ -21,6 +23,7 @@
 #include "content/public/common/content_plugin_info.h"
 #include "net/base/mime_util.h"
 #include "ppapi/shared_impl/ppapi_permissions.h"
+#include "tizen_src/chromium_impl/tizen/vconf_handle.h"
 #include "url/gurl.h"
 
 #define PARSING_ERROR(pmf) \
@@ -294,38 +297,42 @@ TrustedPepperPluginInfoCache::TrustedPepperPluginInfoCache(
     const std::vector<base::FilePath>& paths) {
 
   for (const auto& path : paths)
-  {
-        AddPluginsFromDirectory(path);
-  }
-
+    AddPluginsFromDirectory(path.value());
 }
 
 TrustedPepperPluginInfoCache::~TrustedPepperPluginInfoCache() {}
 
 void TrustedPepperPluginInfoCache::GetPlugins(
-    std::vector<ContentPluginInfo>* plugins) const {
+    std::vector<ContentPluginInfo>* plugins) {
+  LOG(INFO) << "GetPlugins, param vector size " << plugins->size();
+  MaybeUpdateRw();
+
   if (plugins->empty()) {
-    plugins->reserve(plugins_.size());
-    std::for_each(plugins_.cbegin(), plugins_.cend(),
-                  [plugins](const PluginEntry& element) {
-                    plugins->push_back(*(element.second));
-                  });
+    plugins->reserve(path_map_.size());
+    for (const auto& entry : path_map_)
+      plugins->push_back(entry.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));
+    for (const auto& entry : path_map_) {
+      if (!plugins_not_to_add.count(entry.second.path))
+        plugins->push_back(entry.second);
     }
   }
 }
 
-bool TrustedPepperPluginInfoCache::FindPlugin(
-    std::string mime_type,
-    const GURL& url,
-    ContentPluginInfo* found_plugin) const {
+bool TrustedPepperPluginInfoCache::FindPlugin(std::string mime_type,
+                                              const GURL& url,
+                                              ContentPluginInfo* found_plugin,
+                                              std::string pkg_id) {
+  LOG(INFO) << "FindPlugin, mime " << mime_type << ", pkg_id " << pkg_id
+            << ", url " << url.possibly_invalid_spec();
+  MaybeUpdateRw();
+
+  // The search is divided into three phases, see comments below.
+
   if (mime_type.empty()) {
     // Try to guess the MIME type based on the extension.
     auto filename = url.ExtractFileName();
@@ -339,18 +346,43 @@ bool TrustedPepperPluginInfoCache::FindPlugin(
       return false;
   }
 
-  auto it = mime_map_.find(mime_type);
-  if (it != mime_map_.cend()) {
-    *found_plugin = *(it->second);
+  // 1st. RW has the highest priority
+  auto path = mime_to_rw_map_.find(mime_type);
+  if (path != mime_to_rw_map_.end()) {  // this mime has tpk
+    std::string rwpath = path->second;
+    if (judge_map_.count(rwpath)  // this tpk is force update
+        ||
+        judge_map_.count(
+            rwpath + pkg_id)  // judge whether the tpk and app combination exists
+    ) {
+      *found_plugin = path_map_.find(rwpath)->second;
+      return true;
+    }
+  }
+
+  // 2nd. If SRO exists, use it
+  path = mime_to_sro_map_.find(mime_type);
+  if (path != mime_to_sro_map_.end()) {
+    *found_plugin = path_map_.find(path->second)->second;
     return true;
   }
 
-  return false;
+  // 3rd. At last, search in RO
+  path = mime_to_ro_map_.find(mime_type);
+  if (path == mime_to_ro_map_.end())
+    return false;
+  *found_plugin = path_map_.find(path->second)->second;
+  return true;
+}
+
+bool TrustedPepperPluginInfoCache::IsAppInPepperUpgradeList(std::string id) {
+  MaybeUpdateRw();
+  return app_map_.count(id);
 }
 
 TrustedPepperPluginInfoCache::TrustedPepperPluginInfoCache() {
   for (const auto& path : kPepperPluginsPaths)
-    AddPluginsFromDirectory(base::FilePath(path));
+    AddPluginsFromDirectory(path);
 
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kTrustedPepperPluginsSearchPaths)) {
@@ -359,38 +391,138 @@ TrustedPepperPluginInfoCache::TrustedPepperPluginInfoCache() {
     std::vector<std::string> paths = base::SplitString(
         value, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
     for (const auto& path : paths)
-      AddPluginsFromDirectory(base::FilePath(path));
+      AddPluginsFromDirectory(path);
   }
+
+  MaybeUpdateRw();
+  LOG(INFO) << "constru without param end, mime_to_ro_map_ size "
+            << mime_to_ro_map_.size() << ", mime_to_sro_map_ size "
+            << mime_to_sro_map_.size() << ", mime_to_rw_map_ size "
+            << mime_to_rw_map_.size() << ", path_map_ size " << path_map_.size()
+            << ", judge_map_ size " << judge_map_.size() << ", app_map_ size "
+            << app_map_.size();
 }
 
-void TrustedPepperPluginInfoCache::AddPluginsFromDirectory(
-    const FilePath& dir) {
-  if (!base::PathExists(dir))
+void TrustedPepperPluginInfoCache::MaybeUpdateRw() {
+  char* kJsonPath = (char*)tzplatform_mkpath(
+      TZ_SYS_RW_APP,
+      "/appbinarymanager/webapi_result/upgrade_webapi_result.json");
+
+  base::stat_wrapper_t file_stat;
+  if (base::File::Stat(kJsonPath, &file_stat) == -1) {
+    LOG(ERROR) << "file not found: " << kJsonPath;
+    return;
+  }
+  auto latest_time = base::Time::FromTimeSpec(file_stat.st_mtim);
+  if (rw_latest_time_ == latest_time) {
+    LOG(INFO) << "file same as last read: " << kJsonPath;
+    return;
+  }
+  rw_latest_time_ = latest_time;
+  LOG(INFO) << "file latest modified: " << latest_time;
+
+  FilePath tpk_info_file(kJsonPath);
+  JSONFileValueDeserializer deserializer(tpk_info_file);
+  int error_code;
+  std::string error_message;
+  std::unique_ptr<base::Value> root =
+      deserializer.Deserialize(&error_code, &error_message);
+  if (!root) {
+    LOG(ERROR) << "readJsonFile error: " << error_message
+               << ", file is: " << kJsonPath;
+    return;
+  }
+  if (!root->is_dict()) {
+    LOG(ERROR) << "readJsonFile, content is not JsonObject";
     return;
+  }
 
+  base::Value* dict = root->FindDictKey("forceupdate_webapi");
+  if (!dict) {
+    LOG(ERROR) << "readJsonFile, no obj under key forceupdate_webapi";
+    return;
+  }
+  base::Value* list = dict->FindListKey("pepper");
+  if (!list) {
+    LOG(ERROR) << "readJsonFile, no list under key pepper";
+    return;
+  }
+  for (base::Value& plugin : list->GetList()) {
+    if (!plugin.is_dict())
+      continue;
+    std::string* dir = plugin.FindStringKey("path");
+    std::string* dir_sys = plugin.FindStringKey("systempath");
+    if (dir_sys && plugin.FindBoolKey("system").value_or(false))
+      AddPluginsFromDirectory(*dir_sys, kSRO);
+    if (!dir || (dir_sys && (dir->compare(*dir_sys) == 0)))
+      // no rw installed. rw path IS sro path
+      continue;
+    bool force = plugin.FindBoolKey("forceupdate").value_or(false);
+    if (AddPluginsFromDirectory(*dir, kRW) && force)
+      judge_map_.insert({*dir, true});
+  }
+
+  dict = root->FindDictPath("upgradable_webapi_applist.pepper");
+  if (!dict) {
+    LOG(ERROR)
+        << "readJsonFile, no obj under key upgradable_webapi_applist.pepper";
+    return;
+  }
+  for (auto kv : dict->DictItems()) {
+    base::Value& tpk_list = kv.second;
+    if (!tpk_list.is_list())
+      continue;
+    for (base::Value& tpk : tpk_list.GetList()) {
+      if (!tpk.is_dict())
+        continue;
+      std::string* dir = tpk.FindStringKey("path");
+      if (!dir)
+        continue;
+      if (!judge_map_.count(*dir)) {
+        std::string combination = *dir + kv.first;
+        judge_map_.insert({combination, true});
+      }
+    }
+    app_map_.insert({kv.first, true});
+  }
+}
+
+bool TrustedPepperPluginInfoCache::AddPluginsFromDirectory(
+    const std::string& directory,
+    Goal goal) {
+  LOG(INFO) << "AddPluginsFromDirectory, " << directory << ", goal " << goal;
+  base::FilePath dir(directory);
+  if (!base::PathExists(dir))
+    return false;
+
+  bool handled = false;
   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()))
+    ContentPluginInfo info;
+    if (!FillPepperPluginInfoFromManifest(name, &info))
       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();
+    handled = true;
+    if (kRW != goal)
+      path_map_.insert({info.path.value(), info});
+    else
+      path_map_.insert({directory, info});
+
+    for (const auto& plugin_mime : info.mime_types) {
+      if (kRO == goal)
+        mime_to_ro_map_.insert({plugin_mime.mime_type, info.path.value()});
+      else if (kSRO == goal)
+        mime_to_sro_map_.insert({plugin_mime.mime_type, info.path.value()});
+      else
+        mime_to_rw_map_.insert({plugin_mime.mime_type, directory});
+      LOG(INFO) << "goal " << goal << ", handled key " << plugin_mime.mime_type
+                << ", value " << &info;
     }
-
-    plugins_.emplace_back(name, std::move(info));
   }
+  return handled;
 }
 
 bool ParsePepperPluginManifest(const FilePath& pmf,
index bdd8b98..0e51372 100644 (file)
@@ -11,8 +11,8 @@
 #include <utility>
 #include <vector>
 
-//#include "base/containers/hash_tables.h"
 #include "base/files/file_path.h"
+#include "base/time/time.h"
 #include "content/public/common/content_plugin_info.h"
 #include "url/gurl.h"
 
@@ -47,7 +47,7 @@ class TrustedPepperPluginInfoCache {
   // 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;
+  void GetPlugins(std::vector<content::ContentPluginInfo>* plugins);
 
   // Searches cached pepper plugins whether there is plugin which supports
   // given |mime_type| or |url|. If |mime_type| is empty, method tries to find
@@ -60,9 +60,16 @@ class TrustedPepperPluginInfoCache {
   // |found_plugin| must be *non-null* pointer
   bool FindPlugin(std::string mime_type,
                   const GURL& url,
-                  content::ContentPluginInfo* found_plugin) const;
+                  content::ContentPluginInfo* found_plugin,
+                  std::string pkg_id = "");
+
+  // Searches whether app is in pepper's upgradable webapi applist
+  bool IsAppInPepperUpgradeList(std::string id);
 
  private:
+  // read only, read write, system read only
+  enum Goal { kRO, kRW, kSRO };
+
   friend struct base::DefaultSingletonTraits<TrustedPepperPluginInfoCache>;
 
   // Builds plugin cache based on predefined directories.
@@ -70,16 +77,38 @@ class 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_;
+  // @return true: handled at least one plugin. false otherwise
+  bool AddPluginsFromDirectory(const std::string& directory, Goal goal = kRO);
+
+  // There is a json file which stores all rw plugins' info
+  // If the file has never been read, or it has been modified since last read by
+  // this cache, update rw info by re-reading it
+  void MaybeUpdateRw();
+
+  using PathToPluginMap =
+      std::unordered_map<std::string, content::ContentPluginInfo>;
+  using MimeToPathMap = std::unordered_map<std::string, std::string>;
+  using DummyValueMap =
+      std::unordered_map<std::string, bool>;  // bool value is not used
+
+  // These maps are filled during ctor, used when loading specific plugin
+
+  // stores all(ro and rw) path->plugin mapping
+  PathToPluginMap path_map_;
+  // stores mimetype->path mapping. ro, sro and rw separately
+  MimeToPathMap mime_to_ro_map_;
+  MimeToPathMap mime_to_rw_map_;
+  MimeToPathMap mime_to_sro_map_;
+  // stores two types of key:
+  // 1) raw path of rw
+  // 2) raw path of rw + app's package id
+  // used to determine which to use between ro and rw for a specific plugin
+  DummyValueMap judge_map_;
+  // contains all existing pkg id in all tpk's app list
+  DummyValueMap app_map_;
+
+  // when latest rw plugin is updated
+  base::Time rw_latest_time_;
 };
 
 // Exposed in header for UnitTesting:
index 6c39de3..b9d6ff9 100755 (executable)
@@ -196,7 +196,7 @@ bool WRTRendererClient::CreateTrustedPepperPlugin(
   LOG(INFO) << "WRTRendererClient::CreateTrustedPepperPlugin, plugin cache "
                "will FindPlugin(), mime "
             << params.mime_type.Utf8();
-  if (cache->FindPlugin(params.mime_type.Utf8(), params.url, &info)) {
+  if (cache->FindPlugin(params.mime_type.Utf8(), params.url, &info, pkg_id)) {
     LOG(INFO) << "plugin found! is_out_of_process " << info.is_out_of_process
               << ", path " << info.path.value() << ", name " << info.name
               << ", permissions " << info.permissions