summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-23 01:43:56 +0000
committerrsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-23 01:43:56 +0000
commitd33e7cc3d6195681decd0787db8131eb614e7594 (patch)
tree4e3fecbc3246bc583f98856e1150ff4a6f3d84de
parent6c16a36fff1052efef25d0045f0c6222b027a0eb (diff)
downloadchromium_src-d33e7cc3d6195681decd0787db8131eb614e7594.zip
chromium_src-d33e7cc3d6195681decd0787db8131eb614e7594.tar.gz
chromium_src-d33e7cc3d6195681decd0787db8131eb614e7594.tar.bz2
Convert the PluginService interface to be an async wrapper around PluginList.
This adds additional methods to PluginService so that most callers can be moved off PluginList and use the new asynchronous interface. This is in preparation for moving plugin probing out-of-process on Mac and Linux. BUG=17863,95114 TEST=none Review URL: http://codereview.chromium.org/7980011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102421 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/automation/testing_automation_provider.cc22
-rw-r--r--chrome/browser/automation/testing_automation_provider.h8
-rw-r--r--chrome/browser/extensions/extension_content_settings_api.cc35
-rw-r--r--chrome/browser/extensions/extension_content_settings_api.h9
-rw-r--r--chrome/browser/extensions/extension_content_settings_apitest.cc8
-rw-r--r--chrome/browser/metrics/metrics_service.cc77
-rw-r--r--chrome/browser/metrics/metrics_service.h16
-rw-r--r--chrome/browser/pdf_unsupported_feature.cc53
-rw-r--r--chrome/browser/ui/webui/plugins_ui.cc57
-rw-r--r--content/browser/plugin_service.cc72
-rw-r--r--content/browser/plugin_service.h42
-rw-r--r--content/browser/renderer_host/buffered_resource_handler.cc22
-rw-r--r--content/browser/renderer_host/buffered_resource_handler.h9
-rw-r--r--content/browser/renderer_host/render_message_filter.cc40
-rw-r--r--content/browser/renderer_host/render_message_filter.h5
-rw-r--r--webkit/plugins/npapi/plugin_list.h10
16 files changed, 279 insertions, 206 deletions
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index bc08fdc..b8f2e0a 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -103,6 +103,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
+#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/tab_contents/interstitial_page.h"
@@ -115,7 +116,7 @@
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/base/message_box_flags.h"
#include "webkit/glue/webdropdata.h"
-#include "webkit/plugins/npapi/plugin_list.h"
+#include "webkit/plugins/webplugininfo.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/ui/webui/active_downloads_ui.h"
@@ -3495,15 +3496,16 @@ void TestingAutomationProvider::GetPluginsInfo(
Browser* browser,
DictionaryValue* args,
IPC::Message* reply_message) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&TestingAutomationProvider::GetPluginsInfo,
- this, browser, args, reply_message));
- return;
- }
- std::vector<webkit::WebPluginInfo> plugins;
- webkit::npapi::PluginList::Singleton()->GetPlugins(&plugins);
+ PluginService::GetInstance()->GetPlugins(
+ base::Bind(&TestingAutomationProvider::GetPluginsInfoCallback,
+ this, browser, args, reply_message));
+}
+
+void TestingAutomationProvider::GetPluginsInfoCallback(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message,
+ const std::vector<webkit::WebPluginInfo>& plugins) {
PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(browser->profile());
ListValue* items = new ListValue;
for (std::vector<webkit::WebPluginInfo>::const_iterator it =
diff --git a/chrome/browser/automation/testing_automation_provider.h b/chrome/browser/automation/testing_automation_provider.h
index 02efc7c..193cf31 100644
--- a/chrome/browser/automation/testing_automation_provider.h
+++ b/chrome/browser/automation/testing_automation_provider.h
@@ -29,6 +29,10 @@ namespace base {
class DictionaryValue;
}
+namespace webkit {
+struct WebPluginInfo;
+}
+
// This is an automation provider containing testing calls.
class TestingAutomationProvider : public AutomationProvider,
public BrowserList::Observer,
@@ -499,6 +503,10 @@ class TestingAutomationProvider : public AutomationProvider,
void GetPluginsInfo(Browser* browser,
base::DictionaryValue* args,
IPC::Message* reply_message);
+ void GetPluginsInfoCallback(Browser* browser,
+ base::DictionaryValue* args,
+ IPC::Message* reply_message,
+ const std::vector<webkit::WebPluginInfo>& plugins);
// Enable a plugin.
// Uses the JSON interface for input/output.
diff --git a/chrome/browser/extensions/extension_content_settings_api.cc b/chrome/browser/extensions/extension_content_settings_api.cc
index b76024e..01dfee08 100644
--- a/chrome/browser/extensions/extension_content_settings_api.cc
+++ b/chrome/browser/extensions/extension_content_settings_api.cc
@@ -19,8 +19,8 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_error_utils.h"
+#include "content/browser/plugin_service.h"
#include "webkit/plugins/npapi/plugin_group.h"
-#include "webkit/plugins/npapi/plugin_list.h"
namespace helpers = extension_content_settings_helpers;
namespace keys = extension_content_settings_api_constants;
@@ -29,7 +29,7 @@ namespace pref_keys = extension_preference_api_constants;
namespace {
-webkit::npapi::PluginList* g_plugin_list = NULL;
+const std::vector<webkit::npapi::PluginGroup>* g_testing_plugin_groups_;
} // namespace
@@ -265,10 +265,12 @@ bool GetResourceIdentifiersFunction::RunImpl() {
if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS &&
CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableResourceContentSettings)) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&GetResourceIdentifiersFunction::GetPluginsOnFileThread,
- this));
+ if (g_testing_plugin_groups_) {
+ OnGotPluginGroups(*g_testing_plugin_groups_);
+ } else {
+ PluginService::GetInstance()->GetPluginGroups(
+ base::Bind(&GetResourceIdentifiersFunction::OnGotPluginGroups, this));
+ }
} else {
SendResponse(true);
}
@@ -276,18 +278,11 @@ bool GetResourceIdentifiersFunction::RunImpl() {
return true;
}
-void GetResourceIdentifiersFunction::GetPluginsOnFileThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- webkit::npapi::PluginList* plugin_list = g_plugin_list;
- if (!plugin_list) {
- plugin_list = webkit::npapi::PluginList::Singleton();
- }
-
- std::vector<webkit::npapi::PluginGroup> groups;
- plugin_list->GetPluginGroups(true, &groups);
-
+void GetResourceIdentifiersFunction::OnGotPluginGroups(
+ const std::vector<webkit::npapi::PluginGroup>& groups) {
ListValue* list = new ListValue();
- for (std::vector<webkit::npapi::PluginGroup>::iterator it = groups.begin();
+ for (std::vector<webkit::npapi::PluginGroup>::const_iterator it =
+ groups.begin();
it != groups.end(); ++it) {
DictionaryValue* dict = new DictionaryValue();
dict->SetString(keys::kIdKey, it->identifier());
@@ -301,7 +296,7 @@ void GetResourceIdentifiersFunction::GetPluginsOnFileThread() {
}
// static
-void GetResourceIdentifiersFunction::SetPluginListForTesting(
- webkit::npapi::PluginList* plugin_list) {
- g_plugin_list = plugin_list;
+void GetResourceIdentifiersFunction::SetPluginGroupsForTesting(
+ const std::vector<webkit::npapi::PluginGroup>* plugin_groups) {
+ g_testing_plugin_groups_ = plugin_groups;
}
diff --git a/chrome/browser/extensions/extension_content_settings_api.h b/chrome/browser/extensions/extension_content_settings_api.h
index 25aca13..0330e5d 100644
--- a/chrome/browser/extensions/extension_content_settings_api.h
+++ b/chrome/browser/extensions/extension_content_settings_api.h
@@ -10,9 +10,7 @@
namespace webkit {
namespace npapi {
-
-class PluginList;
-
+class PluginGroup;
}
}
@@ -47,10 +45,11 @@ class GetResourceIdentifiersFunction : public AsyncExtensionFunction {
FRIEND_TEST_ALL_PREFIXES(ExtensionApiTest,
ContentSettingsGetResourceIdentifiers);
- void GetPluginsOnFileThread();
+ void OnGotPluginGroups(const std::vector<webkit::npapi::PluginGroup>& groups);
// Used to override the global plugin list in tests.
- static void SetPluginListForTesting(webkit::npapi::PluginList* plugin_list);
+ static void SetPluginGroupsForTesting(
+ const std::vector<webkit::npapi::PluginGroup>* plugin_groups);
};
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_CONTENT_SETTINGS_API_H__
diff --git a/chrome/browser/extensions/extension_content_settings_apitest.cc b/chrome/browser/extensions/extension_content_settings_apitest.cc
index 3294c23..cae206c 100644
--- a/chrome/browser/extensions/extension_content_settings_apitest.cc
+++ b/chrome/browser/extensions/extension_content_settings_apitest.cc
@@ -117,10 +117,14 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest,
FilePath(kBarPath),
ASCIIToUTF16("2.3.4"),
ASCIIToUTF16("bar")));
- GetResourceIdentifiersFunction::SetPluginListForTesting(&plugin_list);
+
+ std::vector<webkit::npapi::PluginGroup> groups;
+ plugin_list.GetPluginGroups(true, &groups);
+
+ GetResourceIdentifiersFunction::SetPluginGroupsForTesting(&groups);
EXPECT_TRUE(RunExtensionTest("content_settings/getresourceidentifiers"))
<< message_;
- GetResourceIdentifiersFunction::SetPluginListForTesting(NULL);
+ GetResourceIdentifiersFunction::SetPluginGroupsForTesting(NULL);
}
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index a64e993..4efdc8c 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -187,6 +187,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "content/browser/load_notification_details.h"
+#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/common/child_process_info.h"
#include "content/common/notification_service.h"
@@ -321,44 +322,6 @@ class MetricsMemoryDetails : public MemoryDetails {
DISALLOW_COPY_AND_ASSIGN(MetricsMemoryDetails);
};
-class MetricsService::InitTaskComplete : public Task {
- public:
- explicit InitTaskComplete(
- const std::string& hardware_class,
- const std::vector<webkit::WebPluginInfo>& plugins)
- : hardware_class_(hardware_class), plugins_(plugins) {}
-
- virtual void Run() {
- g_browser_process->metrics_service()->OnInitTaskComplete(
- hardware_class_, plugins_);
- }
-
- private:
- std::string hardware_class_;
- std::vector<webkit::WebPluginInfo> plugins_;
-};
-
-class MetricsService::InitTask : public Task {
- public:
- explicit InitTask(MessageLoop* callback_loop)
- : callback_loop_(callback_loop) {}
-
- virtual void Run() {
- std::vector<webkit::WebPluginInfo> plugins;
- webkit::npapi::PluginList::Singleton()->GetPlugins(&plugins);
- std::string hardware_class; // Empty string by default.
-#if defined(OS_CHROMEOS)
- chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic(
- "hardware_class", &hardware_class);
-#endif // OS_CHROMEOS
- callback_loop_->PostTask(FROM_HERE, new InitTaskComplete(
- hardware_class, plugins));
- }
-
- private:
- MessageLoop* callback_loop_;
-};
-
// static
void MetricsService::RegisterPrefs(PrefService* local_state) {
DCHECK(IsSingleThreaded());
@@ -796,12 +759,38 @@ void MetricsService::InitializeMetricsState() {
ScheduleNextStateSave();
}
-void MetricsService::OnInitTaskComplete(
- const std::string& hardware_class,
- const std::vector<webkit::WebPluginInfo>& plugins) {
+void MetricsService::InitTaskGetHardwareClass(
+ base::MessageLoopProxy* target_loop) {
+ DCHECK(state_ == INIT_TASK_SCHEDULED);
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ std::string hardware_class;
+#if defined(OS_CHROMEOS)
+ chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic(
+ "hardware_class", &hardware_class);
+#endif // OS_CHROMEOS
+
+ target_loop->PostTask(FROM_HERE,
+ base::Bind(&MetricsService::OnInitTaskGotHardwareClass,
+ base::Unretained(this), hardware_class));
+}
+
+void MetricsService::OnInitTaskGotHardwareClass(
+ const std::string& hardware_class) {
DCHECK(state_ == INIT_TASK_SCHEDULED);
hardware_class_ = hardware_class;
+
+ // Start the next part of the init task: loading plugin information.
+ PluginService::GetInstance()->GetPlugins(
+ base::Bind(&MetricsService::OnInitTaskGotPluginInfo,
+ base::Unretained(this)));
+}
+
+void MetricsService::OnInitTaskGotPluginInfo(
+ const std::vector<webkit::WebPluginInfo>& plugins) {
+ DCHECK(state_ == INIT_TASK_SCHEDULED);
plugins_ = plugins;
+
io_thread_ = g_browser_process->io_thread();
if (state_ == INIT_TASK_SCHEDULED)
state_ = INIT_TASK_DONE;
@@ -853,8 +842,10 @@ void MetricsService::StartRecording() {
// initialization steps (such as plugin list generation) necessary
// for sending the initial log. This avoids blocking the main UI
// thread.
- g_browser_process->file_thread()->message_loop()->PostDelayedTask(FROM_HERE,
- new InitTask(MessageLoop::current()),
+ BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&MetricsService::InitTaskGetHardwareClass,
+ base::Unretained(this),
+ MessageLoop::current()->message_loop_proxy()),
kInitializationDelaySeconds * 1000);
}
}
diff --git a/chrome/browser/metrics/metrics_service.h b/chrome/browser/metrics/metrics_service.h
index 7d9f0284..b3e38f2 100644
--- a/chrome/browser/metrics/metrics_service.h
+++ b/chrome/browser/metrics/metrics_service.h
@@ -38,6 +38,7 @@ class TemplateURLService;
namespace base {
class DictionaryValue;
class ListValue;
+class MessageLoopProxy;
}
namespace prerender {
@@ -165,12 +166,17 @@ class MetricsService : public NotificationObserver,
NEED_TO_SHUTDOWN = ~CLEANLY_SHUTDOWN
};
- class InitTask;
- class InitTaskComplete;
+ // First part of the init task. Called on the FILE thread to load hardware
+ // class information.
+ void InitTaskGetHardwareClass(base::MessageLoopProxy* target_loop);
- // Callback to let us know that the init task is done.
- void OnInitTaskComplete(
- const std::string& hardware_class,
+ // Callback from InitTaskGetHardwareClass() that continues the init task by
+ // loading plugin information.
+ void OnInitTaskGotHardwareClass(const std::string& hardware_class);
+
+ // Callback from PluginService::GetPlugins() that moves the state to
+ // INIT_TASK_DONE.
+ void OnInitTaskGotPluginInfo(
const std::vector<webkit::WebPluginInfo>& plugins);
// When we start a new version of Chromium (different from our last run), we
diff --git a/chrome/browser/pdf_unsupported_feature.cc b/chrome/browser/pdf_unsupported_feature.cc
index d69d8a0..e83b6e1 100644
--- a/chrome/browser/pdf_unsupported_feature.cc
+++ b/chrome/browser/pdf_unsupported_feature.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/pdf_unsupported_feature.h"
+#include "base/bind.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/version.h"
@@ -14,6 +15,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/chrome_interstitial_page.h"
#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
+#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/jstemplate_builder.h"
@@ -30,11 +32,8 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "webkit/plugins/npapi/plugin_group.h"
-#include "webkit/plugins/npapi/plugin_list.h"
-#include "webkit/plugins/webplugininfo.h"
using webkit::npapi::PluginGroup;
-using webkit::npapi::PluginList;
using webkit::WebPluginInfo;
namespace {
@@ -236,7 +235,7 @@ class PDFUnsupportedFeatureInfoBarDelegate : public ConfirmInfoBarDelegate {
public:
// |reader_group| is NULL if Adobe Reader isn't installed.
PDFUnsupportedFeatureInfoBarDelegate(TabContentsWrapper* tab_contents,
- PluginGroup* reader_group);
+ const PluginGroup* reader_group);
virtual ~PDFUnsupportedFeatureInfoBarDelegate();
// ConfirmInfoBarDelegate
@@ -262,7 +261,7 @@ class PDFUnsupportedFeatureInfoBarDelegate : public ConfirmInfoBarDelegate {
PDFUnsupportedFeatureInfoBarDelegate::PDFUnsupportedFeatureInfoBarDelegate(
TabContentsWrapper* tab_contents,
- PluginGroup* reader_group)
+ const PluginGroup* reader_group)
: ConfirmInfoBarDelegate(tab_contents->tab_contents()),
tab_contents_(tab_contents),
reader_installed_(!!reader_group),
@@ -362,14 +361,19 @@ void PDFUnsupportedFeatureInfoBarDelegate::OnNo() {
UserMetricsAction("PDF_InstallReaderInfoBarCancel"));
}
-} // namespace
+void GotPluginGroupsCallback(int process_id,
+ int routing_id,
+ const std::vector<PluginGroup>& groups) {
+ TabContents* tab_contents =
+ tab_util::GetTabContentsByID(process_id, routing_id);
+ if (!tab_contents)
+ return;
+
+ TabContentsWrapper* tab =
+ TabContentsWrapper::GetCurrentWrapperForContents(tab_contents);
+ if (!tab)
+ return;
-void PDFHasUnsupportedFeature(TabContentsWrapper* tab) {
-#if !defined(OS_WIN)
- // Only works for Windows for now. For Mac, we'll have to launch the file
- // externally since Adobe Reader doesn't work inside Chrome.
- return;
-#endif
string16 reader_group_name(ASCIIToUTF16(PluginGroup::kAdobeReaderGroupName));
// If the Reader plugin is disabled by policy, don't prompt them.
@@ -379,12 +383,10 @@ void PDFHasUnsupportedFeature(TabContentsWrapper* tab) {
return;
}
- PluginGroup* reader_group = NULL;
- std::vector<PluginGroup> plugin_groups;
- PluginList::Singleton()->GetPluginGroups(false, &plugin_groups);
- for (size_t i = 0; i < plugin_groups.size(); ++i) {
- if (plugin_groups[i].GetGroupName() == reader_group_name) {
- reader_group = &plugin_groups[i];
+ const PluginGroup* reader_group = NULL;
+ for (size_t i = 0; i < groups.size(); ++i) {
+ if (groups[i].GetGroupName() == reader_group_name) {
+ reader_group = &groups[i];
break;
}
}
@@ -392,3 +394,18 @@ void PDFHasUnsupportedFeature(TabContentsWrapper* tab) {
tab->infobar_tab_helper()->AddInfoBar(
new PDFUnsupportedFeatureInfoBarDelegate(tab, reader_group));
}
+
+} // namespace
+
+void PDFHasUnsupportedFeature(TabContentsWrapper* tab) {
+#if !defined(OS_WIN)
+ // Only works for Windows for now. For Mac, we'll have to launch the file
+ // externally since Adobe Reader doesn't work inside Chrome.
+ return;
+#endif
+
+ PluginService::GetInstance()->GetPluginGroups(
+ base::Bind(&GotPluginGroupsCallback,
+ tab->render_view_host()->process()->id(),
+ tab->render_view_host()->routing_id()));
+}
diff --git a/chrome/browser/ui/webui/plugins_ui.cc b/chrome/browser/ui/webui/plugins_ui.cc
index 0bc8293..d07b1bb 100644
--- a/chrome/browser/ui/webui/plugins_ui.cc
+++ b/chrome/browser/ui/webui/plugins_ui.cc
@@ -8,7 +8,9 @@
#include <string>
#include <vector>
+#include "base/bind.h"
#include "base/memory/singleton.h"
+#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/utf_string_conversions.h"
@@ -27,6 +29,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/browser/browser_thread.h"
+#include "content/browser/plugin_service.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/common/notification_service.h"
#include "grit/browser_resources.h"
@@ -34,7 +37,7 @@
#include "grit/theme_resources.h"
#include "grit/theme_resources_standard.h"
#include "ui/base/resource/resource_bundle.h"
-#include "webkit/plugins/npapi/plugin_list.h"
+#include "webkit/plugins/npapi/plugin_group.h"
using webkit::npapi::PluginGroup;
using webkit::WebPluginInfo;
@@ -119,23 +122,15 @@ class PluginsDOMHandler : public WebUIMessageHandler,
const NotificationDetails& details) OVERRIDE;
private:
- // Loads the plugins on the FILE thread.
- static void LoadPluginsOnFileThread(
- std::vector<PluginGroup>* groups, Task* task);
-
- // Used in conjunction with ListWrapper to avoid any memory leaks.
- static void EnsurePluginGroupsDeleted(
- std::vector<PluginGroup>* groups);
-
// Call this to start getting the plugins on the UI thread.
void LoadPlugins();
// Called on the UI thread when the plugin information is ready.
- void PluginsLoaded(const std::vector<PluginGroup>* groups);
+ void PluginsLoaded(const std::vector<PluginGroup>& groups);
NotificationRegistrar registrar_;
- ScopedRunnableMethodFactory<PluginsDOMHandler> get_plugins_factory_;
+ base::WeakPtrFactory<PluginsDOMHandler> weak_ptr_factory_;
// This pref guards the value whether about:plugins is in the details mode or
// not.
@@ -145,7 +140,7 @@ class PluginsDOMHandler : public WebUIMessageHandler,
};
PluginsDOMHandler::PluginsDOMHandler()
- : ALLOW_THIS_IN_INITIALIZER_LIST(get_plugins_factory_(this)) {
+ : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
registrar_.Add(this,
chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED,
NotificationService::AllSources());
@@ -235,40 +230,16 @@ void PluginsDOMHandler::Observe(int type,
LoadPlugins();
}
-void PluginsDOMHandler::LoadPluginsOnFileThread(
- std::vector<PluginGroup>* groups,
- Task* task) {
- webkit::npapi::PluginList::Singleton()->GetPluginGroups(true, groups);
-
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task);
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- NewRunnableFunction(&PluginsDOMHandler::EnsurePluginGroupsDeleted,
- groups));
-}
-
-void PluginsDOMHandler::EnsurePluginGroupsDeleted(
- std::vector<PluginGroup>* groups) {
- delete groups;
-}
-
void PluginsDOMHandler::LoadPlugins() {
- if (!get_plugins_factory_.empty())
+ if (weak_ptr_factory_.HasWeakPtrs())
return;
- std::vector<PluginGroup>* groups = new std::vector<PluginGroup>;
- Task* task = get_plugins_factory_.NewRunnableMethod(
- &PluginsDOMHandler::PluginsLoaded, groups);
-
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- NewRunnableFunction(
- &PluginsDOMHandler::LoadPluginsOnFileThread, groups, task));
+ PluginService::GetInstance()->GetPluginGroups(
+ base::Bind(&PluginsDOMHandler::PluginsLoaded,
+ weak_ptr_factory_.GetWeakPtr()));
}
-void PluginsDOMHandler::PluginsLoaded(const std::vector<PluginGroup>* groups) {
+void PluginsDOMHandler::PluginsLoaded(const std::vector<PluginGroup>& groups) {
PluginPrefs* plugin_prefs =
PluginPrefs::GetForProfile(Profile::FromWebUI(web_ui_));
@@ -277,9 +248,9 @@ void PluginsDOMHandler::PluginsLoaded(const std::vector<PluginGroup>* groups) {
// Construct DictionaryValues to return to the UI
ListValue* plugin_groups_data = new ListValue();
- for (size_t i = 0; i < groups->size(); ++i) {
+ for (size_t i = 0; i < groups.size(); ++i) {
ListValue* plugin_files = new ListValue();
- const PluginGroup& group = (*groups)[i];
+ const PluginGroup& group = groups[i];
string16 group_name = group.GetGroupName();
bool group_enabled = false;
const WebPluginInfo* active_plugin = NULL;
diff --git a/content/browser/plugin_service.cc b/content/browser/plugin_service.cc
index 0a6007c..6be232a 100644
--- a/content/browser/plugin_service.cc
+++ b/content/browser/plugin_service.cc
@@ -4,9 +4,12 @@
#include "content/browser/plugin_service.h"
+#include "base/bind.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/synchronization/waitable_event.h"
@@ -27,6 +30,7 @@
#include "content/common/plugin_messages.h"
#include "content/common/view_messages.h"
#include "webkit/plugins/npapi/plugin_constants_win.h"
+#include "webkit/plugins/npapi/plugin_group.h"
#include "webkit/plugins/npapi/plugin_list.h"
#include "webkit/plugins/webplugininfo.h"
@@ -36,6 +40,28 @@ using ::base::files::FilePathWatcher;
using content::PluginServiceFilter;
+namespace {
+
+// Helper function that merely runs the callback with the result. Called on the
+// thread on which the original GetPlugins() call was made.
+static void RunGetPluginsCallback(
+ const PluginService::GetPluginsCallback& callback,
+ const std::vector<webkit::WebPluginInfo>& result) {
+ callback.Run(result);
+}
+
+// A callback for GetPlugins() that then gets the freshly loaded plugin groups
+// and runs the callback for GetPluginGroups().
+static void GetPluginsForGroupsCallback(
+ const PluginService::GetPluginGroupsCallback& callback,
+ const std::vector<webkit::WebPluginInfo>& plugins) {
+ std::vector<webkit::npapi::PluginGroup> groups;
+ webkit::npapi::PluginList::Singleton()->GetPluginGroups(false, &groups);
+ callback.Run(groups);
+}
+
+} // namespace
+
#if defined(OS_MACOSX)
static void NotifyPluginsOfActivation() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -417,29 +443,31 @@ bool PluginService::GetPluginInfo(int render_process_id,
return false;
}
-void PluginService::GetPlugins(
- const content::ResourceContext& context,
- std::vector<webkit::WebPluginInfo>* plugins) {
- // GetPlugins may need to load the plugins, so we need to be
- // on the FILE thread.
+void PluginService::RefreshPluginList() {
+ webkit::npapi::PluginList::Singleton()->RefreshPlugins();
+}
+
+void PluginService::GetPlugins(const GetPluginsCallback& callback) {
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&PluginService::GetPluginsInternal, base::Unretained(this),
+ MessageLoop::current()->message_loop_proxy(),
+ callback));
+}
+
+void PluginService::GetPluginGroups(const GetPluginGroupsCallback& callback) {
+ GetPlugins(base::Bind(&GetPluginsForGroupsCallback, callback));
+}
+
+void PluginService::GetPluginsInternal(
+ base::MessageLoopProxy* target_loop,
+ const PluginService::GetPluginsCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- webkit::npapi::PluginList* plugin_list =
- webkit::npapi::PluginList::Singleton();
- std::vector<webkit::WebPluginInfo> all_plugins;
- plugin_list->GetPlugins(&all_plugins);
-
- int child_process_id = -1;
- int routing_id = MSG_ROUTING_NONE;
- for (size_t i = 0; i < all_plugins.size(); ++i) {
- if (!filter_ || filter_->ShouldUsePlugin(child_process_id,
- routing_id,
- &context,
- GURL(),
- GURL(),
- &all_plugins[i])) {
- plugins->push_back(all_plugins[i]);
- }
- }
+
+ std::vector<webkit::WebPluginInfo> plugins;
+ webkit::npapi::PluginList::Singleton()->GetPlugins(&plugins);
+
+ target_loop->PostTask(FROM_HERE,
+ base::Bind(&RunGetPluginsCallback, callback, plugins));
}
void PluginService::OnWaitableEventSignaled(
diff --git a/content/browser/plugin_service.h b/content/browser/plugin_service.h
index 2d2596e..f662b33 100644
--- a/content/browser/plugin_service.h
+++ b/content/browser/plugin_service.h
@@ -13,6 +13,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/singleton.h"
#include "base/synchronization/waitable_event_watcher.h"
@@ -25,7 +26,6 @@
#include "content/common/notification_registrar.h"
#include "googleurl/src/gurl.h"
#include "ipc/ipc_channel_handle.h"
-#include "webkit/plugins/webplugininfo.h"
#if defined(OS_WIN)
#include "base/memory/scoped_ptr.h"
@@ -39,13 +39,26 @@
struct PepperPluginInfo;
class PluginDirWatcherDelegate;
+namespace base {
+class MessageLoopProxy;
+}
+
namespace content {
class ResourceContext;
class PluginServiceFilter;
}
+namespace webkit {
+namespace npapi {
+class PluginGroup;
+class PluginList;
+}
+}
+
// This must be created on the main thread but it's only called on the IO/file
-// thread.
+// thread. 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.
class CONTENT_EXPORT PluginService
: public base::WaitableEventWatcher::Delegate,
public NotificationObserver {
@@ -57,6 +70,11 @@ class CONTENT_EXPORT PluginService
webkit::WebPluginInfo plugin;
};
+ typedef base::Callback<void(const std::vector<webkit::WebPluginInfo>&)>
+ GetPluginsCallback;
+ typedef base::Callback<void(const std::vector<webkit::npapi::PluginGroup>&)>
+ GetPluginGroupsCallback;
+
// Returns the PluginService singleton.
static PluginService* GetInstance();
@@ -115,10 +133,17 @@ class CONTENT_EXPORT PluginService
webkit::WebPluginInfo* info,
std::string* actual_mime_type);
- // Returns a list of all plug-ins available to the resource context. Must be
- // called on the FILE thread.
- void GetPlugins(const content::ResourceContext& context,
- std::vector<webkit::WebPluginInfo>* plugins);
+ // Marks the plugin list as dirty and will cause the plugins to be reloaded
+ // on the next access through GetPlugins() or GetPluginGroups().
+ void RefreshPluginList();
+
+ // Asynchronously loads plugins if necessary and then calls back to the
+ // provided function on the calling MessageLoop on completion.
+ void GetPlugins(const GetPluginsCallback& callback);
+
+ // Asynchronously loads the list of plugin groups if necessary and then calls
+ // back to the provided function on the calling MessageLoop on completion.
+ void GetPluginGroups(const GetPluginGroupsCallback& callback);
// Tells all the renderer processes to throw away their cache of the plugin
// list, and optionally also reload all the pages with plugins.
@@ -128,6 +153,7 @@ class CONTENT_EXPORT PluginService
void set_filter(content::PluginServiceFilter* filter) {
filter_ = filter;
}
+ content::PluginServiceFilter* filter() { return filter_; }
private:
friend struct DefaultSingletonTraits<PluginService>;
@@ -148,6 +174,10 @@ class CONTENT_EXPORT PluginService
PepperPluginInfo* GetRegisteredPpapiPluginInfo(const FilePath& plugin_path);
+ // Function that is run on the FILE thread to load the plugins synchronously.
+ void GetPluginsInternal(base::MessageLoopProxy* target_loop,
+ const GetPluginsCallback& callback);
+
// Helper so we can do the plugin lookup on the FILE thread.
void GetAllowedPluginForOpenChannelToPlugin(
int render_process_id,
diff --git a/content/browser/renderer_host/buffered_resource_handler.cc b/content/browser/renderer_host/buffered_resource_handler.cc
index 5665f15..0cfbc10 100644
--- a/content/browser/renderer_host/buffered_resource_handler.cc
+++ b/content/browser/renderer_host/buffered_resource_handler.cc
@@ -6,6 +6,7 @@
#include <vector>
+#include "base/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/string_util.h"
@@ -24,7 +25,7 @@
#include "net/base/mime_util.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
-#include "webkit/plugins/npapi/plugin_list.h"
+#include "webkit/plugins/webplugininfo.h"
namespace {
@@ -346,10 +347,9 @@ bool BufferedResourceHandler::ShouldWaitForPlugins() {
ResourceDispatcherHost::InfoForRequest(request_);
host_->PauseRequest(info->child_id(), info->request_id(), true);
- // Schedule plugin loading on the file thread.
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(this, &BufferedResourceHandler::LoadPlugins));
+ // Get the plugins asynchronously.
+ PluginService::GetInstance()->GetPlugins(
+ base::Bind(&BufferedResourceHandler::OnPluginsLoaded, this));
return true;
}
@@ -455,16 +455,8 @@ void BufferedResourceHandler::UseAlternateResourceHandler(
real_handler_ = handler;
}
-void BufferedResourceHandler::LoadPlugins() {
- std::vector<webkit::WebPluginInfo> plugins;
- webkit::npapi::PluginList::Singleton()->GetPlugins(&plugins);
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- NewRunnableMethod(this, &BufferedResourceHandler::OnPluginsLoaded));
-}
-
-void BufferedResourceHandler::OnPluginsLoaded() {
+void BufferedResourceHandler::OnPluginsLoaded(
+ const std::vector<webkit::WebPluginInfo>& plugins) {
wait_for_plugins_ = false;
if (!request_)
return;
diff --git a/content/browser/renderer_host/buffered_resource_handler.h b/content/browser/renderer_host/buffered_resource_handler.h
index 8257f54..adffbbc 100644
--- a/content/browser/renderer_host/buffered_resource_handler.h
+++ b/content/browser/renderer_host/buffered_resource_handler.h
@@ -17,6 +17,10 @@ namespace net {
class URLRequest;
} // namespace net
+namespace webkit {
+struct WebPluginInfo;
+}
+
// Used to buffer a request until enough data has been received.
class BufferedResourceHandler : public ResourceHandler {
public:
@@ -69,11 +73,8 @@ class BufferedResourceHandler : public ResourceHandler {
// A reference to |handler| is acquired.
void UseAlternateResourceHandler(int request_id, ResourceHandler* handler);
- // Called on the file thread to load the list of plugins.
- void LoadPlugins();
-
// Called on the IO thread once the list of plugins has been loaded.
- void OnPluginsLoaded();
+ void OnPluginsLoaded(const std::vector<webkit::WebPluginInfo>& plugins);
scoped_refptr<ResourceHandler> real_handler_;
scoped_refptr<ResourceResponse> response_;
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index d64b464..12ba59e 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -21,6 +21,7 @@
#include "content/browser/download/download_types.h"
#include "content/browser/plugin_process_host.h"
#include "content/browser/plugin_service.h"
+#include "content/browser/plugin_service_filter.h"
#include "content/browser/ppapi_plugin_process_host.h"
#include "content/browser/ppapi_broker_process_host.h"
#include "content/browser/renderer_host/browser_render_process_host.h"
@@ -51,7 +52,6 @@
#include "webkit/glue/webcookie.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/plugins/npapi/plugin_group.h"
-#include "webkit/plugins/npapi/plugin_list.h"
#include "webkit/plugins/npapi/webplugin.h"
#include "webkit/plugins/webplugininfo.h"
@@ -295,8 +295,6 @@ void RenderMessageFilter::OnChannelError() {
void RenderMessageFilter::OverrideThreadForMessage(const IPC::Message& message,
BrowserThread::ID* thread) {
switch (message.type()) {
- // Can't load plugins on IO thread.
- case ViewHostMsg_GetPlugins::ID:
// The PluginService::GetPluginInfo may need to load the plugins. Don't do
// it on the IO thread.
case ViewHostMsg_GetPluginInfo::ID:
@@ -338,7 +336,7 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(ViewHostMsg_LoadFont, OnLoadFont)
#endif
- IPC_MESSAGE_HANDLER(ViewHostMsg_GetPlugins, OnGetPlugins)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetPluginInfo, OnGetPluginInfo)
IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin,
@@ -513,7 +511,7 @@ void RenderMessageFilter::OnReleaseCachedFonts() {
void RenderMessageFilter::OnGetPlugins(
bool refresh,
- std::vector<webkit::WebPluginInfo>* plugins) {
+ IPC::Message* reply_msg) {
// Don't refresh if the specified threshold has not been passed. Note that
// this check is performed before off-loading to the file thread. The reason
// we do this is that some pages tend to request that the list of plugins be
@@ -526,13 +524,39 @@ void RenderMessageFilter::OnGetPlugins(
const base::TimeTicks now = base::TimeTicks::Now();
if (now - last_plugin_refresh_time_ >= threshold) {
// Only refresh if the threshold hasn't been exceeded yet.
- webkit::npapi::PluginList::Singleton()->RefreshPlugins();
+ PluginService::GetInstance()->RefreshPluginList();
last_plugin_refresh_time_ = now;
}
}
- PluginService::GetInstance()->GetPlugins(resource_context_,
- plugins);
+ PluginService::GetInstance()->GetPlugins(
+ base::Bind(&RenderMessageFilter::GetPluginsCallback, this, reply_msg));
+}
+
+void RenderMessageFilter::GetPluginsCallback(
+ IPC::Message* reply_msg,
+ const std::vector<webkit::WebPluginInfo>& all_plugins) {
+ // Filter the plugin list.
+ content::PluginServiceFilter* filter = PluginService::GetInstance()->filter();
+ std::vector<webkit::WebPluginInfo> plugins;
+
+ int child_process_id = -1;
+ int routing_id = MSG_ROUTING_NONE;
+ for (size_t i = 0; i < all_plugins.size(); ++i) {
+ // Copy because the filter can mutate.
+ webkit::WebPluginInfo plugin(all_plugins[i]);
+ if (!filter || filter->ShouldUsePlugin(child_process_id,
+ routing_id,
+ &resource_context_,
+ GURL(),
+ GURL(),
+ &plugin)) {
+ plugins.push_back(plugin);
+ }
+ }
+
+ ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins);
+ Send(reply_msg);
}
void RenderMessageFilter::OnGetPluginInfo(
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index 4079134..9922ba1 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -156,8 +156,9 @@ class RenderMessageFilter : public BrowserMessageFilter {
void OnReleaseCachedFonts();
#endif
- void OnGetPlugins(bool refresh,
- std::vector<webkit::WebPluginInfo>* plugins);
+ void OnGetPlugins(bool refresh, IPC::Message* reply_msg);
+ void GetPluginsCallback(IPC::Message* reply_msg,
+ const std::vector<webkit::WebPluginInfo>& plugins);
void OnGetPluginInfo(int routing_id,
const GURL& url,
const GURL& policy_url,
diff --git a/webkit/plugins/npapi/plugin_list.h b/webkit/plugins/npapi/plugin_list.h
index 640ccbd..9d4214a 100644
--- a/webkit/plugins/npapi/plugin_list.h
+++ b/webkit/plugins/npapi/plugin_list.h
@@ -36,7 +36,9 @@ extern FilePath::CharType kDefaultPluginLibraryName[];
class PluginInstance;
// This struct holds entry points into a plugin. The entry points are
-// slightly different between Win/Mac and Unixes.
+// slightly different between Win/Mac and Unixes. Note that the interface for
+// querying plugins is synchronous and it is preferable to use a higher-level
+// asynchronous information to query information.
struct PluginEntryPoints {
#if !defined(OS_POSIX) || defined(OS_MACOSX)
NP_GetEntryPointsFunc np_getentrypoints;
@@ -118,7 +120,7 @@ class PluginList {
const string16& mime_type_descriptions,
std::vector<webkit::WebPluginMimeType>* parsed_mime_types);
- // Get all the plugins.
+ // Get all the plugins synchronously.
void GetPlugins(std::vector<webkit::WebPluginInfo>* plugins);
// Returns a list in |info| containing plugins that are found for
@@ -146,7 +148,9 @@ class PluginList {
bool GetPluginInfoByPath(const FilePath& plugin_path,
webkit::WebPluginInfo* info);
- // Populates the given vector with all available plugin groups.
+ // Populates the given vector with all available plugin groups. If
+ // |load_if_necessary| is true, this will potentially load the plugin list
+ // synchronously.
void GetPluginGroups(bool load_if_necessary,
std::vector<PluginGroup>* plugin_groups);