Index: content/browser/shared_worker/shared_worker_service_impl.cc |
diff --git a/content/browser/shared_worker/shared_worker_service_impl.cc b/content/browser/shared_worker/shared_worker_service_impl.cc |
index 8ba7eedf739bbd13e5cc999b0096013aa4a007e1..e48add9263e453184df2c7697c2c552ca50d66af 100644 |
--- a/content/browser/shared_worker/shared_worker_service_impl.cc |
+++ b/content/browser/shared_worker/shared_worker_service_impl.cc |
@@ -4,6 +4,12 @@ |
#include "content/browser/shared_worker/shared_worker_service_impl.h" |
+#include <algorithm> |
+#include <iterator> |
+#include <set> |
+#include <vector> |
+ |
+#include "content/browser/renderer_host/render_process_host_impl.h" |
#include "content/browser/shared_worker/shared_worker_host.h" |
#include "content/browser/shared_worker/shared_worker_instance.h" |
#include "content/browser/shared_worker/shared_worker_message_filter.h" |
@@ -14,16 +20,64 @@ |
#include "content/public/browser/worker_service_observer.h" |
namespace content { |
+namespace { |
+ |
+class ScopedWorkerDependencyChecker { |
+ public: |
+ explicit ScopedWorkerDependencyChecker(SharedWorkerServiceImpl* service) |
+ : service_(service) {} |
+ ~ScopedWorkerDependencyChecker() { service_->CheckWorkerDependency(); } |
+ |
+ private: |
+ SharedWorkerServiceImpl* service_; |
+ DISALLOW_COPY_AND_ASSIGN(ScopedWorkerDependencyChecker); |
+}; |
+ |
+void UpdateWorkerDependencyOnUI(const std::vector<int>& added_ids, |
+ const std::vector<int>& removed_ids) { |
+ for (size_t i = 0; i < added_ids.size(); ++i) { |
+ RenderProcessHostImpl* render_process_host_impl = |
+ static_cast<RenderProcessHostImpl*>( |
+ RenderProcessHost::FromID(added_ids[i])); |
+ if (!render_process_host_impl) |
+ continue; |
+ render_process_host_impl->IncrementWorkerRefCount(); |
+ } |
+ for (size_t i = 0; i < removed_ids.size(); ++i) { |
+ RenderProcessHostImpl* render_process_host_impl = |
+ static_cast<RenderProcessHostImpl*>( |
+ RenderProcessHost::FromID(removed_ids[i])); |
+ if (!render_process_host_impl) |
+ continue; |
+ render_process_host_impl->DecrementWorkerRefCount(); |
+ } |
+} |
+ |
+void UpdateWorkerDependency(const std::vector<int>& added_ids, |
+ const std::vector<int>& removed_ids) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&UpdateWorkerDependencyOnUI, added_ids, removed_ids)); |
+} |
+ |
+} // namespace |
SharedWorkerServiceImpl* SharedWorkerServiceImpl::GetInstance() { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
return Singleton<SharedWorkerServiceImpl>::get(); |
} |
-SharedWorkerServiceImpl::SharedWorkerServiceImpl() { |
-} |
+SharedWorkerServiceImpl::SharedWorkerServiceImpl() |
+ : update_worker_dependency_(UpdateWorkerDependency) {} |
-SharedWorkerServiceImpl::~SharedWorkerServiceImpl() { |
+SharedWorkerServiceImpl::~SharedWorkerServiceImpl() {} |
+ |
+void SharedWorkerServiceImpl::ResetForTesting() { |
+ last_worker_depended_renderers_.clear(); |
+ worker_hosts_.clear(); |
+ observers_.Clear(); |
+ update_worker_dependency_ = UpdateWorkerDependency; |
} |
bool SharedWorkerServiceImpl::TerminateWorker(int process_id, int route_id) { |
@@ -73,6 +127,7 @@ void SharedWorkerServiceImpl::CreateWorker( |
const WorkerStoragePartition& partition, |
bool* url_mismatch) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ ScopedWorkerDependencyChecker checker(this); |
*url_mismatch = false; |
SharedWorkerInstance* existing_instance = |
FindSharedWorkerInstance( |
@@ -135,6 +190,7 @@ void SharedWorkerServiceImpl::ForwardToWorker( |
void SharedWorkerServiceImpl::DocumentDetached( |
unsigned long long document_id, |
SharedWorkerMessageFilter* filter) { |
+ ScopedWorkerDependencyChecker checker(this); |
for (WorkerHostMap::const_iterator iter = worker_hosts_.begin(); |
iter != worker_hosts_.end(); |
++iter) { |
@@ -145,6 +201,7 @@ void SharedWorkerServiceImpl::DocumentDetached( |
void SharedWorkerServiceImpl::WorkerContextClosed( |
int worker_route_id, |
SharedWorkerMessageFilter* filter) { |
+ ScopedWorkerDependencyChecker checker(this); |
if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id)) |
host->WorkerContextClosed(); |
} |
@@ -152,6 +209,7 @@ void SharedWorkerServiceImpl::WorkerContextClosed( |
void SharedWorkerServiceImpl::WorkerContextDestroyed( |
int worker_route_id, |
SharedWorkerMessageFilter* filter) { |
+ ScopedWorkerDependencyChecker checker(this); |
scoped_ptr<SharedWorkerHost> host = |
worker_hosts_.take_and_erase(std::make_pair(filter->render_process_id(), |
worker_route_id)); |
@@ -170,6 +228,7 @@ void SharedWorkerServiceImpl::WorkerScriptLoaded( |
void SharedWorkerServiceImpl::WorkerScriptLoadFailed( |
int worker_route_id, |
SharedWorkerMessageFilter* filter) { |
+ ScopedWorkerDependencyChecker checker(this); |
scoped_ptr<SharedWorkerHost> host = |
worker_hosts_.take_and_erase(std::make_pair(filter->render_process_id(), |
worker_route_id)); |
@@ -219,6 +278,7 @@ void SharedWorkerServiceImpl::AllowIndexedDB( |
void SharedWorkerServiceImpl::OnSharedWorkerMessageFilterClosing( |
SharedWorkerMessageFilter* filter) { |
+ ScopedWorkerDependencyChecker checker(this); |
std::vector<ProcessRouteIdPair> remove_list; |
for (WorkerHostMap::iterator iter = worker_hosts_.begin(); |
iter != worker_hosts_.end(); |
@@ -253,4 +313,48 @@ SharedWorkerInstance* SharedWorkerServiceImpl::FindSharedWorkerInstance( |
return NULL; |
} |
+const std::set<int> |
+SharedWorkerServiceImpl::GetRenderersWithWorkerDependency() { |
+ std::set<int> dependent_renderers; |
+ for (WorkerHostMap::iterator host_iter = worker_hosts_.begin(); |
+ host_iter != worker_hosts_.end(); |
+ ++host_iter) { |
+ const int process_id = host_iter->first.first; |
+ if (dependent_renderers.count(process_id)) |
+ continue; |
+ SharedWorkerInstance* instance = host_iter->second->instance(); |
+ if (instance && |
+ instance->worker_document_set()->ContainsExternalRenderer(process_id)) { |
+ dependent_renderers.insert(process_id); |
+ } |
+ } |
+ return dependent_renderers; |
+} |
+ |
+void SharedWorkerServiceImpl::CheckWorkerDependency() { |
+ const std::set<int> current_worker_depended_renderers = |
+ GetRenderersWithWorkerDependency(); |
+ std::vector<int> added_items; |
+ std::vector<int> removed_items; |
+ std::set_difference(current_worker_depended_renderers.begin(), |
+ current_worker_depended_renderers.end(), |
+ last_worker_depended_renderers_.begin(), |
+ last_worker_depended_renderers_.end(), |
+ std::back_inserter(added_items)); |
+ std::set_difference(last_worker_depended_renderers_.begin(), |
+ last_worker_depended_renderers_.end(), |
+ current_worker_depended_renderers.begin(), |
+ current_worker_depended_renderers.end(), |
+ std::back_inserter(removed_items)); |
+ if (!added_items.empty() || !removed_items.empty()) { |
+ last_worker_depended_renderers_ = current_worker_depended_renderers; |
+ update_worker_dependency_(added_items, removed_items); |
+ } |
+} |
+ |
+void SharedWorkerServiceImpl::ChangeUpdateWorkerDependencyFuncForTesting( |
+ UpdateWorkerDependencyFunc new_func) { |
+ update_worker_dependency_ = new_func; |
+} |
+ |
} // namespace content |