|
|
|
@ -1,736 +0,0 @@
|
|
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
|
From: John Kleinschmidt <jkleinsc@electronjs.org>
|
|
|
|
|
Date: Tue, 18 Oct 2022 19:07:14 -0400
|
|
|
|
|
Subject: Revert "Change content::PluginList to only run on the UI thread."
|
|
|
|
|
|
|
|
|
|
https://chromium-review.googlesource.com/c/chromium/src/+/3866812 broke our PDF viewer.
|
|
|
|
|
|
|
|
|
|
We probably should figure out a better way to deal with this, but for now this will
|
|
|
|
|
unblock the roll.
|
|
|
|
|
|
|
|
|
|
diff --git a/content/browser/plugin_list.cc b/content/browser/plugin_list.cc
|
|
|
|
|
index f6a5b2c2a19fe7094d62d02763276af70950a621..483163f94335fc65d7c46230f7b3839c7ab95f33 100644
|
|
|
|
|
--- a/content/browser/plugin_list.cc
|
|
|
|
|
+++ b/content/browser/plugin_list.cc
|
|
|
|
|
@@ -16,7 +16,6 @@
|
|
|
|
|
#include "base/strings/sys_string_conversions.h"
|
|
|
|
|
#include "base/strings/utf_string_conversions.h"
|
|
|
|
|
#include "build/build_config.h"
|
|
|
|
|
-#include "content/public/browser/browser_thread.h"
|
|
|
|
|
#include "content/public/common/content_switches.h"
|
|
|
|
|
#include "net/base/mime_util.h"
|
|
|
|
|
#include "url/gurl.h"
|
|
|
|
|
@@ -68,18 +67,17 @@ bool SupportsExtension(const WebPluginInfo& plugin,
|
|
|
|
|
|
|
|
|
|
// static
|
|
|
|
|
PluginList* PluginList::Singleton() {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
return g_singleton.Pointer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginList::RefreshPlugins() {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
loading_state_ = LOADING_STATE_NEEDS_REFRESH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginList::RegisterInternalPlugin(const WebPluginInfo& info,
|
|
|
|
|
bool add_at_beginning) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
|
|
|
|
|
internal_plugins_.push_back(info);
|
|
|
|
|
if (add_at_beginning) {
|
|
|
|
|
@@ -92,8 +90,7 @@ void PluginList::RegisterInternalPlugin(const WebPluginInfo& info,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginList::UnregisterInternalPlugin(const base::FilePath& path) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
bool found = false;
|
|
|
|
|
for (size_t i = 0; i < internal_plugins_.size(); i++) {
|
|
|
|
|
if (internal_plugins_[i].path == path) {
|
|
|
|
|
@@ -103,12 +100,12 @@ void PluginList::UnregisterInternalPlugin(const base::FilePath& path) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DCHECK(found);
|
|
|
|
|
- RemoveExtraPluginPath(path);
|
|
|
|
|
+ RemoveExtraPluginPathLocked(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginList::GetInternalPlugins(
|
|
|
|
|
std::vector<WebPluginInfo>* internal_plugins) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
|
|
|
|
|
for (const auto& plugin : internal_plugins_)
|
|
|
|
|
internal_plugins->push_back(plugin);
|
|
|
|
|
@@ -116,8 +113,7 @@ void PluginList::GetInternalPlugins(
|
|
|
|
|
|
|
|
|
|
bool PluginList::ReadPluginInfo(const base::FilePath& filename,
|
|
|
|
|
WebPluginInfo* info) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
for (const auto& plugin : internal_plugins_) {
|
|
|
|
|
if (filename == plugin.path) {
|
|
|
|
|
*info = plugin;
|
|
|
|
|
@@ -127,13 +123,10 @@ bool PluginList::ReadPluginInfo(const base::FilePath& filename,
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-PluginList::PluginList() {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-}
|
|
|
|
|
+PluginList::PluginList() = default;
|
|
|
|
|
|
|
|
|
|
bool PluginList::PrepareForPluginLoading() {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
if (loading_state_ == LOADING_STATE_UP_TO_DATE)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
@@ -142,12 +135,18 @@ bool PluginList::PrepareForPluginLoading() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginList::LoadPlugins() {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
if (!PrepareForPluginLoading())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
std::vector<WebPluginInfo> new_plugins;
|
|
|
|
|
+ base::OnceClosure will_load_callback;
|
|
|
|
|
+ {
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
+ will_load_callback = will_load_plugins_callback_;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (will_load_callback)
|
|
|
|
|
+ std::move(will_load_callback).Run();
|
|
|
|
|
+
|
|
|
|
|
std::vector<base::FilePath> plugin_paths;
|
|
|
|
|
GetPluginPathsToLoad(&plugin_paths);
|
|
|
|
|
|
|
|
|
|
@@ -162,8 +161,6 @@ void PluginList::LoadPlugins() {
|
|
|
|
|
bool PluginList::LoadPluginIntoPluginList(const base::FilePath& path,
|
|
|
|
|
std::vector<WebPluginInfo>* plugins,
|
|
|
|
|
WebPluginInfo* plugin_info) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
if (!ReadPluginInfo(path, plugin_info))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
@@ -181,9 +178,15 @@ bool PluginList::LoadPluginIntoPluginList(const base::FilePath& path,
|
|
|
|
|
|
|
|
|
|
void PluginList::GetPluginPathsToLoad(
|
|
|
|
|
std::vector<base::FilePath>* plugin_paths) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
+ // Don't want to hold the lock while loading new plugins, so we don't block
|
|
|
|
|
+ // other methods if they're called on other threads.
|
|
|
|
|
+ std::vector<base::FilePath> extra_plugin_paths;
|
|
|
|
|
+ {
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
+ extra_plugin_paths = extra_plugin_paths_;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
- for (const base::FilePath& path : extra_plugin_paths_) {
|
|
|
|
|
+ for (const base::FilePath& path : extra_plugin_paths) {
|
|
|
|
|
if (base::Contains(*plugin_paths, path))
|
|
|
|
|
continue;
|
|
|
|
|
plugin_paths->push_back(path);
|
|
|
|
|
@@ -191,7 +194,7 @@ void PluginList::GetPluginPathsToLoad(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginList::SetPlugins(const std::vector<WebPluginInfo>& plugins) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
|
|
|
|
|
// If we haven't been invalidated in the mean time, mark the plugin list as
|
|
|
|
|
// up to date.
|
|
|
|
|
@@ -201,14 +204,20 @@ void PluginList::SetPlugins(const std::vector<WebPluginInfo>& plugins) {
|
|
|
|
|
plugins_list_ = plugins;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+void PluginList::set_will_load_plugins_callback(
|
|
|
|
|
+ const base::RepeatingClosure& callback) {
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
+ will_load_plugins_callback_ = callback;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
LoadPlugins();
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PluginList::GetPluginsNoRefresh(std::vector<WebPluginInfo>* plugins) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
|
|
|
|
|
|
|
|
|
|
return loading_state_ == LOADING_STATE_UP_TO_DATE;
|
|
|
|
|
@@ -220,10 +229,10 @@ bool PluginList::GetPluginInfoArray(
|
|
|
|
|
bool allow_wildcard,
|
|
|
|
|
std::vector<WebPluginInfo>* info,
|
|
|
|
|
std::vector<std::string>* actual_mime_types) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
DCHECK(mime_type == base::ToLowerASCII(mime_type));
|
|
|
|
|
DCHECK(info);
|
|
|
|
|
|
|
|
|
|
+ base::AutoLock lock(lock_);
|
|
|
|
|
bool is_stale = loading_state_ != LOADING_STATE_UP_TO_DATE;
|
|
|
|
|
info->clear();
|
|
|
|
|
if (actual_mime_types)
|
|
|
|
|
@@ -270,8 +279,9 @@ bool PluginList::GetPluginInfoArray(
|
|
|
|
|
return is_stale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-void PluginList::RemoveExtraPluginPath(const base::FilePath& plugin_path) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
+void PluginList::RemoveExtraPluginPathLocked(
|
|
|
|
|
+ const base::FilePath& plugin_path) {
|
|
|
|
|
+ lock_.AssertAcquired();
|
|
|
|
|
std::vector<base::FilePath>::iterator it =
|
|
|
|
|
base::ranges::find(extra_plugin_paths_, plugin_path);
|
|
|
|
|
if (it != extra_plugin_paths_.end())
|
|
|
|
|
diff --git a/content/browser/plugin_list.h b/content/browser/plugin_list.h
|
|
|
|
|
index 0b0a8600acfa1884f499cd2de5c0c149c68fefb9..0949b863b7e35511a9ef679d18ed410c4222434d 100644
|
|
|
|
|
--- a/content/browser/plugin_list.h
|
|
|
|
|
+++ b/content/browser/plugin_list.h
|
|
|
|
|
@@ -10,8 +10,11 @@
|
|
|
|
|
#include <utility>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
+#include "base/callback.h"
|
|
|
|
|
#include "base/files/file_path.h"
|
|
|
|
|
#include "base/lazy_instance.h"
|
|
|
|
|
+#include "base/synchronization/lock.h"
|
|
|
|
|
+#include "base/thread_annotations.h"
|
|
|
|
|
#include "build/build_config.h"
|
|
|
|
|
#include "content/common/content_export.h"
|
|
|
|
|
#include "content/public/common/webplugininfo.h"
|
|
|
|
|
@@ -25,8 +28,14 @@ class GURL;
|
|
|
|
|
|
|
|
|
|
namespace content {
|
|
|
|
|
|
|
|
|
|
-// Manages the list of plugins. At this point, there are no external plugins.
|
|
|
|
|
-// This object lives on the UI thread.
|
|
|
|
|
+// The PluginList is responsible for loading our NPAPI based plugins. It does
|
|
|
|
|
+// so in whatever manner is appropriate for the platform. On Windows, it loads
|
|
|
|
|
+// plugins from a known directory by looking for DLLs which start with "NP",
|
|
|
|
|
+// and checking to see if they are valid NPAPI libraries. On the Mac, it walks
|
|
|
|
|
+// the machine-wide and user plugin directories and loads anything that has
|
|
|
|
|
+// the correct types. On Linux, it walks the plugin directories as well
|
|
|
|
|
+// (e.g. /usr/lib/browser-plugins/).
|
|
|
|
|
+// This object is thread safe.
|
|
|
|
|
class CONTENT_EXPORT PluginList {
|
|
|
|
|
public:
|
|
|
|
|
// Gets the one instance of the PluginList.
|
|
|
|
|
@@ -77,6 +86,8 @@ class CONTENT_EXPORT PluginList {
|
|
|
|
|
std::vector<WebPluginInfo>* info,
|
|
|
|
|
std::vector<std::string>* actual_mime_types);
|
|
|
|
|
|
|
|
|
|
+ void set_will_load_plugins_callback(const base::RepeatingClosure& callback);
|
|
|
|
|
+
|
|
|
|
|
private:
|
|
|
|
|
enum LoadingState {
|
|
|
|
|
LOADING_STATE_NEEDS_REFRESH,
|
|
|
|
|
@@ -109,8 +120,10 @@ class CONTENT_EXPORT PluginList {
|
|
|
|
|
// Load all plugins from the default plugins directory.
|
|
|
|
|
void LoadPlugins();
|
|
|
|
|
|
|
|
|
|
- // Removes |plugin_path| from the list of extra plugin paths.
|
|
|
|
|
- void RemoveExtraPluginPath(const base::FilePath& plugin_path);
|
|
|
|
|
+ // Removes |plugin_path| from the list of extra plugin paths. Should only be
|
|
|
|
|
+ // called while holding |lock_|.
|
|
|
|
|
+ void RemoveExtraPluginPathLocked(const base::FilePath& plugin_path)
|
|
|
|
|
+ EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
|
|
|
|
|
|
|
|
|
// Creates a WebPluginInfo structure given a plugin's path. On success
|
|
|
|
|
// returns true, with the information being put into "info".
|
|
|
|
|
@@ -130,16 +143,23 @@ class CONTENT_EXPORT PluginList {
|
|
|
|
|
// States whether we will load the plugin list the next time we try to access
|
|
|
|
|
// it, whether we are currently in the process of loading it, or whether we
|
|
|
|
|
// consider it up to date.
|
|
|
|
|
- LoadingState loading_state_ = LOADING_STATE_NEEDS_REFRESH;
|
|
|
|
|
+ LoadingState loading_state_ GUARDED_BY(lock_) = LOADING_STATE_NEEDS_REFRESH;
|
|
|
|
|
|
|
|
|
|
// Extra plugin paths that we want to search when loading.
|
|
|
|
|
- std::vector<base::FilePath> extra_plugin_paths_;
|
|
|
|
|
+ std::vector<base::FilePath> extra_plugin_paths_ GUARDED_BY(lock_);
|
|
|
|
|
|
|
|
|
|
// Holds information about internal plugins.
|
|
|
|
|
- std::vector<WebPluginInfo> internal_plugins_;
|
|
|
|
|
+ std::vector<WebPluginInfo> internal_plugins_ GUARDED_BY(lock_);
|
|
|
|
|
|
|
|
|
|
// A list holding all plugins.
|
|
|
|
|
- std::vector<WebPluginInfo> plugins_list_;
|
|
|
|
|
+ std::vector<WebPluginInfo> plugins_list_ GUARDED_BY(lock_);
|
|
|
|
|
+
|
|
|
|
|
+ // Callback that is invoked whenever the PluginList will reload the plugins.
|
|
|
|
|
+ base::RepeatingClosure will_load_plugins_callback_ GUARDED_BY(lock_);
|
|
|
|
|
+
|
|
|
|
|
+ // Need synchronization for the above members since this object can be
|
|
|
|
|
+ // accessed on multiple threads.
|
|
|
|
|
+ base::Lock lock_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace content
|
|
|
|
|
diff --git a/content/browser/plugin_list_unittest.cc b/content/browser/plugin_list_unittest.cc
|
|
|
|
|
index 7cda980e4272dec80b0db5571f7fefb0ea3355ea..7f319488496786d605c6fda210492f587f7e6e14 100644
|
|
|
|
|
--- a/content/browser/plugin_list_unittest.cc
|
|
|
|
|
+++ b/content/browser/plugin_list_unittest.cc
|
|
|
|
|
@@ -6,8 +6,7 @@
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
-#include "base/files/file_path.h"
|
|
|
|
|
-#include "content/public/test/browser_task_environment.h"
|
|
|
|
|
+#include "base/strings/utf_string_conversions.h"
|
|
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
|
#include "url/gurl.h"
|
|
|
|
|
|
|
|
|
|
@@ -17,8 +16,9 @@ namespace {
|
|
|
|
|
|
|
|
|
|
base::FilePath::CharType kFooPath[] = FILE_PATH_LITERAL("/plugins/foo.plugin");
|
|
|
|
|
base::FilePath::CharType kBarPath[] = FILE_PATH_LITERAL("/plugins/bar.plugin");
|
|
|
|
|
-const char kFooMimeType[] = "application/x-foo-mime-type";
|
|
|
|
|
-const char kFooFileType[] = "foo";
|
|
|
|
|
+const char* kFooName = "Foo Plugin";
|
|
|
|
|
+const char* kFooMimeType = "application/x-foo-mime-type";
|
|
|
|
|
+const char* kFooFileType = "foo";
|
|
|
|
|
|
|
|
|
|
bool Equals(const WebPluginInfo& a, const WebPluginInfo& b) {
|
|
|
|
|
return (a.name == b.name && a.path == b.path && a.version == b.version &&
|
|
|
|
|
@@ -40,7 +40,7 @@ bool Contains(const std::vector<WebPluginInfo>& list,
|
|
|
|
|
class PluginListTest : public testing::Test {
|
|
|
|
|
public:
|
|
|
|
|
PluginListTest()
|
|
|
|
|
- : foo_plugin_(u"Foo PluginListTest",
|
|
|
|
|
+ : foo_plugin_(base::ASCIIToUTF16(kFooName),
|
|
|
|
|
base::FilePath(kFooPath),
|
|
|
|
|
u"1.2.3",
|
|
|
|
|
u"foo"),
|
|
|
|
|
@@ -48,33 +48,21 @@ class PluginListTest : public testing::Test {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetUp() override {
|
|
|
|
|
- // Cannot use std::unique_ptr due to private ctor.
|
|
|
|
|
- plugin_list_ = new PluginList();
|
|
|
|
|
- plugin_list_->RegisterInternalPlugin(bar_plugin_, false);
|
|
|
|
|
+ plugin_list_.RegisterInternalPlugin(bar_plugin_, false);
|
|
|
|
|
foo_plugin_.mime_types.emplace_back(kFooMimeType, kFooFileType,
|
|
|
|
|
std::string());
|
|
|
|
|
- plugin_list_->RegisterInternalPlugin(foo_plugin_, false);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void TearDown() override {
|
|
|
|
|
- // Cannot use std::unique_ptr due to private dtor.
|
|
|
|
|
- delete plugin_list_;
|
|
|
|
|
+ plugin_list_.RegisterInternalPlugin(foo_plugin_, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
- // Must be first.
|
|
|
|
|
- BrowserTaskEnvironment task_environment_;
|
|
|
|
|
-
|
|
|
|
|
- // Owns the PluginList but cannot be a std::unique_ptr due to private
|
|
|
|
|
- // ctor/dtor.
|
|
|
|
|
- PluginList* plugin_list_;
|
|
|
|
|
+ PluginList plugin_list_;
|
|
|
|
|
WebPluginInfo foo_plugin_;
|
|
|
|
|
WebPluginInfo bar_plugin_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TEST_F(PluginListTest, GetPlugins) {
|
|
|
|
|
std::vector<WebPluginInfo> plugins;
|
|
|
|
|
- plugin_list_->GetPlugins(&plugins);
|
|
|
|
|
+ plugin_list_.GetPlugins(&plugins);
|
|
|
|
|
EXPECT_EQ(2u, plugins.size());
|
|
|
|
|
EXPECT_TRUE(Contains(plugins, foo_plugin_));
|
|
|
|
|
EXPECT_TRUE(Contains(plugins, bar_plugin_));
|
|
|
|
|
@@ -85,11 +73,11 @@ TEST_F(PluginListTest, BadPluginDescription) {
|
|
|
|
|
std::u16string(), base::FilePath(FILE_PATH_LITERAL("/myplugin.3.0.43")),
|
|
|
|
|
std::u16string(), std::u16string());
|
|
|
|
|
// Simulate loading of the plugins.
|
|
|
|
|
- plugin_list_->RegisterInternalPlugin(plugin_3043, false);
|
|
|
|
|
+ plugin_list_.RegisterInternalPlugin(plugin_3043, false);
|
|
|
|
|
// Now we should have them in the state we specified above.
|
|
|
|
|
- plugin_list_->RefreshPlugins();
|
|
|
|
|
+ plugin_list_.RefreshPlugins();
|
|
|
|
|
std::vector<WebPluginInfo> plugins;
|
|
|
|
|
- plugin_list_->GetPlugins(&plugins);
|
|
|
|
|
+ plugin_list_.GetPlugins(&plugins);
|
|
|
|
|
ASSERT_TRUE(Contains(plugins, plugin_3043));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -101,7 +89,7 @@ TEST_F(PluginListTest, GetPluginInfoArray) {
|
|
|
|
|
bool is_stale;
|
|
|
|
|
|
|
|
|
|
// The PluginList starts out in a stale state.
|
|
|
|
|
- is_stale = plugin_list_->GetPluginInfoArray(
|
|
|
|
|
+ is_stale = plugin_list_.GetPluginInfoArray(
|
|
|
|
|
target_url, "application/octet-stream",
|
|
|
|
|
/*allow_wildcard=*/false, &plugins, &actual_mime_types);
|
|
|
|
|
EXPECT_TRUE(is_stale);
|
|
|
|
|
@@ -109,13 +97,13 @@ TEST_F(PluginListTest, GetPluginInfoArray) {
|
|
|
|
|
EXPECT_EQ(0u, actual_mime_types.size());
|
|
|
|
|
|
|
|
|
|
// Refresh it.
|
|
|
|
|
- plugin_list_->GetPlugins(&plugins);
|
|
|
|
|
+ plugin_list_.GetPlugins(&plugins);
|
|
|
|
|
plugins.clear();
|
|
|
|
|
|
|
|
|
|
// The file type of the URL is supported by |foo_plugin_|. However,
|
|
|
|
|
// GetPluginInfoArray should not match |foo_plugin_| because the MIME type is
|
|
|
|
|
// application/octet-stream.
|
|
|
|
|
- is_stale = plugin_list_->GetPluginInfoArray(
|
|
|
|
|
+ is_stale = plugin_list_.GetPluginInfoArray(
|
|
|
|
|
target_url, "application/octet-stream",
|
|
|
|
|
/*allow_wildcard=*/false, &plugins, &actual_mime_types);
|
|
|
|
|
EXPECT_FALSE(is_stale);
|
|
|
|
|
@@ -125,9 +113,9 @@ TEST_F(PluginListTest, GetPluginInfoArray) {
|
|
|
|
|
// |foo_plugin_| matches due to the MIME type.
|
|
|
|
|
plugins.clear();
|
|
|
|
|
actual_mime_types.clear();
|
|
|
|
|
- is_stale = plugin_list_->GetPluginInfoArray(target_url, kFooMimeType,
|
|
|
|
|
- /*allow_wildcard=*/false,
|
|
|
|
|
- &plugins, &actual_mime_types);
|
|
|
|
|
+ is_stale = plugin_list_.GetPluginInfoArray(target_url, kFooMimeType,
|
|
|
|
|
+ /*allow_wildcard=*/false, &plugins,
|
|
|
|
|
+ &actual_mime_types);
|
|
|
|
|
EXPECT_FALSE(is_stale);
|
|
|
|
|
EXPECT_EQ(1u, plugins.size());
|
|
|
|
|
EXPECT_TRUE(Contains(plugins, foo_plugin_));
|
|
|
|
|
@@ -137,9 +125,9 @@ TEST_F(PluginListTest, GetPluginInfoArray) {
|
|
|
|
|
// |foo_plugin_| matches due to the file type and empty MIME type.
|
|
|
|
|
plugins.clear();
|
|
|
|
|
actual_mime_types.clear();
|
|
|
|
|
- is_stale = plugin_list_->GetPluginInfoArray(target_url, "",
|
|
|
|
|
- /*allow_wildcard=*/false,
|
|
|
|
|
- &plugins, &actual_mime_types);
|
|
|
|
|
+ is_stale = plugin_list_.GetPluginInfoArray(target_url, "",
|
|
|
|
|
+ /*allow_wildcard=*/false, &plugins,
|
|
|
|
|
+ &actual_mime_types);
|
|
|
|
|
EXPECT_FALSE(is_stale);
|
|
|
|
|
EXPECT_EQ(1u, plugins.size());
|
|
|
|
|
EXPECT_TRUE(Contains(plugins, foo_plugin_));
|
|
|
|
|
diff --git a/content/browser/plugin_service_impl.cc b/content/browser/plugin_service_impl.cc
|
|
|
|
|
index ab3e8c87dc84bcf1284d65b61a4a2f0338c24903..59e73c99c499d312dd6d31ad2f067f364a7909cd 100644
|
|
|
|
|
--- a/content/browser/plugin_service_impl.cc
|
|
|
|
|
+++ b/content/browser/plugin_service_impl.cc
|
|
|
|
|
@@ -19,7 +19,6 @@
|
|
|
|
|
#include "base/strings/string_util.h"
|
|
|
|
|
#include "base/strings/utf_string_conversions.h"
|
|
|
|
|
#include "base/synchronization/waitable_event.h"
|
|
|
|
|
-#include "base/task/sequenced_task_runner.h"
|
|
|
|
|
#include "base/task/task_runner_util.h"
|
|
|
|
|
#include "base/task/thread_pool.h"
|
|
|
|
|
#include "base/threading/thread.h"
|
|
|
|
|
@@ -55,6 +54,18 @@ namespace content {
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
+std::vector<WebPluginInfo> GetPluginsHelper() {
|
|
|
|
|
+ std::vector<WebPluginInfo> plugins;
|
|
|
|
|
+ PluginList::Singleton()->GetPlugins(&plugins);
|
|
|
|
|
+ return plugins;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Callback set on the PluginList to assert that plugin loading happens on the
|
|
|
|
|
+// correct thread.
|
|
|
|
|
+void WillLoadPluginsCallback(base::SequenceChecker* sequence_checker) {
|
|
|
|
|
+ DCHECK(sequence_checker->CalledOnValidSequence());
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
#if BUILDFLAG(ENABLE_PPAPI)
|
|
|
|
|
int CountPpapiPluginProcessesForProfile(
|
|
|
|
|
const base::FilePath& plugin_path,
|
|
|
|
|
@@ -79,8 +90,6 @@ PluginService* PluginService::GetInstance() {
|
|
|
|
|
|
|
|
|
|
void PluginService::PurgePluginListCache(BrowserContext* browser_context,
|
|
|
|
|
bool reload_pages) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
|
|
|
|
|
!it.IsAtEnd(); it.Advance()) {
|
|
|
|
|
RenderProcessHost* host = it.GetCurrentValue();
|
|
|
|
|
@@ -99,7 +108,14 @@ PluginServiceImpl::PluginServiceImpl() = default;
|
|
|
|
|
PluginServiceImpl::~PluginServiceImpl() = default;
|
|
|
|
|
|
|
|
|
|
void PluginServiceImpl::Init() {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
+ plugin_list_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
|
|
|
|
|
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
|
|
|
|
|
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
|
|
|
|
|
+
|
|
|
|
|
+ // Setup the sequence checker right after setting up the task runner.
|
|
|
|
|
+ plugin_list_sequence_checker_.DetachFromSequence();
|
|
|
|
|
+ PluginList::Singleton()->set_will_load_plugins_callback(base::BindRepeating(
|
|
|
|
|
+ &WillLoadPluginsCallback, &plugin_list_sequence_checker_));
|
|
|
|
|
|
|
|
|
|
RegisterPlugins();
|
|
|
|
|
}
|
|
|
|
|
@@ -109,8 +125,6 @@ PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
|
|
|
|
|
const base::FilePath& plugin_path,
|
|
|
|
|
const base::FilePath& profile_data_directory,
|
|
|
|
|
const absl::optional<url::Origin>& origin_lock) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) {
|
|
|
|
|
if (iter->plugin_path() == plugin_path &&
|
|
|
|
|
iter->profile_data_directory() == profile_data_directory &&
|
|
|
|
|
@@ -170,8 +184,6 @@ void PluginServiceImpl::OpenChannelToPpapiPlugin(
|
|
|
|
|
const base::FilePath& profile_data_directory,
|
|
|
|
|
const absl::optional<url::Origin>& origin_lock,
|
|
|
|
|
PpapiPluginProcessHost::PluginClient* client) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
|
|
|
|
|
render_process_id, plugin_path, profile_data_directory, origin_lock);
|
|
|
|
|
if (plugin_host) {
|
|
|
|
|
@@ -189,8 +201,6 @@ bool PluginServiceImpl::GetPluginInfoArray(
|
|
|
|
|
bool allow_wildcard,
|
|
|
|
|
std::vector<WebPluginInfo>* plugins,
|
|
|
|
|
std::vector<std::string>* actual_mime_types) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
return PluginList::Singleton()->GetPluginInfoArray(
|
|
|
|
|
url, mime_type, allow_wildcard, plugins, actual_mime_types);
|
|
|
|
|
}
|
|
|
|
|
@@ -224,8 +234,6 @@ bool PluginServiceImpl::GetPluginInfo(content::BrowserContext* browser_context,
|
|
|
|
|
|
|
|
|
|
bool PluginServiceImpl::GetPluginInfoByPath(const base::FilePath& plugin_path,
|
|
|
|
|
WebPluginInfo* info) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
std::vector<WebPluginInfo> plugins;
|
|
|
|
|
PluginList::Singleton()->GetPluginsNoRefresh(&plugins);
|
|
|
|
|
|
|
|
|
|
@@ -241,8 +249,6 @@ bool PluginServiceImpl::GetPluginInfoByPath(const base::FilePath& plugin_path,
|
|
|
|
|
|
|
|
|
|
std::u16string PluginServiceImpl::GetPluginDisplayNameByPath(
|
|
|
|
|
const base::FilePath& path) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
std::u16string plugin_name = path.LossyDisplayName();
|
|
|
|
|
WebPluginInfo info;
|
|
|
|
|
if (PluginService::GetInstance()->GetPluginInfoByPath(path, &info) &&
|
|
|
|
|
@@ -260,23 +266,16 @@ std::u16string PluginServiceImpl::GetPluginDisplayNameByPath(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginServiceImpl::GetPlugins(GetPluginsCallback callback) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
- // Run `callback` later, to stay compatible with prior behavior.
|
|
|
|
|
- base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
|
|
|
|
|
- FROM_HERE, base::BindOnce(std::move(callback), GetPluginsSynchronous()));
|
|
|
|
|
+ base::PostTaskAndReplyWithResult(plugin_list_task_runner_.get(), FROM_HERE,
|
|
|
|
|
+ base::BindOnce(&GetPluginsHelper),
|
|
|
|
|
+ std::move(callback));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<WebPluginInfo> PluginServiceImpl::GetPluginsSynchronous() {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
- std::vector<WebPluginInfo> plugins;
|
|
|
|
|
- PluginList::Singleton()->GetPlugins(&plugins);
|
|
|
|
|
- return plugins;
|
|
|
|
|
+ return GetPluginsHelper();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginServiceImpl::RegisterPlugins() {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
#if BUILDFLAG(ENABLE_PPAPI)
|
|
|
|
|
ComputePepperPluginList(&plugins_);
|
|
|
|
|
#else
|
|
|
|
|
@@ -289,8 +288,6 @@ void PluginServiceImpl::RegisterPlugins() {
|
|
|
|
|
// There should generally be very few plugins so a brute-force search is fine.
|
|
|
|
|
const ContentPluginInfo* PluginServiceImpl::GetRegisteredPluginInfo(
|
|
|
|
|
const base::FilePath& plugin_path) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
-
|
|
|
|
|
for (auto& plugin : plugins_) {
|
|
|
|
|
if (plugin.path == plugin_path)
|
|
|
|
|
return &plugin;
|
|
|
|
|
@@ -316,12 +313,10 @@ const ContentPluginInfo* PluginServiceImpl::GetRegisteredPluginInfo(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginServiceImpl::SetFilter(PluginServiceFilter* filter) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
filter_ = filter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PluginServiceFilter* PluginServiceImpl::GetFilter() {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
return filter_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -357,32 +352,27 @@ bool PluginServiceImpl::IsPluginUnstable(const base::FilePath& path) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginServiceImpl::RefreshPlugins() {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
PluginList::Singleton()->RefreshPlugins();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginServiceImpl::RegisterInternalPlugin(
|
|
|
|
|
const WebPluginInfo& info,
|
|
|
|
|
bool add_at_beginning) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
PluginList::Singleton()->RegisterInternalPlugin(info, add_at_beginning);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginServiceImpl::UnregisterInternalPlugin(const base::FilePath& path) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
PluginList::Singleton()->UnregisterInternalPlugin(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PluginServiceImpl::GetInternalPlugins(
|
|
|
|
|
std::vector<WebPluginInfo>* plugins) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
PluginList::Singleton()->GetInternalPlugins(plugins);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PluginServiceImpl::PpapiDevChannelSupported(
|
|
|
|
|
BrowserContext* browser_context,
|
|
|
|
|
const GURL& document_url) {
|
|
|
|
|
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
|
|
return GetContentClient()->browser()->IsPluginAllowedToUseDevChannelAPIs(
|
|
|
|
|
browser_context, document_url);
|
|
|
|
|
}
|
|
|
|
|
diff --git a/content/browser/plugin_service_impl.h b/content/browser/plugin_service_impl.h
|
|
|
|
|
index e179b53facd24e6eef7b273bf52d8d80bdc41398..cf98068c47fb772d1f7fe1e8be67d42bac8bde54 100644
|
|
|
|
|
--- a/content/browser/plugin_service_impl.h
|
|
|
|
|
+++ b/content/browser/plugin_service_impl.h
|
|
|
|
|
@@ -10,6 +10,8 @@
|
|
|
|
|
|
|
|
|
|
#include "base/memory/raw_ptr.h"
|
|
|
|
|
#include "base/memory/singleton.h"
|
|
|
|
|
+#include "base/sequence_checker.h"
|
|
|
|
|
+#include "base/task/sequenced_task_runner.h"
|
|
|
|
|
#include "base/time/time.h"
|
|
|
|
|
#include "build/build_config.h"
|
|
|
|
|
#include "content/common/content_export.h"
|
|
|
|
|
@@ -32,7 +34,7 @@ class PluginServiceFilter;
|
|
|
|
|
struct ContentPluginInfo;
|
|
|
|
|
|
|
|
|
|
// This class responds to requests from renderers for the list of plugins, and
|
|
|
|
|
-// also a proxy object for plugin instances. It lives on the UI thread.
|
|
|
|
|
+// also a proxy object for plugin instances.
|
|
|
|
|
class CONTENT_EXPORT PluginServiceImpl : public PluginService {
|
|
|
|
|
public:
|
|
|
|
|
// Returns the PluginServiceImpl singleton.
|
|
|
|
|
@@ -78,7 +80,7 @@ class CONTENT_EXPORT PluginServiceImpl : public PluginService {
|
|
|
|
|
// Returns the plugin process host corresponding to the plugin process that
|
|
|
|
|
// has been started by this service. This will start a process to host the
|
|
|
|
|
// 'plugin_path' if needed. If the process fails to start, the return value
|
|
|
|
|
- // is NULL.
|
|
|
|
|
+ // is NULL. Must be called on the IO thread.
|
|
|
|
|
PpapiPluginProcessHost* FindOrStartPpapiPluginProcess(
|
|
|
|
|
int render_process_id,
|
|
|
|
|
const base::FilePath& plugin_path,
|
|
|
|
|
@@ -86,7 +88,8 @@ class CONTENT_EXPORT PluginServiceImpl : public PluginService {
|
|
|
|
|
const absl::optional<url::Origin>& origin_lock);
|
|
|
|
|
|
|
|
|
|
// Opens a channel to a plugin process for the given mime type, starting
|
|
|
|
|
- // a new plugin process if necessary.
|
|
|
|
|
+ // a new plugin process if necessary. This must be called on the IO thread
|
|
|
|
|
+ // or else a deadlock can occur.
|
|
|
|
|
void OpenChannelToPpapiPlugin(int render_process_id,
|
|
|
|
|
const base::FilePath& plugin_path,
|
|
|
|
|
const base::FilePath& profile_data_directory,
|
|
|
|
|
@@ -129,9 +132,15 @@ class CONTENT_EXPORT PluginServiceImpl : public PluginService {
|
|
|
|
|
|
|
|
|
|
int max_ppapi_processes_per_profile_ = kDefaultMaxPpapiProcessesPerProfile;
|
|
|
|
|
|
|
|
|
|
- // Weak pointer; set during the startup and must outlive us.
|
|
|
|
|
+ // Weak pointer; set during the startup on UI thread and must outlive us.
|
|
|
|
|
raw_ptr<PluginServiceFilter> filter_ = nullptr;
|
|
|
|
|
|
|
|
|
|
+ // Used to load plugins from disk.
|
|
|
|
|
+ scoped_refptr<base::SequencedTaskRunner> plugin_list_task_runner_;
|
|
|
|
|
+
|
|
|
|
|
+ // Used to verify that loading plugins from disk is done sequentially.
|
|
|
|
|
+ base::SequenceChecker plugin_list_sequence_checker_;
|
|
|
|
|
+
|
|
|
|
|
// Used to detect if a given plugin is crashing over and over.
|
|
|
|
|
std::map<base::FilePath, std::vector<base::Time>> crash_times_;
|
|
|
|
|
};
|
|
|
|
|
diff --git a/content/public/browser/plugin_service.h b/content/public/browser/plugin_service.h
|
|
|
|
|
index 0cd7b92aa5850c9dc139e0689e3394fb8ecb42c5..9c3d960a9c6a1ad16487599a0e75875ee1676aaf 100644
|
|
|
|
|
--- a/content/public/browser/plugin_service.h
|
|
|
|
|
+++ b/content/public/browser/plugin_service.h
|
|
|
|
|
@@ -30,7 +30,12 @@ class PluginServiceFilter;
|
|
|
|
|
struct ContentPluginInfo;
|
|
|
|
|
struct WebPluginInfo;
|
|
|
|
|
|
|
|
|
|
-// This class lives on the UI thread.
|
|
|
|
|
+// This must be created on the main thread but it's only called on the IO/file
|
|
|
|
|
+// thread unless otherwise noted. This is an asynchronous wrapper around the
|
|
|
|
|
+// PluginList interface for querying plugin information. This must be used
|
|
|
|
|
+// instead of that to avoid doing expensive disk operations on the IO/UI
|
|
|
|
|
+// threads.
|
|
|
|
|
+// TODO(http://crbug.com/990013): Only use this on the UI thread.
|
|
|
|
|
class CONTENT_EXPORT PluginService {
|
|
|
|
|
public:
|
|
|
|
|
using GetPluginsCallback =
|
|
|
|
|
@@ -43,6 +48,7 @@ class CONTENT_EXPORT PluginService {
|
|
|
|
|
// to throw away their cache of the plugin list, and optionally also reload
|
|
|
|
|
// all the pages with plugins. If |browser_context| is nullptr, purges the
|
|
|
|
|
// cache in all renderers.
|
|
|
|
|
+ // NOTE: can only be called on the UI thread.
|
|
|
|
|
static void PurgePluginListCache(BrowserContext* browser_context,
|
|
|
|
|
bool reload_pages);
|
|
|
|
|
|
|
|
|
|
@@ -52,8 +58,8 @@ class CONTENT_EXPORT PluginService {
|
|
|
|
|
virtual void Init() = 0;
|
|
|
|
|
|
|
|
|
|
// Gets the plugin in the list of plugins that matches the given url and mime
|
|
|
|
|
- // type. Returns true if the data is from a stale plugin list, false if it is
|
|
|
|
|
- // up to date.
|
|
|
|
|
+ // type. Returns true if the data is frome a stale plugin list, false if it
|
|
|
|
|
+ // is up to date. This can be called from any thread.
|
|
|
|
|
virtual bool GetPluginInfoArray(
|
|
|
|
|
const GURL& url,
|
|
|
|
|
const std::string& mime_type,
|
|
|
|
|
@@ -63,7 +69,8 @@ class CONTENT_EXPORT PluginService {
|
|
|
|
|
|
|
|
|
|
// Gets plugin info for an individual plugin and filters the plugins using
|
|
|
|
|
// the |browser_context|. This will report whether the data is stale via
|
|
|
|
|
- // |is_stale| and returns whether or not the plugin can be found.
|
|
|
|
|
+ // |is_stale| and returns whether or not the plugin can be found. This must be
|
|
|
|
|
+ // called from the UI thread.
|
|
|
|
|
virtual bool GetPluginInfo(content::BrowserContext* browser_context,
|
|
|
|
|
const GURL& url,
|
|
|
|
|
const std::string& mime_type,
|
|
|
|
|
@@ -75,21 +82,25 @@ class CONTENT_EXPORT PluginService {
|
|
|
|
|
// Get plugin info by plugin path (including disabled plugins). Returns true
|
|
|
|
|
// if the plugin is found and WebPluginInfo has been filled in |info|. This
|
|
|
|
|
// will use cached data in the plugin list.
|
|
|
|
|
+ // This can be called from any thread.
|
|
|
|
|
virtual bool GetPluginInfoByPath(const base::FilePath& plugin_path,
|
|
|
|
|
WebPluginInfo* info) = 0;
|
|
|
|
|
|
|
|
|
|
// Returns the display name for the plugin identified by the given path. If
|
|
|
|
|
// the path doesn't identify a plugin, or the plugin has no display name,
|
|
|
|
|
// this will attempt to generate a display name from the path.
|
|
|
|
|
+ // This can be called from any thread.
|
|
|
|
|
virtual std::u16string GetPluginDisplayNameByPath(
|
|
|
|
|
const base::FilePath& plugin_path) = 0;
|
|
|
|
|
|
|
|
|
|
// Asynchronously loads plugins if necessary and then calls back to the
|
|
|
|
|
// provided function on the calling sequence on completion.
|
|
|
|
|
+ // This can be called from any thread.
|
|
|
|
|
virtual void GetPlugins(GetPluginsCallback callback) = 0;
|
|
|
|
|
|
|
|
|
|
// Synchronously loads plugins if necessary and returns the list of plugin
|
|
|
|
|
- // infos.
|
|
|
|
|
+ // infos. This can be called from any thread. This method is expected to
|
|
|
|
|
+ // not perform any disk IO.
|
|
|
|
|
virtual std::vector<WebPluginInfo> GetPluginsSynchronous() = 0;
|
|
|
|
|
|
|
|
|
|
// Returns information about a plugin if it exists, otherwise `nullptr`. The
|