diff options
-rw-r--r-- | chrome/browser/metrics/metrics_service.cc | 57 | ||||
-rw-r--r-- | chrome/browser/metrics/metrics_service.h | 5 | ||||
-rw-r--r-- | chrome/browser/plugin_service.cc | 38 | ||||
-rw-r--r-- | chrome/browser/plugin_service.h | 13 | ||||
-rw-r--r-- | chrome/browser/renderer_host/buffered_resource_handler.cc | 38 | ||||
-rw-r--r-- | chrome/browser/renderer_host/buffered_resource_handler.h | 9 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.cc | 38 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.h | 11 |
8 files changed, 138 insertions, 71 deletions
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc index 5839171..82cdeac 100644 --- a/chrome/browser/metrics/metrics_service.cc +++ b/chrome/browser/metrics/metrics_service.cc @@ -174,6 +174,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/load_notification_details.h" #include "chrome/browser/memory_details.h" +#include "chrome/browser/plugin_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/search_engines/template_url_model.h" @@ -284,35 +285,39 @@ class MetricsMemoryDetails : public MemoryDetails { DISALLOW_EVIL_CONSTRUCTORS(MetricsMemoryDetails); }; -class MetricsService::GetPluginListTaskComplete : public Task { +// This object and its static functions manage the calls to and from +// the plugin service. It lives on the IO thread. It only lives long +// enough to handle the callback, then it deletes itself. +class GetPluginListClient : public PluginService::GetPluginListClient { public: - explicit GetPluginListTaskComplete( - const std::vector<WebPluginInfo>& plugins) : plugins_(plugins) { } - virtual void Run() { - g_browser_process->metrics_service()->OnGetPluginListTaskComplete(plugins_); + // Call GetPluginList on a GetPluginListClient. Used to proxy this call + // from the UI thread to the IO thread. + static void CallGetPluginList(GetPluginListClient* client) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + PluginService::GetInstance()->GetPluginList(false, client); } - private: - std::vector<WebPluginInfo> plugins_; -}; - -class MetricsService::GetPluginListTask : public Task { - public: - explicit GetPluginListTask(MessageLoop* callback_loop) - : callback_loop_(callback_loop) {} - - virtual void Run() { - std::vector<WebPluginInfo> plugins; - NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); - - callback_loop_->PostTask( - FROM_HERE, new GetPluginListTaskComplete(plugins)); + // Callback from the PluginService when the plugin list has been retrieved. + virtual void OnGetPluginList(const std::vector<WebPluginInfo>& plugins) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + // Forward back to the UI thread. + ChromeThread::PostTask( + ChromeThread::UI, FROM_HERE, + NewRunnableFunction(&GetPluginListClient::GetPluginListComplete, + plugins)); + delete this; } - private: - MessageLoop* callback_loop_; + // A function to proxy the plugin list back from the IO thread to the UI + // thread to call the metrics service. + // |plugins| is intentionally pass by value. + static void GetPluginListComplete(const std::vector<WebPluginInfo> plugins) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + g_browser_process->metrics_service()->OnGetPluginListComplete(plugins); + } }; + // static void MetricsService::RegisterPrefs(PrefService* local_state) { DCHECK(IsSingleThreaded()); @@ -745,7 +750,7 @@ void MetricsService::InitializeMetricsState() { ScheduleNextStateSave(); } -void MetricsService::OnGetPluginListTaskComplete( +void MetricsService::OnGetPluginListComplete( const std::vector<WebPluginInfo>& plugins) { DCHECK(state_ == PLUGIN_LIST_REQUESTED); plugins_ = plugins; @@ -826,8 +831,10 @@ void MetricsService::StartRecording() { // Make sure the plugin list is loaded before the inital log is sent, so // that the main thread isn't blocked generating the list. - g_browser_process->file_thread()->message_loop()->PostDelayedTask(FROM_HERE, - new GetPluginListTask(MessageLoop::current()), + ChromeThread::PostDelayedTask( + ChromeThread::IO, FROM_HERE, + NewRunnableFunction(&GetPluginListClient::CallGetPluginList, + new GetPluginListClient), kInitialInterlogDuration * 1000 / 2); } } diff --git a/chrome/browser/metrics/metrics_service.h b/chrome/browser/metrics/metrics_service.h index 2386827..b66d36e 100644 --- a/chrome/browser/metrics/metrics_service.h +++ b/chrome/browser/metrics/metrics_service.h @@ -118,7 +118,7 @@ class MetricsService : public NotificationObserver, void RecordBreakpadHasDebugger(bool has_debugger); // Callback to let us knew that the plugin list is warmed up. - void OnGetPluginListTaskComplete(const std::vector<WebPluginInfo>& plugins); + void OnGetPluginListComplete(const std::vector<WebPluginInfo>& plugins); // Save any unsent logs into a persistent store in a pref. We always do this // at shutdown, but we can do it as we reduce the list as well. @@ -146,9 +146,6 @@ class MetricsService : public NotificationObserver, // Maintain a map of histogram names to the sample stats we've sent. typedef std::map<std::string, Histogram::SampleSet> LoggedSampleMap; - class GetPluginListTask; - class GetPluginListTaskComplete; - // When we start a new version of Chromium (different from our last run), we // need to discard the old crash stats so that we don't attribute crashes etc. // in the old version to the current version (via current logs). diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc index ba5821e..578e23e 100644 --- a/chrome/browser/plugin_service.cc +++ b/chrome/browser/plugin_service.cc @@ -126,6 +126,44 @@ const FilePath& PluginService::GetChromePluginDataDir() { return chrome_plugin_data_dir_; } +// Call the GetPluginListClient back with a list of plugings. +// |plugins| is intentionally pass-by-value so it's copied from the File thread +// back to the IO thread. +static void CallGetPluginListClient(PluginService::GetPluginListClient* client, + const std::vector<WebPluginInfo> plugins) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + + client->OnGetPluginList(plugins); +} + +// Go out to disk (well, NPAPI::PluginList) to get the plugin list. +// Called on the file thread. +static void GetPluginListOnFileThread( + bool refresh, + PluginService::GetPluginListClient* client) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); + + std::vector<WebPluginInfo> plugins; + NPAPI::PluginList::Singleton()->GetPlugins(refresh, &plugins); + + // Call the client back on the IO thread. + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, + NewRunnableFunction(&CallGetPluginListClient, + client, + plugins)); +} + +void PluginService::GetPluginList(bool refresh, + GetPluginListClient* client) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + + // Forward the request on to the file thread. + ChromeThread::PostTask( + ChromeThread::FILE, FROM_HERE, + NewRunnableFunction(&GetPluginListOnFileThread, refresh, client)); +} + const std::wstring& PluginService::GetUILocale() { return ui_locale_; } diff --git a/chrome/browser/plugin_service.h b/chrome/browser/plugin_service.h index 7ab39e2..fba9b04 100644 --- a/chrome/browser/plugin_service.h +++ b/chrome/browser/plugin_service.h @@ -53,6 +53,19 @@ class PluginService void SetChromePluginDataDir(const FilePath& data_dir); const FilePath& GetChromePluginDataDir(); + // An interface for GetPluginList callbacks. Note that this is + // called directly by the PluginService on the IO thread, so the + // implementor of this interface must outlive the request. + class GetPluginListClient { + public: + // Called when the request completes. + virtual void OnGetPluginList(const std::vector<WebPluginInfo>& plugins) = 0; + }; + + // Start a query for the list of plugins. + // If |refresh| is true, refreshes the list. + void GetPluginList(bool refresh, GetPluginListClient* client); + // Gets the browser's UI locale. const std::wstring& GetUILocale(); diff --git a/chrome/browser/renderer_host/buffered_resource_handler.cc b/chrome/browser/renderer_host/buffered_resource_handler.cc index f3ca82f..a72c54d 100644 --- a/chrome/browser/renderer_host/buffered_resource_handler.cc +++ b/chrome/browser/renderer_host/buffered_resource_handler.cc @@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/string_util.h" #include "chrome/browser/chrome_thread.h" +#include "chrome/browser/plugin_service.h" #include "chrome/browser/renderer_host/download_throttling_resource_handler.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" @@ -395,10 +396,10 @@ bool BufferedResourceHandler::ShouldWaitForPlugins() { ResourceDispatcherHost::InfoForRequest(request_); host_->PauseRequest(info->child_id(), info->request_id(), true); - // Schedule plugin loading on the file thread. - ChromeThread::PostTask( - ChromeThread::FILE, FROM_HERE, - NewRunnableMethod(this, &BufferedResourceHandler::LoadPlugins)); + // Schedule plugin loading. + this->AddRef(); // Balanced in OnGetPluginList. + PluginService::GetInstance()->GetPluginList(false, this); + return true; } @@ -466,23 +467,18 @@ bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) { GURL(), type, allow_wildcard, &info, NULL); } -void BufferedResourceHandler::LoadPlugins() { - std::vector<WebPluginInfo> plugins; - NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); - - ChromeThread::PostTask( - ChromeThread::IO, FROM_HERE, - NewRunnableMethod(this, &BufferedResourceHandler::OnPluginsLoaded)); -} - -void BufferedResourceHandler::OnPluginsLoaded() { +void BufferedResourceHandler::OnGetPluginList( + const std::vector<WebPluginInfo>& plugins) { wait_for_plugins_ = false; - if (!request_) - return; - ResourceDispatcherHostRequestInfo* info = - ResourceDispatcherHost::InfoForRequest(request_); - host_->PauseRequest(info->child_id(), info->request_id(), false); - if (!CompleteResponseStarted(info->request_id(), false)) - host_->CancelRequest(info->child_id(), info->request_id(), false); + if (request_) { + ResourceDispatcherHostRequestInfo* info = + ResourceDispatcherHost::InfoForRequest(request_); + host_->PauseRequest(info->child_id(), info->request_id(), false); + if (!CompleteResponseStarted(info->request_id(), false)) + host_->CancelRequest(info->child_id(), info->request_id(), false); + } + + // Drop the reference added before the GetPluginList call. + this->Release(); } diff --git a/chrome/browser/renderer_host/buffered_resource_handler.h b/chrome/browser/renderer_host/buffered_resource_handler.h index 6bc34e1..3bed83a7 100644 --- a/chrome/browser/renderer_host/buffered_resource_handler.h +++ b/chrome/browser/renderer_host/buffered_resource_handler.h @@ -7,6 +7,7 @@ #include <string> +#include "chrome/browser/plugin_service.h" #include "chrome/browser/renderer_host/resource_handler.h" class MessageLoop; @@ -14,7 +15,8 @@ class ResourceDispatcherHost; class URLRequest; // Used to buffer a request until enough data has been received. -class BufferedResourceHandler : public ResourceHandler { +class BufferedResourceHandler : public ResourceHandler, + public PluginService::GetPluginListClient { public: BufferedResourceHandler(ResourceHandler* handler, ResourceDispatcherHost* host, @@ -63,11 +65,8 @@ class BufferedResourceHandler : public ResourceHandler { // loaded. bool ShouldDownload(bool* need_plugin_list); - // 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 OnGetPluginList(const std::vector<WebPluginInfo>& plugins); scoped_refptr<ResourceHandler> real_handler_; scoped_refptr<ResourceResponse> response_; diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 8006960..afc5007 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -582,22 +582,32 @@ void ResourceMessageFilter::OnLoadFont(LOGFONT font) { void ResourceMessageFilter::OnGetPlugins(bool refresh, IPC::Message* reply_msg) { - ChromeThread::PostTask( - ChromeThread::FILE, FROM_HERE, - NewRunnableMethod( - this, &ResourceMessageFilter::OnGetPluginsOnFileThread, refresh, - reply_msg)); + // Start the query to the plugin service, but only if we don't have another + // query already processing. + if (pending_getpluginlist_.empty()) { + PluginService::GetInstance()->GetPluginList(refresh, this); + this->AddRef(); + } + + // Put reply_msg into the queue of waiting responses. + pending_getpluginlist_.push(std::make_pair(refresh, reply_msg)); } -void ResourceMessageFilter::OnGetPluginsOnFileThread( - bool refresh, IPC::Message* reply_msg) { - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); - std::vector<WebPluginInfo> plugins; - NPAPI::PluginList::Singleton()->GetPlugins(refresh, &plugins); - ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins); - ChromeThread::PostTask( - ChromeThread::IO, FROM_HERE, - NewRunnableMethod(this, &ResourceMessageFilter::Send, reply_msg)); +void ResourceMessageFilter::OnGetPluginList( + const std::vector<WebPluginInfo>& plugins) { + IPC::Message* msg = pending_getpluginlist_.front().second; + ViewHostMsg_GetPlugins::WriteReplyParams(msg, plugins); + Send(msg); + + pending_getpluginlist_.pop(); + if (!pending_getpluginlist_.empty()) { + // We have more pending requests; start the next one. + PluginService::GetInstance()->GetPluginList( + pending_getpluginlist_.front().first, this); + } else { + // Drop the reference grabbed in OnGetPlugins(). + this->Release(); + } } void ResourceMessageFilter::OnGetPluginPath(const GURL& url, diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 53c78dd..974abfc 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -24,6 +24,7 @@ #include "build/build_config.h" #include "chrome/browser/net/resolve_proxy_msg_helper.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" +#include "chrome/browser/plugin_service.h" #include "chrome/common/nacl_types.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/transport_dib.h" @@ -73,7 +74,8 @@ struct ViewHostMsg_DidPrintPage_Params; class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, public ResourceDispatcherHost::Receiver, public NotificationObserver, - public ResolveProxyMsgHelper::Delegate { + public ResolveProxyMsgHelper::Delegate, + public PluginService::GetPluginListClient { public: // Create the filter. // Note: because the lifecycle of the ResourceMessageFilter is not @@ -152,7 +154,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, void OnGetScreenInfo(gfx::NativeViewId window, IPC::Message* reply); #endif void OnGetPlugins(bool refresh, IPC::Message* reply_msg); - void OnGetPluginsOnFileThread(bool refresh, IPC::Message* reply_msg); + virtual void OnGetPluginList(const std::vector<WebPluginInfo>& plugins); void OnGetPluginPath(const GURL& url, const GURL& policy_url, const std::string& mime_type, @@ -398,6 +400,11 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, // A callback to create a routing id for the associated renderer process. scoped_ptr<CallbackWithReturnValue<int>::Type> next_route_id_callback_; + // A queue of pending GetPluginList calls. The bool is the |refresh| + // flag used to make the call, and the IPC::Message is the destination + // of the result of the call once the call completes. + std::queue<std::pair<bool, IPC::Message*> > pending_getpluginlist_; + DISALLOW_COPY_AND_ASSIGN(ResourceMessageFilter); }; |