OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_internals_ui.h" | 5 #include "content/browser/service_worker/service_worker_internals_ui.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 17 matching lines...) Expand all Loading... | |
28 | 28 |
29 using base::DictionaryValue; | 29 using base::DictionaryValue; |
30 using base::FundamentalValue; | 30 using base::FundamentalValue; |
31 using base::ListValue; | 31 using base::ListValue; |
32 using base::StringValue; | 32 using base::StringValue; |
33 using base::Value; | 33 using base::Value; |
34 using base::WeakPtr; | 34 using base::WeakPtr; |
35 | 35 |
36 namespace content { | 36 namespace content { |
37 | 37 |
38 // This class proxies calls to the ServiceWorker APIs on the IO | 38 namespace { |
39 // thread, and then calls back JavaScript on the UI thread. | 39 |
40 class ServiceWorkerInternalsUI::OperationProxy | 40 typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback; |
41 : public base::RefCountedThreadSafe< | 41 typedef void (ServiceWorkerVersion::*ServiceWorkerVersionMethod)( |
42 ServiceWorkerInternalsUI::OperationProxy> { | 42 const StatusCallback& callback); |
falken
2014/05/28 08:21:40
These typedefs are duplicated in the .h file.
horo
2014/05/28 09:06:39
Done.
| |
43 public: | 43 |
44 OperationProxy(const WeakPtr<ServiceWorkerInternalsUI> internals, | 44 void OperationCompleteCallback( |
45 scoped_ptr<ListValue> original_args) | 45 const WeakPtr<ServiceWorkerInternalsUI> internals, |
falken
2014/05/28 08:21:40
Chrome code doesn't seem to use const WeakPtr... I
horo
2014/05/28 09:06:39
Done.
| |
46 : internals_(internals), original_args_(original_args.Pass()) {} | 46 int callback_id, |
47 | 47 ServiceWorkerStatusCode status) { |
48 void GetRegistrationsOnIOThread(int partition_id, | 48 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
49 ServiceWorkerContextWrapper* context, | 49 BrowserThread::PostTask( |
50 const base::FilePath& context_path); | 50 BrowserThread::UI, |
51 void UnregisterOnIOThread(scoped_refptr<ServiceWorkerContextWrapper> context, | 51 FROM_HERE, |
52 const GURL& scope); | 52 base::Bind(OperationCompleteCallback, internals, callback_id, status)); |
53 void StartWorkerOnIOThread(scoped_refptr<ServiceWorkerContextWrapper> context, | 53 return; |
54 const GURL& scope); | 54 } |
55 void StopWorkerOnIOThread(scoped_refptr<ServiceWorkerContextWrapper> context, | 55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
56 const GURL& scope); | 56 if (internals) |
falken
2014/05/28 08:21:40
this if should probably have braces as the body ha
horo
2014/05/28 09:06:39
Done.
| |
57 void DispatchSyncEventToWorkerOnIOThread( | 57 internals->web_ui()->CallJavascriptFunction( |
58 scoped_refptr<ServiceWorkerContextWrapper> context, | 58 "serviceworker.onOperationComplete", |
59 const GURL& scope); | 59 FundamentalValue(static_cast<int>(status)), |
60 void InspectWorkerOnIOThread( | 60 FundamentalValue(callback_id)); |
61 scoped_refptr<ServiceWorkerContextWrapper> context, | 61 } |
62 const GURL& scope); | 62 |
63 | 63 void CallServiceWorkerVersionMethodWithVersionID( |
64 private: | 64 ServiceWorkerVersionMethod method, |
65 friend class base::RefCountedThreadSafe<OperationProxy>; | 65 scoped_refptr<ServiceWorkerContextWrapper> context, |
66 ~OperationProxy() {} | 66 int64 version_id, |
67 void OnHaveRegistrations( | 67 const StatusCallback& callback) { |
68 int partition_id, | 68 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
69 const base::FilePath& context_path, | 69 BrowserThread::PostTask( |
70 const std::vector<ServiceWorkerRegistrationInfo>& registrations); | 70 BrowserThread::IO, |
71 | 71 FROM_HERE, |
72 void OperationComplete(ServiceWorkerStatusCode status); | 72 base::Bind(CallServiceWorkerVersionMethodWithVersionID, |
73 | 73 method, |
74 void StartActiveWorker( | 74 context, |
75 ServiceWorkerStatusCode status, | 75 version_id, |
76 const scoped_refptr<ServiceWorkerRegistration>& registration); | 76 callback)); |
77 | 77 return; |
78 void StopActiveWorker( | 78 } |
79 ServiceWorkerStatusCode status, | 79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
80 const scoped_refptr<ServiceWorkerRegistration>& registration); | 80 scoped_refptr<ServiceWorkerVersion> version = |
81 | 81 context->context()->GetLiveVersion(version_id); |
82 void DispatchSyncEventToActiveWorker( | 82 if (!version) { |
83 ServiceWorkerStatusCode status, | 83 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND); |
84 const scoped_refptr<ServiceWorkerRegistration>& registration); | 84 return; |
85 | 85 } |
86 void InspectActiveWorker( | 86 (*version.*method)(callback); |
87 const ServiceWorkerContextCore* const service_worker_context, | 87 } |
88 ServiceWorkerStatusCode status, | 88 |
89 const scoped_refptr<ServiceWorkerRegistration>& registration); | 89 void UnregisterWithScope(scoped_refptr<ServiceWorkerContextWrapper> context, |
90 | 90 const GURL& scope, |
91 void InspectWorkerOnUIThread( | 91 const StatusCallback& callback) { |
92 const ServiceWorkerContextCore* const service_worker_context, | 92 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
93 int64 version_id); | 93 BrowserThread::PostTask( |
94 | 94 BrowserThread::IO, |
95 WeakPtr<ServiceWorkerInternalsUI> internals_; | 95 FROM_HERE, |
96 scoped_ptr<ListValue> original_args_; | 96 base::Bind(UnregisterWithScope, context, scope, callback)); |
97 }; | 97 return; |
98 } | |
99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
100 context->context()->UnregisterServiceWorker(scope, callback); | |
101 } | |
102 | |
103 void WorkerStarted(const scoped_refptr<ServiceWorkerRegistration>& registration, | |
104 const StatusCallback& callback, | |
105 ServiceWorkerStatusCode status) { | |
106 callback.Run(status); | |
107 } | |
108 | |
109 void StartActiveWorker( | |
110 const StatusCallback& callback, | |
111 ServiceWorkerStatusCode status, | |
112 const scoped_refptr<ServiceWorkerRegistration>& registration) { | |
113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
114 if (status == SERVICE_WORKER_OK) { | |
115 // Pass the reference of |registration| to WorkerStarted callback to prevent | |
116 // it from being deleted while starting the worker. It the refcount of | |
falken
2014/05/28 08:21:40
s/It/If/.... but why does StartWorker destroy the
horo
2014/05/28 09:06:39
Done.
If there is no ServiceWorkerHandle which has
| |
117 // |registration| is 1, it will be deleted after WorkerStarted is called. | |
118 registration->active_version()->StartWorker( | |
119 base::Bind(WorkerStarted, registration, callback)); | |
120 return; | |
121 } | |
122 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND); | |
123 } | |
124 | |
125 void FindRegistrationForPattern( | |
126 scoped_refptr<ServiceWorkerContextWrapper> context, | |
127 const GURL& scope, | |
128 const ServiceWorkerStorage::FindRegistrationCallback callback) { | |
129 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | |
130 BrowserThread::PostTask( | |
131 BrowserThread::IO, | |
132 FROM_HERE, | |
133 base::Bind(FindRegistrationForPattern, context, scope, callback)); | |
134 return; | |
135 } | |
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
137 context->context()->storage()->FindRegistrationForPattern(scope, callback); | |
138 } | |
139 | |
140 void UpdateVersionInfo(const ServiceWorkerVersionInfo& version, | |
141 DictionaryValue* info) { | |
142 switch (version.running_status) { | |
143 case ServiceWorkerVersion::STOPPED: | |
144 info->SetString("running_status", "STOPPED"); | |
145 break; | |
146 case ServiceWorkerVersion::STARTING: | |
147 info->SetString("running_status", "STARTING"); | |
148 break; | |
149 case ServiceWorkerVersion::RUNNING: | |
150 info->SetString("running_status", "RUNNING"); | |
151 break; | |
152 case ServiceWorkerVersion::STOPPING: | |
153 info->SetString("running_status", "STOPPING"); | |
154 break; | |
155 } | |
156 | |
157 switch (version.status) { | |
158 case ServiceWorkerVersion::NEW: | |
159 info->SetString("status", "NEW"); | |
160 break; | |
161 case ServiceWorkerVersion::INSTALLING: | |
162 info->SetString("status", "INSTALLING"); | |
163 break; | |
164 case ServiceWorkerVersion::INSTALLED: | |
165 info->SetString("status", "INSTALLED"); | |
166 break; | |
167 case ServiceWorkerVersion::ACTIVATING: | |
168 info->SetString("status", "ACTIVATING"); | |
169 break; | |
170 case ServiceWorkerVersion::ACTIVE: | |
171 info->SetString("status", "ACTIVE"); | |
172 break; | |
173 case ServiceWorkerVersion::DEACTIVATED: | |
174 info->SetString("status", "DEACTIVATED"); | |
175 break; | |
176 } | |
177 info->SetString("version_id", base::Int64ToString(version.version_id)); | |
178 info->SetInteger("process_id", version.process_id); | |
179 info->SetInteger("thread_id", version.thread_id); | |
180 info->SetInteger("devtools_agent_route_id", version.devtools_agent_route_id); | |
181 } | |
182 | |
183 ListValue* GetRegistrationListValue( | |
184 const std::vector<ServiceWorkerRegistrationInfo>& registrations) { | |
185 ListValue* result = new ListValue(); | |
186 for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it = | |
187 registrations.begin(); | |
188 it != registrations.end(); | |
189 ++it) { | |
190 const ServiceWorkerRegistrationInfo& registration = *it; | |
191 DictionaryValue* registration_info = new DictionaryValue(); | |
192 registration_info->SetString("scope", registration.pattern.spec()); | |
193 registration_info->SetString("script_url", registration.script_url.spec()); | |
194 registration_info->SetString( | |
195 "registration_id", base::Int64ToString(registration.registration_id)); | |
196 | |
197 if (!registration.active_version.is_null) { | |
198 DictionaryValue* active_info = new DictionaryValue(); | |
199 UpdateVersionInfo(registration.active_version, active_info); | |
200 registration_info->Set("active", active_info); | |
201 } | |
202 | |
203 if (!registration.pending_version.is_null) { | |
204 DictionaryValue* pending_info = new DictionaryValue(); | |
205 UpdateVersionInfo(registration.pending_version, pending_info); | |
206 registration_info->Set("pending", pending_info); | |
207 } | |
208 | |
209 result->Append(registration_info); | |
210 } | |
211 return result; | |
212 } | |
213 | |
214 ListValue* GetVersionListValue( | |
215 const std::vector<ServiceWorkerVersionInfo>& versions) { | |
216 ListValue* result = new ListValue(); | |
217 for (std::vector<ServiceWorkerVersionInfo>::const_iterator it = | |
218 versions.begin(); | |
219 it != versions.end(); | |
220 ++it) { | |
221 DictionaryValue* info = new DictionaryValue(); | |
222 UpdateVersionInfo(*it, info); | |
223 result->Append(info); | |
224 } | |
225 return result; | |
226 } | |
227 | |
228 void GetRegistrationsOnIOThread( | |
229 scoped_refptr<ServiceWorkerContextWrapper> context, | |
230 base::Callback<void(const std::vector<ServiceWorkerRegistrationInfo>&)> | |
231 callback) { | |
232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
233 context->context()->storage()->GetAllRegistrations(callback); | |
234 } | |
235 | |
236 void OnStoredRegistrations( | |
237 scoped_refptr<ServiceWorkerContextWrapper> context, | |
238 base::Callback<void(const std::vector<ServiceWorkerRegistrationInfo>&, | |
239 const std::vector<ServiceWorkerVersionInfo>&, | |
240 const std::vector<ServiceWorkerRegistrationInfo>&)> | |
241 callback, | |
242 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) { | |
243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
244 BrowserThread::PostTask( | |
245 BrowserThread::UI, | |
246 FROM_HERE, | |
247 base::Bind(callback, | |
248 context->context()->GetAllLiveRegistrationInfo(), | |
249 context->context()->GetAllLiveVersionInfo(), | |
250 stored_registrations)); | |
251 } | |
252 | |
253 void OnAllRegistrations( | |
254 const WeakPtr<ServiceWorkerInternalsUI> internals, | |
falken
2014/05/28 08:21:40
const WeakPtr again
horo
2014/05/28 09:06:39
Done.
| |
255 int partition_id, | |
256 const base::FilePath& context_path, | |
257 const std::vector<ServiceWorkerRegistrationInfo>& live_registrations, | |
258 const std::vector<ServiceWorkerVersionInfo>& live_versions, | |
259 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) { | |
260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
261 if (!internals) | |
262 return; | |
263 | |
264 ScopedVector<const Value> args; | |
265 args.push_back(GetRegistrationListValue(live_registrations)); | |
266 args.push_back(GetVersionListValue(live_versions)); | |
267 args.push_back(GetRegistrationListValue(stored_registrations)); | |
268 args.push_back(new FundamentalValue(partition_id)); | |
269 args.push_back(new StringValue(context_path.value())); | |
270 internals->web_ui()->CallJavascriptFunction("serviceworker.onPartitionData", | |
271 args.get()); | |
272 } | |
273 | |
274 } // namespace | |
98 | 275 |
99 class ServiceWorkerInternalsUI::PartitionObserver | 276 class ServiceWorkerInternalsUI::PartitionObserver |
100 : public ServiceWorkerContextObserver { | 277 : public ServiceWorkerContextObserver { |
101 public: | 278 public: |
102 PartitionObserver(int partition_id, WebUI* web_ui) | 279 PartitionObserver(int partition_id, WebUI* web_ui) |
103 : partition_id_(partition_id), web_ui_(web_ui) {} | 280 : partition_id_(partition_id), web_ui_(web_ui) {} |
104 virtual ~PartitionObserver() {} | 281 virtual ~PartitionObserver() {} |
105 // ServiceWorkerContextObserver overrides: | 282 // ServiceWorkerContextObserver overrides: |
106 virtual void OnWorkerStarted(int64 version_id, | 283 virtual void OnWorkerStarted(int64 version_id, |
107 int process_id, | 284 int process_id, |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 | 379 |
203 BrowserContext* browser_context = | 380 BrowserContext* browser_context = |
204 web_ui->GetWebContents()->GetBrowserContext(); | 381 web_ui->GetWebContents()->GetBrowserContext(); |
205 WebUIDataSource::Add(browser_context, source); | 382 WebUIDataSource::Add(browser_context, source); |
206 | 383 |
207 web_ui->RegisterMessageCallback( | 384 web_ui->RegisterMessageCallback( |
208 "getAllRegistrations", | 385 "getAllRegistrations", |
209 base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations, | 386 base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations, |
210 base::Unretained(this))); | 387 base::Unretained(this))); |
211 web_ui->RegisterMessageCallback( | 388 web_ui->RegisterMessageCallback( |
212 "start", | 389 "stop", |
213 base::Bind(&ServiceWorkerInternalsUI::StartWorker, | 390 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod, |
214 base::Unretained(this))); | 391 base::Unretained(this), |
392 &ServiceWorkerVersion::StopWorker)); | |
215 web_ui->RegisterMessageCallback( | 393 web_ui->RegisterMessageCallback( |
216 "stop", | 394 "sync", |
217 base::Bind(&ServiceWorkerInternalsUI::StopWorker, | 395 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod, |
396 base::Unretained(this), | |
397 &ServiceWorkerVersion::DispatchSyncEvent)); | |
398 web_ui->RegisterMessageCallback( | |
399 "inspect", | |
400 base::Bind(&ServiceWorkerInternalsUI::InspectWorker, | |
218 base::Unretained(this))); | 401 base::Unretained(this))); |
219 web_ui->RegisterMessageCallback( | 402 web_ui->RegisterMessageCallback( |
220 "unregister", | 403 "unregister", |
221 base::Bind(&ServiceWorkerInternalsUI::Unregister, | 404 base::Bind(&ServiceWorkerInternalsUI::Unregister, |
222 base::Unretained(this))); | 405 base::Unretained(this))); |
223 web_ui->RegisterMessageCallback( | 406 web_ui->RegisterMessageCallback( |
224 "sync", | 407 "start", |
225 base::Bind(&ServiceWorkerInternalsUI::DispatchSyncEventToWorker, | 408 base::Bind(&ServiceWorkerInternalsUI::StartWorker, |
226 base::Unretained(this))); | |
227 web_ui->RegisterMessageCallback( | |
228 "inspect", | |
229 base::Bind(&ServiceWorkerInternalsUI::InspectWorker, | |
230 base::Unretained(this))); | 409 base::Unretained(this))); |
231 } | 410 } |
232 | 411 |
233 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() { | 412 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() { |
234 BrowserContext* browser_context = | 413 BrowserContext* browser_context = |
235 web_ui()->GetWebContents()->GetBrowserContext(); | 414 web_ui()->GetWebContents()->GetBrowserContext(); |
236 // Safe to use base::Unretained(this) because | 415 // Safe to use base::Unretained(this) because |
237 // ForEachStoragePartition is synchronous. | 416 // ForEachStoragePartition is synchronous. |
238 BrowserContext::StoragePartitionCallback remove_observer_cb = | 417 BrowserContext::StoragePartitionCallback remove_observer_cb = |
239 base::Bind(&ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition, | 418 base::Bind(&ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition, |
240 base::Unretained(this)); | 419 base::Unretained(this)); |
241 BrowserContext::ForEachStoragePartition(browser_context, remove_observer_cb); | 420 BrowserContext::ForEachStoragePartition(browser_context, remove_observer_cb); |
242 } | 421 } |
243 | 422 |
244 void ServiceWorkerInternalsUI::GetAllRegistrations(const ListValue* args) { | 423 void ServiceWorkerInternalsUI::GetAllRegistrations(const ListValue* args) { |
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
246 | |
247 BrowserContext* browser_context = | 425 BrowserContext* browser_context = |
248 web_ui()->GetWebContents()->GetBrowserContext(); | 426 web_ui()->GetWebContents()->GetBrowserContext(); |
249 | |
250 // Safe to use base::Unretained(this) because | 427 // Safe to use base::Unretained(this) because |
251 // ForEachStoragePartition is synchronous. | 428 // ForEachStoragePartition is synchronous. |
252 BrowserContext::StoragePartitionCallback add_context_cb = | 429 BrowserContext::StoragePartitionCallback add_context_cb = |
253 base::Bind(&ServiceWorkerInternalsUI::AddContextFromStoragePartition, | 430 base::Bind(&ServiceWorkerInternalsUI::AddContextFromStoragePartition, |
254 base::Unretained(this)); | 431 base::Unretained(this)); |
255 BrowserContext::ForEachStoragePartition(browser_context, add_context_cb); | 432 BrowserContext::ForEachStoragePartition(browser_context, add_context_cb); |
256 } | 433 } |
257 | 434 |
258 void ServiceWorkerInternalsUI::AddContextFromStoragePartition( | 435 void ServiceWorkerInternalsUI::AddContextFromStoragePartition( |
259 StoragePartition* partition) { | 436 StoragePartition* partition) { |
260 int partition_id = 0; | 437 int partition_id = 0; |
261 scoped_refptr<ServiceWorkerContextWrapper> context = | 438 scoped_refptr<ServiceWorkerContextWrapper> context = |
262 static_cast<ServiceWorkerContextWrapper*>( | 439 static_cast<ServiceWorkerContextWrapper*>( |
263 partition->GetServiceWorkerContext()); | 440 partition->GetServiceWorkerContext()); |
264 if (PartitionObserver* observer = | 441 if (PartitionObserver* observer = |
265 observers_.get(reinterpret_cast<uintptr_t>(partition))) { | 442 observers_.get(reinterpret_cast<uintptr_t>(partition))) { |
266 partition_id = observer->partition_id(); | 443 partition_id = observer->partition_id(); |
267 } else { | 444 } else { |
268 partition_id = next_partition_id_++; | 445 partition_id = next_partition_id_++; |
269 scoped_ptr<PartitionObserver> new_observer( | 446 scoped_ptr<PartitionObserver> new_observer( |
270 new PartitionObserver(partition_id, web_ui())); | 447 new PartitionObserver(partition_id, web_ui())); |
271 context->AddObserver(new_observer.get()); | 448 context->AddObserver(new_observer.get()); |
272 observers_.set(reinterpret_cast<uintptr_t>(partition), new_observer.Pass()); | 449 observers_.set(reinterpret_cast<uintptr_t>(partition), new_observer.Pass()); |
273 } | 450 } |
274 BrowserThread::PostTask( | 451 BrowserThread::PostTask( |
275 BrowserThread::IO, | 452 BrowserThread::IO, |
276 FROM_HERE, | 453 FROM_HERE, |
277 base::Bind( | 454 base::Bind(GetRegistrationsOnIOThread, |
278 &ServiceWorkerInternalsUI::OperationProxy::GetRegistrationsOnIOThread, | 455 context, |
279 new OperationProxy(AsWeakPtr(), scoped_ptr<ListValue>()), | 456 base::Bind(OnStoredRegistrations, |
280 partition_id, | 457 context, |
281 context, | 458 base::Bind(OnAllRegistrations, |
282 partition->GetPath())); | 459 AsWeakPtr(), |
460 partition_id, | |
461 partition->GetPath())))); | |
283 } | 462 } |
284 | 463 |
285 void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition( | 464 void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition( |
286 StoragePartition* partition) { | 465 StoragePartition* partition) { |
287 scoped_ptr<PartitionObserver> observer( | 466 scoped_ptr<PartitionObserver> observer( |
288 observers_.take_and_erase(reinterpret_cast<uintptr_t>(partition))); | 467 observers_.take_and_erase(reinterpret_cast<uintptr_t>(partition))); |
289 if (!observer.get()) | 468 if (!observer.get()) |
290 return; | 469 return; |
291 scoped_refptr<ServiceWorkerContextWrapper> context = | 470 scoped_refptr<ServiceWorkerContextWrapper> context = |
292 static_cast<ServiceWorkerContextWrapper*>( | 471 static_cast<ServiceWorkerContextWrapper*>( |
293 partition->GetServiceWorkerContext()); | 472 partition->GetServiceWorkerContext()); |
294 context->RemoveObserver(observer.get()); | 473 context->RemoveObserver(observer.get()); |
295 } | 474 } |
296 | 475 |
297 namespace { | 476 void ServiceWorkerInternalsUI::FindContext( |
298 void FindContext(const base::FilePath& partition_path, | 477 int partition_id, |
299 StoragePartition** result_partition, | 478 StoragePartition** result_partition, |
300 scoped_refptr<ServiceWorkerContextWrapper>* result_context, | 479 StoragePartition* storage_partition) const { |
301 StoragePartition* storage_partition) { | 480 PartitionObserver* observer = |
302 if (storage_partition->GetPath() == partition_path) { | 481 observers_.get(reinterpret_cast<uintptr_t>(storage_partition)); |
482 if (observer && partition_id == observer->partition_id()) { | |
303 *result_partition = storage_partition; | 483 *result_partition = storage_partition; |
304 *result_context = static_cast<ServiceWorkerContextWrapper*>( | |
305 storage_partition->GetServiceWorkerContext()); | |
306 } | 484 } |
307 } | 485 } |
308 } // namespace | |
309 | 486 |
310 bool ServiceWorkerInternalsUI::GetRegistrationInfo( | 487 bool ServiceWorkerInternalsUI::GetServiceWorkerContext( |
311 const ListValue* args, | 488 int partition_id, |
312 base::FilePath* partition_path, | |
313 GURL* scope, | |
314 scoped_refptr<ServiceWorkerContextWrapper>* context) const { | 489 scoped_refptr<ServiceWorkerContextWrapper>* context) const { |
315 base::FilePath::StringType path_string; | |
316 if (!args->GetString(0, &path_string)) | |
317 return false; | |
318 *partition_path = base::FilePath(path_string); | |
319 | |
320 std::string scope_string; | |
321 if (!args->GetString(1, &scope_string)) | |
322 return false; | |
323 *scope = GURL(scope_string); | |
324 | |
325 BrowserContext* browser_context = | 490 BrowserContext* browser_context = |
326 web_ui()->GetWebContents()->GetBrowserContext(); | 491 web_ui()->GetWebContents()->GetBrowserContext(); |
327 | |
328 StoragePartition* result_partition(NULL); | 492 StoragePartition* result_partition(NULL); |
329 BrowserContext::StoragePartitionCallback find_context_cb = | 493 BrowserContext::StoragePartitionCallback find_context_cb = |
330 base::Bind(&FindContext, *partition_path, &result_partition, context); | 494 base::Bind(&ServiceWorkerInternalsUI::FindContext, |
495 base::Unretained(this), | |
496 partition_id, | |
497 &result_partition); | |
331 BrowserContext::ForEachStoragePartition(browser_context, find_context_cb); | 498 BrowserContext::ForEachStoragePartition(browser_context, find_context_cb); |
332 | 499 if (!result_partition) |
333 if (!result_partition || !(*context)) | |
334 return false; | 500 return false; |
335 | 501 *context = static_cast<ServiceWorkerContextWrapper*>( |
502 result_partition->GetServiceWorkerContext()); | |
336 return true; | 503 return true; |
337 } | 504 } |
338 | 505 |
339 void ServiceWorkerInternalsUI::DispatchSyncEventToWorker( | 506 void ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod( |
507 ServiceWorkerVersionMethod method, | |
340 const ListValue* args) { | 508 const ListValue* args) { |
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 509 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
342 base::FilePath partition_path; | 510 int callback_id; |
343 GURL scope; | 511 int partition_id; |
512 int64 version_id; | |
513 std::string version_id_string; | |
514 const DictionaryValue* cmd_args = NULL; | |
344 scoped_refptr<ServiceWorkerContextWrapper> context; | 515 scoped_refptr<ServiceWorkerContextWrapper> context; |
345 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) | 516 if (!args->GetInteger(0, &callback_id) || |
517 !args->GetDictionary(1, &cmd_args) || | |
518 !cmd_args->GetInteger("partition_id", &partition_id) || | |
519 !GetServiceWorkerContext(partition_id, &context) || | |
520 !cmd_args->GetString("version_id", &version_id_string) || | |
521 !base::StringToInt64(version_id_string, &version_id)) { | |
346 return; | 522 return; |
523 } | |
347 | 524 |
348 scoped_ptr<ListValue> args_copy(args->DeepCopy()); | 525 base::Callback<void(ServiceWorkerStatusCode)> callback = |
349 BrowserThread::PostTask( | 526 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id); |
350 BrowserThread::IO, | 527 CallServiceWorkerVersionMethodWithVersionID( |
351 FROM_HERE, | 528 method, context, version_id, callback); |
352 base::Bind(&ServiceWorkerInternalsUI::OperationProxy:: | |
353 DispatchSyncEventToWorkerOnIOThread, | |
354 new OperationProxy(AsWeakPtr(), args_copy.Pass()), | |
355 context, | |
356 scope)); | |
357 } | 529 } |
358 | 530 |
359 void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) { | 531 void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) { |
360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
361 base::FilePath partition_path; | 533 int callback_id; |
362 GURL scope; | 534 int process_id; |
535 int devtools_agent_route_id; | |
536 const DictionaryValue* cmd_args = NULL; | |
363 scoped_refptr<ServiceWorkerContextWrapper> context; | 537 scoped_refptr<ServiceWorkerContextWrapper> context; |
364 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) | 538 if (!args->GetInteger(0, &callback_id) || |
539 !args->GetDictionary(1, &cmd_args) || | |
540 !cmd_args->GetInteger("process_id", &process_id) || | |
541 !cmd_args->GetInteger("devtools_agent_route_id", | |
542 &devtools_agent_route_id)) { | |
365 return; | 543 return; |
366 scoped_ptr<ListValue> args_copy(args->DeepCopy()); | 544 } |
367 BrowserThread::PostTask( | 545 base::Callback<void(ServiceWorkerStatusCode)> callback = |
368 BrowserThread::IO, | 546 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id); |
369 FROM_HERE, | 547 scoped_refptr<DevToolsAgentHost> agent_host( |
370 base::Bind( | 548 EmbeddedWorkerDevToolsManager::GetInstance() |
371 &ServiceWorkerInternalsUI::OperationProxy::InspectWorkerOnIOThread, | 549 ->GetDevToolsAgentHostForWorker(process_id, devtools_agent_route_id)); |
372 new OperationProxy(AsWeakPtr(), args_copy.Pass()), | 550 if (!agent_host) { |
373 context, | 551 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND); |
374 scope)); | 552 return; |
553 } | |
554 DevToolsManagerImpl::GetInstance()->Inspect( | |
555 web_ui()->GetWebContents()->GetBrowserContext(), agent_host.get()); | |
556 callback.Run(SERVICE_WORKER_OK); | |
375 } | 557 } |
376 | 558 |
377 void ServiceWorkerInternalsUI::Unregister(const ListValue* args) { | 559 void ServiceWorkerInternalsUI::Unregister(const ListValue* args) { |
378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 560 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
379 base::FilePath partition_path; | 561 int callback_id; |
380 GURL scope; | 562 int partition_id; |
563 std::string scope_string; | |
564 const DictionaryValue* cmd_args = NULL; | |
381 scoped_refptr<ServiceWorkerContextWrapper> context; | 565 scoped_refptr<ServiceWorkerContextWrapper> context; |
382 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) | 566 if (!args->GetInteger(0, &callback_id) || |
567 !args->GetDictionary(1, &cmd_args) || | |
568 !cmd_args->GetInteger("partition_id", &partition_id) || | |
569 !GetServiceWorkerContext(partition_id, &context) || | |
570 !cmd_args->GetString("scope", &scope_string)) { | |
383 return; | 571 return; |
572 } | |
384 | 573 |
385 scoped_ptr<ListValue> args_copy(args->DeepCopy()); | 574 base::Callback<void(ServiceWorkerStatusCode)> callback = |
386 BrowserThread::PostTask( | 575 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id); |
387 BrowserThread::IO, | 576 UnregisterWithScope(context, GURL(scope_string), callback); |
388 FROM_HERE, | |
389 base::Bind( | |
390 &ServiceWorkerInternalsUI::OperationProxy::UnregisterOnIOThread, | |
391 new OperationProxy(AsWeakPtr(), args_copy.Pass()), | |
392 context, | |
393 scope)); | |
394 } | 577 } |
395 | 578 |
396 void ServiceWorkerInternalsUI::StartWorker(const ListValue* args) { | 579 void ServiceWorkerInternalsUI::StartWorker(const ListValue* args) { |
397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 580 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
398 base::FilePath partition_path; | 581 int callback_id; |
399 GURL scope; | 582 int partition_id; |
583 std::string scope_string; | |
584 const DictionaryValue* cmd_args = NULL; | |
400 scoped_refptr<ServiceWorkerContextWrapper> context; | 585 scoped_refptr<ServiceWorkerContextWrapper> context; |
401 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) | 586 if (!args->GetInteger(0, &callback_id) || |
402 return; | 587 !args->GetDictionary(1, &cmd_args) || |
403 | 588 !cmd_args->GetInteger("partition_id", &partition_id) || |
404 scoped_ptr<ListValue> args_copy(args->DeepCopy()); | 589 !GetServiceWorkerContext(partition_id, &context) || |
405 BrowserThread::PostTask( | 590 !cmd_args->GetString("scope", &scope_string)) { |
406 BrowserThread::IO, | |
407 FROM_HERE, | |
408 base::Bind( | |
409 &ServiceWorkerInternalsUI::OperationProxy::StartWorkerOnIOThread, | |
410 new OperationProxy(AsWeakPtr(), args_copy.Pass()), | |
411 context, | |
412 scope)); | |
413 } | |
414 | |
415 void ServiceWorkerInternalsUI::StopWorker(const ListValue* args) { | |
416 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
417 base::FilePath partition_path; | |
418 GURL scope; | |
419 scoped_refptr<ServiceWorkerContextWrapper> context; | |
420 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) | |
421 return; | |
422 | |
423 scoped_ptr<ListValue> args_copy(args->DeepCopy()); | |
424 BrowserThread::PostTask( | |
425 BrowserThread::IO, | |
426 FROM_HERE, | |
427 base::Bind( | |
428 &ServiceWorkerInternalsUI::OperationProxy::StopWorkerOnIOThread, | |
429 new OperationProxy(AsWeakPtr(), args_copy.Pass()), | |
430 context, | |
431 scope)); | |
432 } | |
433 | |
434 void ServiceWorkerInternalsUI::OperationProxy::GetRegistrationsOnIOThread( | |
435 int partition_id, | |
436 ServiceWorkerContextWrapper* context, | |
437 const base::FilePath& context_path) { | |
438 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
439 | |
440 context->context()->storage()->GetAllRegistrations( | |
441 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::OnHaveRegistrations, | |
442 this, | |
443 partition_id, | |
444 context_path)); | |
445 } | |
446 | |
447 void ServiceWorkerInternalsUI::OperationProxy::UnregisterOnIOThread( | |
448 scoped_refptr<ServiceWorkerContextWrapper> context, | |
449 const GURL& scope) { | |
450 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
451 context->context()->UnregisterServiceWorker( | |
452 scope, | |
453 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::OperationComplete, | |
454 this)); | |
455 } | |
456 | |
457 void ServiceWorkerInternalsUI::OperationProxy::StartWorkerOnIOThread( | |
458 scoped_refptr<ServiceWorkerContextWrapper> context, | |
459 const GURL& scope) { | |
460 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
461 // TODO(alecflett): Add support for starting/stopping workers for | |
462 // pending versions too. | |
463 context->context()->storage()->FindRegistrationForPattern( | |
464 scope, | |
465 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::StartActiveWorker, | |
466 this)); | |
467 } | |
468 | |
469 void ServiceWorkerInternalsUI::OperationProxy::StopWorkerOnIOThread( | |
470 scoped_refptr<ServiceWorkerContextWrapper> context, | |
471 const GURL& scope) { | |
472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
473 // TODO(alecflett): Add support for starting/stopping workers for | |
474 // pending versions too. | |
475 context->context()->storage()->FindRegistrationForPattern( | |
476 scope, | |
477 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::StopActiveWorker, | |
478 this)); | |
479 } | |
480 | |
481 void | |
482 ServiceWorkerInternalsUI::OperationProxy::DispatchSyncEventToWorkerOnIOThread( | |
483 scoped_refptr<ServiceWorkerContextWrapper> context, | |
484 const GURL& scope) { | |
485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
486 context->context()->storage()->FindRegistrationForPattern( | |
487 scope, | |
488 base::Bind(&ServiceWorkerInternalsUI::OperationProxy:: | |
489 DispatchSyncEventToActiveWorker, | |
490 this)); | |
491 } | |
492 | |
493 void ServiceWorkerInternalsUI::OperationProxy::InspectWorkerOnIOThread( | |
494 scoped_refptr<ServiceWorkerContextWrapper> context, | |
495 const GURL& scope) { | |
496 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
497 context->context()->storage()->FindRegistrationForPattern( | |
498 scope, | |
499 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::InspectActiveWorker, | |
500 this, | |
501 context->context())); | |
502 } | |
503 | |
504 namespace { | |
505 void UpdateVersionInfo(const ServiceWorkerVersionInfo& version, | |
506 DictionaryValue* info) { | |
507 switch (version.running_status) { | |
508 case ServiceWorkerVersion::STOPPED: | |
509 info->SetString("running_status", "STOPPED"); | |
510 break; | |
511 case ServiceWorkerVersion::STARTING: | |
512 info->SetString("running_status", "STARTING"); | |
513 break; | |
514 case ServiceWorkerVersion::RUNNING: | |
515 info->SetString("running_status", "RUNNING"); | |
516 break; | |
517 case ServiceWorkerVersion::STOPPING: | |
518 info->SetString("running_status", "STOPPING"); | |
519 break; | |
520 } | |
521 | |
522 switch (version.status) { | |
523 case ServiceWorkerVersion::NEW: | |
524 info->SetString("status", "NEW"); | |
525 break; | |
526 case ServiceWorkerVersion::INSTALLING: | |
527 info->SetString("status", "INSTALLING"); | |
528 break; | |
529 case ServiceWorkerVersion::INSTALLED: | |
530 info->SetString("status", "INSTALLED"); | |
531 break; | |
532 case ServiceWorkerVersion::ACTIVATING: | |
533 info->SetString("status", "ACTIVATING"); | |
534 break; | |
535 case ServiceWorkerVersion::ACTIVE: | |
536 info->SetString("status", "ACTIVE"); | |
537 break; | |
538 case ServiceWorkerVersion::DEACTIVATED: | |
539 info->SetString("status", "DEACTIVATED"); | |
540 break; | |
541 } | |
542 info->SetString("version_id", base::Int64ToString(version.version_id)); | |
543 info->SetInteger("process_id", version.process_id); | |
544 info->SetInteger("thread_id", version.thread_id); | |
545 } | |
546 } // namespace | |
547 | |
548 void ServiceWorkerInternalsUI::OperationProxy::OnHaveRegistrations( | |
549 int partition_id, | |
550 const base::FilePath& context_path, | |
551 const std::vector<ServiceWorkerRegistrationInfo>& registrations) { | |
552 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
553 BrowserThread::PostTask( | |
554 BrowserThread::UI, | |
555 FROM_HERE, | |
556 base::Bind( | |
557 &ServiceWorkerInternalsUI::OperationProxy::OnHaveRegistrations, | |
558 this, | |
559 partition_id, | |
560 context_path, | |
561 registrations)); | |
562 return; | 591 return; |
563 } | 592 } |
564 | 593 |
565 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 594 base::Callback<void(ServiceWorkerStatusCode)> callback = |
566 ListValue result; | 595 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id); |
567 for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it = | 596 FindRegistrationForPattern( |
568 registrations.begin(); | 597 context, GURL(scope_string), base::Bind(StartActiveWorker, callback)); |
569 it != registrations.end(); | |
570 ++it) { | |
571 const ServiceWorkerRegistrationInfo& registration = *it; | |
572 DictionaryValue* registration_info = new DictionaryValue(); | |
573 registration_info->SetString("scope", registration.pattern.spec()); | |
574 registration_info->SetString("script_url", registration.script_url.spec()); | |
575 | |
576 if (!registration.active_version.is_null) { | |
577 DictionaryValue* active_info = new DictionaryValue(); | |
578 UpdateVersionInfo(registration.active_version, active_info); | |
579 registration_info->Set("active", active_info); | |
580 } | |
581 | |
582 if (!registration.pending_version.is_null) { | |
583 DictionaryValue* pending_info = new DictionaryValue(); | |
584 UpdateVersionInfo(registration.pending_version, pending_info); | |
585 registration_info->Set("pending", pending_info); | |
586 } | |
587 | |
588 result.Append(registration_info); | |
589 } | |
590 | |
591 if (internals_) | |
592 internals_->web_ui()->CallJavascriptFunction( | |
593 "serviceworker.onPartitionData", | |
594 result, | |
595 FundamentalValue(partition_id), | |
596 StringValue(context_path.value())); | |
597 } | |
598 | |
599 void ServiceWorkerInternalsUI::OperationProxy::OperationComplete( | |
600 ServiceWorkerStatusCode status) { | |
601 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
602 BrowserThread::PostTask( | |
603 BrowserThread::UI, | |
604 FROM_HERE, | |
605 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::OperationComplete, | |
606 this, | |
607 status)); | |
608 return; | |
609 } | |
610 | |
611 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
612 original_args_->Insert(0, new FundamentalValue(static_cast<int>(status))); | |
613 if (internals_) | |
614 internals_->web_ui()->CallJavascriptFunction( | |
615 "serviceworker.onOperationComplete", | |
616 std::vector<const Value*>(original_args_->begin(), | |
617 original_args_->end())); | |
618 } | |
619 | |
620 void ServiceWorkerInternalsUI::OperationProxy::StartActiveWorker( | |
621 ServiceWorkerStatusCode status, | |
622 const scoped_refptr<ServiceWorkerRegistration>& registration) { | |
623 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
624 if (status == SERVICE_WORKER_OK) { | |
625 registration->active_version()->StartWorker(base::Bind( | |
626 &ServiceWorkerInternalsUI::OperationProxy::OperationComplete, this)); | |
627 return; | |
628 } | |
629 | |
630 OperationComplete(status); | |
631 } | |
632 | |
633 void ServiceWorkerInternalsUI::OperationProxy::StopActiveWorker( | |
634 ServiceWorkerStatusCode status, | |
635 const scoped_refptr<ServiceWorkerRegistration>& registration) { | |
636 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
637 if (status == SERVICE_WORKER_OK) { | |
638 registration->active_version()->StopWorker(base::Bind( | |
639 &ServiceWorkerInternalsUI::OperationProxy::OperationComplete, this)); | |
640 return; | |
641 } | |
642 | |
643 OperationComplete(status); | |
644 } | |
645 | |
646 void ServiceWorkerInternalsUI::OperationProxy::DispatchSyncEventToActiveWorker( | |
647 ServiceWorkerStatusCode status, | |
648 const scoped_refptr<ServiceWorkerRegistration>& registration) { | |
649 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
650 if (status == SERVICE_WORKER_OK && registration->active_version() && | |
651 registration->active_version()->status() == | |
652 ServiceWorkerVersion::ACTIVE) { | |
653 registration->active_version()->DispatchSyncEvent(base::Bind( | |
654 &ServiceWorkerInternalsUI::OperationProxy::OperationComplete, this)); | |
655 return; | |
656 } | |
657 | |
658 OperationComplete(SERVICE_WORKER_ERROR_FAILED); | |
659 } | |
660 | |
661 void ServiceWorkerInternalsUI::OperationProxy::InspectActiveWorker( | |
662 const ServiceWorkerContextCore* const service_worker_context, | |
663 ServiceWorkerStatusCode status, | |
664 const scoped_refptr<ServiceWorkerRegistration>& registration) { | |
665 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
666 if (status == SERVICE_WORKER_OK) { | |
667 BrowserThread::PostTask( | |
668 BrowserThread::UI, | |
669 FROM_HERE, | |
670 base::Bind(&OperationProxy::InspectWorkerOnUIThread, | |
671 this, | |
672 service_worker_context, | |
673 registration->active_version()->version_id())); | |
674 return; | |
675 } | |
676 | |
677 OperationComplete(status); | |
678 } | |
679 | |
680 void ServiceWorkerInternalsUI::OperationProxy::InspectWorkerOnUIThread( | |
681 const ServiceWorkerContextCore* const service_worker_context, | |
682 int64 version_id) { | |
683 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
684 scoped_refptr<DevToolsAgentHost> agent_host( | |
685 EmbeddedWorkerDevToolsManager::GetInstance() | |
686 ->GetDevToolsAgentHostForServiceWorker( | |
687 EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier( | |
688 service_worker_context, version_id))); | |
689 if (agent_host) { | |
690 DevToolsManagerImpl::GetInstance()->Inspect( | |
691 internals_->web_ui()->GetWebContents()->GetBrowserContext(), | |
692 agent_host.get()); | |
693 OperationComplete(SERVICE_WORKER_OK); | |
694 return; | |
695 } | |
696 OperationComplete(SERVICE_WORKER_ERROR_NOT_FOUND); | |
697 } | 598 } |
698 | 599 |
699 } // namespace content | 600 } // namespace content |
OLD | NEW |