Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 5 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | |
| 7 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/lazy_instance.h" | |
| 10 #include "content/browser/renderer_host/render_process_host_impl.h" | |
| 8 #include "content/browser/service_worker/service_worker_context_core.h" | 11 #include "content/browser/service_worker/service_worker_context_core.h" |
| 9 #include "content/browser/service_worker/service_worker_context_observer.h" | 12 #include "content/browser/service_worker/service_worker_context_observer.h" |
| 10 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
| 14 #include "content/public/browser/site_instance.h" | |
| 11 #include "webkit/browser/quota/quota_manager_proxy.h" | 15 #include "webkit/browser/quota/quota_manager_proxy.h" |
| 12 | 16 |
| 13 namespace content { | 17 namespace content { |
| 18 namespace { | |
| 19 base::LazyInstance<base::Callback<bool(int)> > s_increment_worker_refcount; | |
| 20 base::LazyInstance<base::Callback<bool(int)> > s_decrement_worker_refcount; | |
|
kinuko
2014/04/25 13:46:35
Whoa... ah ok it's for testing.
Jeffrey Yasskin
2014/04/26 03:52:19
And gone now.
| |
| 21 | |
| 22 bool IncrementWorkerRefcountByPid(int process_id) { | |
| 23 if (!s_increment_worker_refcount.Get().is_null()) | |
| 24 return s_increment_worker_refcount.Get().Run(process_id); | |
| 25 | |
| 26 RenderProcessHost* rph = RenderProcessHost::FromID(process_id); | |
| 27 if (rph) | |
|
kinuko
2014/04/25 13:46:35
Probably also check if (!rph->FastShutdownStarted(
Jeffrey Yasskin
2014/04/26 03:52:19
Done.
| |
| 28 static_cast<RenderProcessHostImpl*>(rph)->IncrementWorkerRefCount(); | |
| 29 | |
| 30 return rph; | |
|
kinuko
2014/04/25 13:46:35
I prefer explicitly return a boolean value.
Jeffrey Yasskin
2014/04/26 03:52:19
Done.
| |
| 31 } | |
| 32 | |
| 33 bool DecrementWorkerRefcountByPid(int process_id) { | |
| 34 if (!s_decrement_worker_refcount.Get().is_null()) | |
| 35 return s_decrement_worker_refcount.Get().Run(process_id); | |
| 36 | |
| 37 RenderProcessHost* rph = RenderProcessHost::FromID(process_id); | |
| 38 if (rph) | |
| 39 static_cast<RenderProcessHostImpl*>(rph)->DecrementWorkerRefCount(); | |
| 40 | |
| 41 return rph; | |
| 42 } | |
| 43 } // namespace | |
| 14 | 44 |
| 15 ServiceWorkerContextWrapper::ServiceWorkerContextWrapper() | 45 ServiceWorkerContextWrapper::ServiceWorkerContextWrapper() |
| 16 : observer_list_( | 46 : browser_context_(NULL), |
| 17 new ObserverListThreadSafe<ServiceWorkerContextObserver>()) {} | 47 observer_list_( |
| 48 new ObserverListThreadSafe<ServiceWorkerContextObserver>()) { | |
| 49 } | |
| 18 | 50 |
| 19 ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() { | 51 ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() { |
| 20 } | 52 } |
| 21 | 53 |
| 22 void ServiceWorkerContextWrapper::Init( | 54 void ServiceWorkerContextWrapper::Init( |
| 23 const base::FilePath& user_data_directory, | 55 const base::FilePath& user_data_directory, |
| 24 quota::QuotaManagerProxy* quota_manager_proxy) { | 56 quota::QuotaManagerProxy* quota_manager_proxy) { |
| 25 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 57 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 26 BrowserThread::PostTask( | 58 BrowserThread::PostTask( |
| 27 BrowserThread::IO, FROM_HERE, | 59 BrowserThread::IO, FROM_HERE, |
| 28 base::Bind(&ServiceWorkerContextWrapper::Init, this, | 60 base::Bind(&ServiceWorkerContextWrapper::Init, this, |
| 29 user_data_directory, | 61 user_data_directory, |
| 30 make_scoped_refptr(quota_manager_proxy))); | 62 make_scoped_refptr(quota_manager_proxy))); |
| 31 return; | 63 return; |
| 32 } | 64 } |
| 33 DCHECK(!context_core_); | 65 DCHECK(!context_core_); |
| 34 context_core_.reset(new ServiceWorkerContextCore( | 66 context_core_.reset(new ServiceWorkerContextCore( |
| 35 user_data_directory, quota_manager_proxy, observer_list_)); | 67 this, user_data_directory, quota_manager_proxy, observer_list_)); |
| 36 } | 68 } |
| 37 | 69 |
| 38 void ServiceWorkerContextWrapper::Shutdown() { | 70 void ServiceWorkerContextWrapper::Shutdown() { |
| 39 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 71 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 72 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 73 browser_context_ = NULL; | |
| 40 BrowserThread::PostTask( | 74 BrowserThread::PostTask( |
| 41 BrowserThread::IO, FROM_HERE, | 75 BrowserThread::IO, FROM_HERE, |
| 42 base::Bind(&ServiceWorkerContextWrapper::Shutdown, this)); | 76 base::Bind(&ServiceWorkerContextWrapper::Shutdown, this)); |
| 43 return; | 77 return; |
| 44 } | 78 } |
| 79 // This breaks a reference cycle from Core::wrapper_ back to this object. | |
| 45 context_core_.reset(); | 80 context_core_.reset(); |
| 46 } | 81 } |
| 47 | 82 |
| 48 ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() { | 83 ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() { |
| 49 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 84 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 50 return context_core_.get(); | 85 return context_core_.get(); |
| 51 } | 86 } |
| 52 | 87 |
| 88 void ServiceWorkerContextWrapper::IncrementWorkerRef( | |
| 89 const std::vector<int>& process_ids, | |
| 90 const GURL& script_url, | |
| 91 const base::Callback<void(ServiceWorkerStatusCode, int process_id)>& | |
| 92 callback) const { | |
| 93 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 94 | |
| 95 for (std::vector<int>::const_iterator it = process_ids.begin(); | |
| 96 it != process_ids.end(); | |
| 97 ++it) { | |
| 98 if (IncrementWorkerRefcountByPid(*it)) { | |
| 99 BrowserThread::PostTask(BrowserThread::IO, | |
| 100 FROM_HERE, | |
| 101 base::Bind(callback, SERVICE_WORKER_OK, *it)); | |
| 102 return; | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 if (!browser_context_) { | |
| 107 // If all of the processes that requested a SW went away before it was | |
| 108 // created, we should just ignore the request. | |
| 109 LOG(ERROR) << "Couldn't start a new process!"; | |
| 110 BrowserThread::PostTask( | |
| 111 BrowserThread::IO, | |
| 112 FROM_HERE, | |
| 113 base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED, -1)); | |
| 114 return; | |
| 115 } | |
| 116 | |
| 117 // No existing processes available; start a new one. | |
| 118 scoped_refptr<SiteInstance> site_instance = | |
| 119 SiteInstance::CreateForURL(browser_context_, script_url); | |
| 120 RenderProcessHost* rph = site_instance->GetProcess(); | |
| 121 // This Init() call posts a task to the IO thread that adds the RPH's | |
| 122 // ServiceWorkerDispatcherHost to the | |
| 123 // EmbeddedWorkerRegistry::process_sender_map_. | |
| 124 if (!rph->Init()) { | |
| 125 LOG(ERROR) << "Couldn't start a new process!"; | |
| 126 BrowserThread::PostTask( | |
| 127 BrowserThread::IO, | |
| 128 FROM_HERE, | |
| 129 base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED, -1)); | |
| 130 return; | |
| 131 } | |
| 132 | |
| 133 static_cast<RenderProcessHostImpl*>(rph)->IncrementWorkerRefCount(); | |
| 134 BrowserThread::PostTask( | |
| 135 BrowserThread::IO, | |
| 136 FROM_HERE, | |
| 137 base::Bind(callback, SERVICE_WORKER_OK, rph->GetID())); | |
| 138 } | |
| 139 | |
| 140 void ServiceWorkerContextWrapper::DecrementWorkerRef(int process_id) { | |
| 141 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 142 if (!DecrementWorkerRefcountByPid(process_id)) { | |
| 143 DCHECK(false) << "DecrementWorkerRef(" << process_id | |
| 144 << ") doesn't match a previous IncrementWorkerRef"; | |
| 145 } | |
| 146 } | |
| 147 | |
| 53 static void FinishRegistrationOnIO( | 148 static void FinishRegistrationOnIO( |
| 54 const ServiceWorkerContext::ResultCallback& continuation, | 149 const ServiceWorkerContext::ResultCallback& continuation, |
| 55 ServiceWorkerStatusCode status, | 150 ServiceWorkerStatusCode status, |
| 56 int64 registration_id, | 151 int64 registration_id, |
| 57 int64 version_id) { | 152 int64 version_id) { |
| 58 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 153 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 154 if (status != SERVICE_WORKER_OK) | |
| 155 LOG(ERROR) << ServiceWorkerStatusToString(status); | |
| 59 BrowserThread::PostTask( | 156 BrowserThread::PostTask( |
| 60 BrowserThread::UI, | 157 BrowserThread::UI, |
| 61 FROM_HERE, | 158 FROM_HERE, |
| 62 base::Bind(continuation, status == SERVICE_WORKER_OK)); | 159 base::Bind(continuation, status == SERVICE_WORKER_OK)); |
| 63 } | 160 } |
| 64 | 161 |
| 65 void ServiceWorkerContextWrapper::RegisterServiceWorker( | 162 void ServiceWorkerContextWrapper::RegisterServiceWorker( |
| 66 const GURL& pattern, | 163 const GURL& pattern, |
| 67 const GURL& script_url, | 164 const GURL& script_url, |
| 68 int source_process_id, | 165 BrowserContext* browser_context, |
| 69 const ResultCallback& continuation) { | 166 const ResultCallback& continuation) { |
| 70 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 167 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 168 DCHECK(browser_context != NULL); | |
| 169 if (browser_context_ != NULL) { | |
| 170 DCHECK_EQ(browser_context_, browser_context) | |
| 171 << "|context| must be the BrowserContext containing *this."; | |
| 172 } | |
| 173 browser_context_ = browser_context; | |
| 71 BrowserThread::PostTask( | 174 BrowserThread::PostTask( |
| 72 BrowserThread::IO, | 175 BrowserThread::IO, |
| 73 FROM_HERE, | 176 FROM_HERE, |
| 74 base::Bind(&ServiceWorkerContextWrapper::RegisterServiceWorker, | 177 base::Bind(&ServiceWorkerContextWrapper::RegisterServiceWorker, |
| 75 this, | 178 this, |
| 76 pattern, | 179 pattern, |
| 77 script_url, | 180 script_url, |
| 78 source_process_id, | 181 browser_context, |
| 79 continuation)); | 182 continuation)); |
| 80 return; | 183 return; |
| 81 } | 184 } |
| 185 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 82 | 186 |
| 83 context()->RegisterServiceWorker( | 187 context()->RegisterServiceWorker( |
| 84 pattern, | 188 pattern, |
| 85 script_url, | 189 script_url, |
| 86 source_process_id, | 190 -1, |
| 87 NULL /* provider_host */, | 191 NULL /* provider_host */, |
| 88 base::Bind(&FinishRegistrationOnIO, continuation)); | 192 base::Bind(&FinishRegistrationOnIO, continuation)); |
| 89 } | 193 } |
| 90 | 194 |
| 91 static void FinishUnregistrationOnIO( | 195 static void FinishUnregistrationOnIO( |
| 92 const ServiceWorkerContext::ResultCallback& continuation, | 196 const ServiceWorkerContext::ResultCallback& continuation, |
| 93 ServiceWorkerStatusCode status) { | 197 ServiceWorkerStatusCode status) { |
| 94 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 198 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 199 if (status != SERVICE_WORKER_OK) | |
| 200 LOG(ERROR) << ServiceWorkerStatusToString(status); | |
| 95 BrowserThread::PostTask( | 201 BrowserThread::PostTask( |
| 96 BrowserThread::UI, | 202 BrowserThread::UI, |
| 97 FROM_HERE, | 203 FROM_HERE, |
| 98 base::Bind(continuation, status == SERVICE_WORKER_OK)); | 204 base::Bind(continuation, status == SERVICE_WORKER_OK)); |
| 99 } | 205 } |
| 100 | 206 |
| 101 void ServiceWorkerContextWrapper::UnregisterServiceWorker( | 207 void ServiceWorkerContextWrapper::UnregisterServiceWorker( |
| 102 const GURL& pattern, | 208 const GURL& pattern, |
| 103 int source_process_id, | 209 int source_process_id, |
| 104 const ResultCallback& continuation) { | 210 const ResultCallback& continuation) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 124 void ServiceWorkerContextWrapper::AddObserver( | 230 void ServiceWorkerContextWrapper::AddObserver( |
| 125 ServiceWorkerContextObserver* observer) { | 231 ServiceWorkerContextObserver* observer) { |
| 126 observer_list_->AddObserver(observer); | 232 observer_list_->AddObserver(observer); |
| 127 } | 233 } |
| 128 | 234 |
| 129 void ServiceWorkerContextWrapper::RemoveObserver( | 235 void ServiceWorkerContextWrapper::RemoveObserver( |
| 130 ServiceWorkerContextObserver* observer) { | 236 ServiceWorkerContextObserver* observer) { |
| 131 observer_list_->RemoveObserver(observer); | 237 observer_list_->RemoveObserver(observer); |
| 132 } | 238 } |
| 133 | 239 |
| 240 void ServiceWorkerContextWrapper::ResetWorkerRefCountOperationsForTest( | |
| 241 const base::Callback<bool(int)>& increment, | |
| 242 const base::Callback<bool(int)>& decrement) { | |
| 243 s_increment_worker_refcount.Get() = increment; | |
| 244 s_decrement_worker_refcount.Get() = decrement; | |
| 245 } | |
| 246 | |
| 134 } // namespace content | 247 } // namespace content |
| OLD | NEW |