#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"
#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) \
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();
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)) {
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,
#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"
// 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
// |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.
// 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: