Chromium Code Reviews| Index: extensions/browser/extension_function_dispatcher.cc |
| diff --git a/extensions/browser/extension_function_dispatcher.cc b/extensions/browser/extension_function_dispatcher.cc |
| index 1ad91613b234814753d71e9abd69060c82270bc8..c0097dc95324fd656858d377e12351f54e607768 100644 |
| --- a/extensions/browser/extension_function_dispatcher.cc |
| +++ b/extensions/browser/extension_function_dispatcher.cc |
| @@ -21,6 +21,7 @@ |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/render_process_host.h" |
| +#include "content/public/browser/render_process_host_observer.h" |
| #include "content/public/browser/render_view_host.h" |
| #include "content/public/browser/user_metrics.h" |
| #include "content/public/browser/web_contents.h" |
| @@ -208,6 +209,89 @@ class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper |
| DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper); |
| }; |
| +class ExtensionFunctionDispatcher::UIThreadWorkerResponseCallbackWrapper |
| + : public content::RenderProcessHostObserver { |
| + public: |
| + UIThreadWorkerResponseCallbackWrapper( |
| + const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher, |
| + int render_process_id, |
| + int worker_thread_id) |
| + : dispatcher_(dispatcher), |
| + render_process_id_(render_process_id), |
| + worker_thread_id_(worker_thread_id), |
| + weak_ptr_factory_(this) { |
| + content::RenderProcessHost::FromID(render_process_id_)->AddObserver(this); |
| + } |
| + |
| + ~UIThreadWorkerResponseCallbackWrapper() override {} |
| + |
| + // content::RenderProcessHostObserver override. |
| + void RenderProcessExited(content::RenderProcessHost* process_host, |
| + base::TerminationStatus status, |
| + int exit_code) override { |
| + process_host->RemoveObserver(this); |
| + Cleanup(process_host->GetID()); |
| + } |
| + |
| + // content::RenderProcessHostObserver override. |
| + void RenderProcessHostDestroyed( |
| + content::RenderProcessHost* process_host) override { |
| + process_host->RemoveObserver(this); |
| + Cleanup(process_host->GetID()); |
| + } |
| + |
| + ExtensionFunction::ResponseCallback CreateCallback(int request_id) { |
| + return base::Bind( |
| + &UIThreadWorkerResponseCallbackWrapper::OnExtensionFunctionCompleted, |
| + weak_ptr_factory_.GetWeakPtr(), request_id); |
| + } |
| + |
| + private: |
| + void Cleanup(int render_process_id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + if (render_process_id != render_process_id_) |
| + return; |
| + |
| + if (dispatcher_.get()) { |
| + UIThreadWorkerResponseCallbackWrapperMap& map = |
|
Devlin
2016/04/13 19:46:30
This could potentially remove multiple CallbackWra
lazyboy
2016/04/14 02:07:52
Ah, RenderProcessHost would still keep a reference
|
| + dispatcher_->ui_thread_response_callback_wrappers_for_worker_; |
| + for (UIThreadWorkerResponseCallbackWrapperMap::iterator it = map.begin(); |
| + it != map.end();) { |
| + if (it->first.first == render_process_id) { |
| + it = map.erase(it); |
| + continue; |
| + } |
| + ++it; |
| + } |
| + } |
| + // Note: we might be deleted here! |
|
Devlin
2016/04/13 19:46:30
Technically, this object might even be deleted *be
lazyboy
2016/04/14 02:07:52
Done.
|
| + } |
| + |
| + void OnExtensionFunctionCompleted(int request_id, |
| + ExtensionFunction::ResponseType type, |
| + const base::ListValue& results, |
| + const std::string& error, |
| + functions::HistogramValue histogram_value) { |
| + if (type == ExtensionFunction::BAD_MESSAGE) { |
| + // TODO(lazyboy): Kill the offending process. |
| + return; |
| + } |
| + content::RenderProcessHost* sender = |
| + content::RenderProcessHost::FromID(render_process_id_); |
| + DCHECK(sender); |
| + sender->Send(new ExtensionMsg_ResponseWorker( |
| + worker_thread_id_, request_id, type == ExtensionFunction::SUCCEEDED, |
| + results, error)); |
| + } |
| + |
| + base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; |
| + const int render_process_id_; |
| + const int worker_thread_id_; |
| + base::WeakPtrFactory<UIThreadWorkerResponseCallbackWrapper> weak_ptr_factory_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(UIThreadWorkerResponseCallbackWrapper); |
| +}; |
| + |
| WindowController* |
| ExtensionFunctionDispatcher::Delegate::GetExtensionWindowController() const { |
| return nullptr; |
| @@ -300,36 +384,59 @@ void ExtensionFunctionDispatcher::DispatchOnIOThread( |
| ExtensionFunctionDispatcher::ExtensionFunctionDispatcher( |
| content::BrowserContext* browser_context) |
| - : browser_context_(browser_context) { |
| -} |
| + : browser_context_(browser_context), delegate_(nullptr) {} |
| ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() { |
| } |
| void ExtensionFunctionDispatcher::Dispatch( |
| const ExtensionHostMsg_Request_Params& params, |
| - content::RenderFrameHost* render_frame_host) { |
| - UIThreadResponseCallbackWrapperMap::const_iterator |
| - iter = ui_thread_response_callback_wrappers_.find(render_frame_host); |
| - UIThreadResponseCallbackWrapper* callback_wrapper = nullptr; |
| - if (iter == ui_thread_response_callback_wrappers_.end()) { |
| - callback_wrapper = new UIThreadResponseCallbackWrapper(AsWeakPtr(), |
| - render_frame_host); |
| - ui_thread_response_callback_wrappers_[render_frame_host] = callback_wrapper; |
| + content::RenderFrameHost* render_frame_host, |
| + int render_process_id) { |
| + if (render_frame_host) { |
| + UIThreadResponseCallbackWrapperMap::const_iterator iter = |
| + ui_thread_response_callback_wrappers_.find(render_frame_host); |
| + UIThreadResponseCallbackWrapper* callback_wrapper = nullptr; |
| + if (iter == ui_thread_response_callback_wrappers_.end()) { |
| + callback_wrapper = |
| + new UIThreadResponseCallbackWrapper(AsWeakPtr(), render_frame_host); |
| + ui_thread_response_callback_wrappers_[render_frame_host] = |
| + callback_wrapper; |
| + } else { |
| + callback_wrapper = iter->second; |
| + } |
| + DispatchWithCallbackInternal( |
| + params, render_frame_host, render_process_id, |
| + callback_wrapper->CreateCallback(params.request_id)); |
| } else { |
| - callback_wrapper = iter->second; |
| + // Extension API from Service Worker. |
|
Devlin
2016/04/13 19:46:31
Add an analogous comment in the other if clause on
lazyboy
2016/04/14 02:07:52
Done.
|
| + DCHECK(params.embedded_worker_id >= 0); |
|
Devlin
2016/04/13 19:46:31
DCHECK_GE?
lazyboy
2016/04/14 02:07:52
Done.
|
| + const int& id = params.embedded_worker_id; |
|
Devlin
2016/04/13 19:46:31
no need to make this a const & - it's no cheaper t
lazyboy
2016/04/14 02:07:52
Done.
|
| + UIThreadWorkerResponseCallbackWrapperMapKey key = |
| + std::make_pair(render_process_id, id); |
| + UIThreadWorkerResponseCallbackWrapperMap::const_iterator iter = |
| + ui_thread_response_callback_wrappers_for_worker_.find(key); |
| + UIThreadWorkerResponseCallbackWrapper* callback_wrapper = nullptr; |
| + if (iter == ui_thread_response_callback_wrappers_for_worker_.end()) { |
| + callback_wrapper = new UIThreadWorkerResponseCallbackWrapper( |
| + AsWeakPtr(), render_process_id, params.worker_thread_id); |
| + ui_thread_response_callback_wrappers_for_worker_[key] = |
| + std::unique_ptr<UIThreadWorkerResponseCallbackWrapper>( |
| + callback_wrapper); |
| + } else { |
| + callback_wrapper = iter->second.get(); |
| + } |
| + DispatchWithCallbackInternal( |
|
Devlin
2016/04/13 19:46:31
We can lump these (this and line 408) together if
lazyboy
2016/04/14 02:07:52
I had that in the beginning, but later the code di
|
| + params, nullptr, render_process_id, |
| + callback_wrapper->CreateCallback(params.request_id)); |
| } |
| - |
| - DispatchWithCallbackInternal( |
| - params, render_frame_host, |
| - callback_wrapper->CreateCallback(params.request_id)); |
| } |
| void ExtensionFunctionDispatcher::DispatchWithCallbackInternal( |
| const ExtensionHostMsg_Request_Params& params, |
| content::RenderFrameHost* render_frame_host, |
| + int render_process_id, |
| const ExtensionFunction::ResponseCallback& callback) { |
| - DCHECK(render_frame_host); |
| // TODO(yzshen): There is some shared logic between this method and |
| // DispatchOnIOThread(). It is nice to deduplicate. |
| ProcessMap* process_map = ProcessMap::Get(browser_context_); |
| @@ -344,15 +451,12 @@ void ExtensionFunctionDispatcher::DispatchWithCallbackInternal( |
| registry->enabled_extensions().GetHostedAppByURL(params.source_url); |
| } |
| - int process_id = render_frame_host->GetProcess()->GetID(); |
| - scoped_refptr<ExtensionFunction> function( |
| - CreateExtensionFunction(params, |
| - extension, |
| - process_id, |
| - *process_map, |
| - ExtensionAPI::GetSharedInstance(), |
| - browser_context_, |
| - callback)); |
| + if (render_frame_host) |
| + DCHECK_EQ(render_process_id, render_frame_host->GetProcess()->GetID()); |
| + |
| + scoped_refptr<ExtensionFunction> function(CreateExtensionFunction( |
| + params, extension, render_process_id, *process_map, |
| + ExtensionAPI::GetSharedInstance(), browser_context_, callback)); |
| if (!function.get()) |
| return; |
| @@ -419,11 +523,15 @@ void ExtensionFunctionDispatcher::DispatchWithCallbackInternal( |
| // now, largely for simplicity's sake. This is OK because currently, only |
| // the webRequest API uses IOThreadExtensionFunction, and that API is not |
| // compatible with lazy background pages. |
| + // TODO(lazyboy): API functions from extension Service Worker will incorrectly |
| + // change keepalive count below. |
| process_manager->IncrementLazyKeepaliveCount(extension); |
| } |
| void ExtensionFunctionDispatcher::OnExtensionFunctionCompleted( |
| const Extension* extension) { |
| + // TODO(lazyboy): API functions from extension Service Worker will incorrectly |
| + // change keepalive count below. |
| if (extension) { |
| ProcessManager::Get(browser_context_) |
| ->DecrementLazyKeepaliveCount(extension); |