| 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
|
|
|