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 |