Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_version.cc
blob0bffa65e38aa767b9eb45143190cea453250072d
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
3 // found in the LICENSE file.
5 #include "content/browser/service_worker/service_worker_version.h"
7 #include "base/command_line.h"
8 #include "base/stl_util.h"
9 #include "base/strings/string16.h"
10 #include "content/browser/service_worker/embedded_worker_instance.h"
11 #include "content/browser/service_worker/embedded_worker_registry.h"
12 #include "content/browser/service_worker/service_worker_context_core.h"
13 #include "content/browser/service_worker/service_worker_registration.h"
14 #include "content/browser/service_worker/service_worker_utils.h"
15 #include "content/common/service_worker/service_worker_messages.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/common/content_switches.h"
19 namespace content {
21 typedef ServiceWorkerVersion::StatusCallback StatusCallback;
22 typedef ServiceWorkerVersion::MessageCallback MessageCallback;
24 namespace {
26 // Default delay for scheduled stop.
27 // (Note that if all references to the version is dropped the worker
28 // is also stopped without delay)
29 const int64 kStopWorkerDelay = 30; // 30 secs.
31 // Default delay for scheduled update.
32 const int kUpdateDelaySeconds = 10;
34 void RunSoon(const base::Closure& callback) {
35 if (!callback.is_null())
36 base::MessageLoop::current()->PostTask(FROM_HERE, callback);
39 template <typename CallbackArray, typename Arg>
40 void RunCallbacks(ServiceWorkerVersion* version,
41 CallbackArray* callbacks_ptr,
42 const Arg& arg) {
43 CallbackArray callbacks;
44 callbacks.swap(*callbacks_ptr);
45 scoped_refptr<ServiceWorkerVersion> protect(version);
46 for (typename CallbackArray::const_iterator i = callbacks.begin();
47 i != callbacks.end(); ++i)
48 (*i).Run(arg);
51 template <typename IDMAP, typename Method, typename Params>
52 void RunIDMapCallbacks(IDMAP* callbacks, Method method, const Params& params) {
53 typename IDMAP::iterator iter(callbacks);
54 while (!iter.IsAtEnd()) {
55 DispatchToMethod(iter.GetCurrentValue(), method, params);
56 iter.Advance();
58 callbacks->Clear();
61 // A callback adapter to start a |task| after StartWorker.
62 void RunTaskAfterStartWorker(
63 base::WeakPtr<ServiceWorkerVersion> version,
64 const StatusCallback& error_callback,
65 const base::Closure& task,
66 ServiceWorkerStatusCode status) {
67 if (status != SERVICE_WORKER_OK) {
68 if (!error_callback.is_null())
69 error_callback.Run(status);
70 return;
72 if (version->running_status() != ServiceWorkerVersion::RUNNING) {
73 // We've tried to start the worker (and it has succeeded), but
74 // it looks it's not running yet.
75 NOTREACHED() << "The worker's not running after successful StartWorker";
76 if (!error_callback.is_null())
77 error_callback.Run(SERVICE_WORKER_ERROR_START_WORKER_FAILED);
78 return;
80 task.Run();
83 void RunErrorFetchCallback(const ServiceWorkerVersion::FetchCallback& callback,
84 ServiceWorkerStatusCode status) {
85 callback.Run(status,
86 SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
87 ServiceWorkerResponse());
90 } // namespace
92 ServiceWorkerVersion::ServiceWorkerVersion(
93 ServiceWorkerRegistration* registration,
94 const GURL& script_url,
95 int64 version_id,
96 base::WeakPtr<ServiceWorkerContextCore> context)
97 : version_id_(version_id),
98 registration_id_(kInvalidServiceWorkerVersionId),
99 script_url_(script_url),
100 status_(NEW),
101 context_(context),
102 script_cache_map_(this, context),
103 is_doomed_(false),
104 weak_factory_(this) {
105 DCHECK(context_);
106 DCHECK(registration);
107 if (registration) {
108 registration_id_ = registration->id();
109 scope_ = registration->pattern();
111 context_->AddLiveVersion(this);
112 embedded_worker_ = context_->embedded_worker_registry()->CreateWorker();
113 embedded_worker_->AddListener(this);
114 cache_listener_.reset(new ServiceWorkerCacheListener(this, context));
115 embedded_worker_->AddListener(cache_listener_.get());
118 ServiceWorkerVersion::~ServiceWorkerVersion() {
119 embedded_worker_->RemoveListener(this);
120 if (context_)
121 context_->RemoveLiveVersion(version_id_);
122 // EmbeddedWorker's dtor sends StopWorker if it's still running.
125 void ServiceWorkerVersion::SetStatus(Status status) {
126 if (status_ == status)
127 return;
129 // Schedule to stop worker after registration successfully completed.
130 if (status_ == ACTIVATING && status == ACTIVATED && !HasControllee())
131 ScheduleStopWorker();
133 status_ = status;
135 std::vector<base::Closure> callbacks;
136 callbacks.swap(status_change_callbacks_);
137 for (std::vector<base::Closure>::const_iterator i = callbacks.begin();
138 i != callbacks.end(); ++i) {
139 (*i).Run();
142 FOR_EACH_OBSERVER(Listener, listeners_, OnVersionStateChanged(this));
145 void ServiceWorkerVersion::RegisterStatusChangeCallback(
146 const base::Closure& callback) {
147 status_change_callbacks_.push_back(callback);
150 ServiceWorkerVersionInfo ServiceWorkerVersion::GetInfo() {
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
152 return ServiceWorkerVersionInfo(
153 running_status(),
154 status(),
155 script_url(),
156 version_id(),
157 embedded_worker()->process_id(),
158 embedded_worker()->thread_id(),
159 embedded_worker()->worker_devtools_agent_route_id());
162 void ServiceWorkerVersion::StartWorker(const StatusCallback& callback) {
163 StartWorkerWithCandidateProcesses(std::vector<int>(), false, callback);
166 void ServiceWorkerVersion::StartWorkerWithCandidateProcesses(
167 const std::vector<int>& possible_process_ids,
168 bool pause_after_download,
169 const StatusCallback& callback) {
170 switch (running_status()) {
171 case RUNNING:
172 RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
173 return;
174 case STOPPING:
175 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED));
176 return;
177 case STOPPED:
178 case STARTING:
179 start_callbacks_.push_back(callback);
180 if (running_status() == STOPPED) {
181 embedded_worker_->Start(
182 version_id_,
183 scope_,
184 script_url_,
185 pause_after_download,
186 possible_process_ids,
187 base::Bind(&ServiceWorkerVersion::RunStartWorkerCallbacksOnError,
188 weak_factory_.GetWeakPtr()));
190 return;
194 void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) {
195 if (running_status() == STOPPED) {
196 RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
197 return;
199 if (stop_callbacks_.empty()) {
200 ServiceWorkerStatusCode status = embedded_worker_->Stop();
201 if (status != SERVICE_WORKER_OK) {
202 RunSoon(base::Bind(callback, status));
203 return;
206 stop_callbacks_.push_back(callback);
209 void ServiceWorkerVersion::ScheduleUpdate() {
210 if (update_timer_.IsRunning()) {
211 update_timer_.Reset();
212 return;
214 update_timer_.Start(
215 FROM_HERE, base::TimeDelta::FromSeconds(kUpdateDelaySeconds),
216 base::Bind(&ServiceWorkerVersion::StartUpdate,
217 weak_factory_.GetWeakPtr()));
220 void ServiceWorkerVersion::DeferScheduledUpdate() {
221 if (update_timer_.IsRunning())
222 update_timer_.Reset();
225 void ServiceWorkerVersion::StartUpdate() {
226 update_timer_.Stop();
227 if (!context_)
228 return;
229 ServiceWorkerRegistration* registration =
230 context_->GetLiveRegistration(registration_id_);
231 if (!registration || !registration->GetNewestVersion())
232 return;
233 context_->UpdateServiceWorker(registration);
236 void ServiceWorkerVersion::SendMessage(
237 const IPC::Message& message, const StatusCallback& callback) {
238 if (running_status() != RUNNING) {
239 // Schedule calling this method after starting the worker.
240 StartWorker(base::Bind(&RunTaskAfterStartWorker,
241 weak_factory_.GetWeakPtr(), callback,
242 base::Bind(&self::SendMessage,
243 weak_factory_.GetWeakPtr(),
244 message, callback)));
245 return;
248 ServiceWorkerStatusCode status = embedded_worker_->SendMessage(message);
249 RunSoon(base::Bind(callback, status));
252 void ServiceWorkerVersion::DispatchInstallEvent(
253 int active_version_id,
254 const StatusCallback& callback) {
255 DCHECK_EQ(INSTALLING, status()) << status();
257 if (running_status() != RUNNING) {
258 // Schedule calling this method after starting the worker.
259 StartWorker(
260 base::Bind(&RunTaskAfterStartWorker,
261 weak_factory_.GetWeakPtr(),
262 callback,
263 base::Bind(&self::DispatchInstallEventAfterStartWorker,
264 weak_factory_.GetWeakPtr(),
265 active_version_id,
266 callback)));
267 } else {
268 DispatchInstallEventAfterStartWorker(active_version_id, callback);
272 void ServiceWorkerVersion::DispatchActivateEvent(
273 const StatusCallback& callback) {
274 DCHECK_EQ(ACTIVATING, status()) << status();
276 if (running_status() != RUNNING) {
277 // Schedule calling this method after starting the worker.
278 StartWorker(
279 base::Bind(&RunTaskAfterStartWorker,
280 weak_factory_.GetWeakPtr(),
281 callback,
282 base::Bind(&self::DispatchActivateEventAfterStartWorker,
283 weak_factory_.GetWeakPtr(),
284 callback)));
285 } else {
286 DispatchActivateEventAfterStartWorker(callback);
290 void ServiceWorkerVersion::DispatchFetchEvent(
291 const ServiceWorkerFetchRequest& request,
292 const base::Closure& prepare_callback,
293 const FetchCallback& fetch_callback) {
294 DCHECK_EQ(ACTIVATED, status()) << status();
296 if (running_status() != RUNNING) {
297 // Schedule calling this method after starting the worker.
298 StartWorker(base::Bind(&RunTaskAfterStartWorker,
299 weak_factory_.GetWeakPtr(),
300 base::Bind(&RunErrorFetchCallback, fetch_callback),
301 base::Bind(&self::DispatchFetchEvent,
302 weak_factory_.GetWeakPtr(),
303 request,
304 prepare_callback,
305 fetch_callback)));
306 return;
309 prepare_callback.Run();
311 int request_id = fetch_callbacks_.Add(new FetchCallback(fetch_callback));
312 ServiceWorkerStatusCode status = embedded_worker_->SendMessage(
313 ServiceWorkerMsg_FetchEvent(request_id, request));
314 if (status != SERVICE_WORKER_OK) {
315 fetch_callbacks_.Remove(request_id);
316 RunSoon(base::Bind(&RunErrorFetchCallback,
317 fetch_callback,
318 SERVICE_WORKER_ERROR_FAILED));
322 void ServiceWorkerVersion::DispatchSyncEvent(const StatusCallback& callback) {
323 DCHECK_EQ(ACTIVATED, status()) << status();
325 if (!CommandLine::ForCurrentProcess()->HasSwitch(
326 switches::kEnableServiceWorkerSync)) {
327 callback.Run(SERVICE_WORKER_ERROR_ABORT);
328 return;
331 if (running_status() != RUNNING) {
332 // Schedule calling this method after starting the worker.
333 StartWorker(base::Bind(&RunTaskAfterStartWorker,
334 weak_factory_.GetWeakPtr(), callback,
335 base::Bind(&self::DispatchSyncEvent,
336 weak_factory_.GetWeakPtr(),
337 callback)));
338 return;
341 int request_id = sync_callbacks_.Add(new StatusCallback(callback));
342 ServiceWorkerStatusCode status = embedded_worker_->SendMessage(
343 ServiceWorkerMsg_SyncEvent(request_id));
344 if (status != SERVICE_WORKER_OK) {
345 sync_callbacks_.Remove(request_id);
346 RunSoon(base::Bind(callback, status));
350 void ServiceWorkerVersion::DispatchPushEvent(const StatusCallback& callback,
351 const std::string& data) {
352 DCHECK_EQ(ACTIVATED, status()) << status();
354 if (!CommandLine::ForCurrentProcess()->HasSwitch(
355 switches::kEnableExperimentalWebPlatformFeatures)) {
356 callback.Run(SERVICE_WORKER_ERROR_ABORT);
357 return;
360 if (running_status() != RUNNING) {
361 // Schedule calling this method after starting the worker.
362 StartWorker(base::Bind(&RunTaskAfterStartWorker,
363 weak_factory_.GetWeakPtr(), callback,
364 base::Bind(&self::DispatchPushEvent,
365 weak_factory_.GetWeakPtr(),
366 callback, data)));
367 return;
370 int request_id = push_callbacks_.Add(new StatusCallback(callback));
371 ServiceWorkerStatusCode status = embedded_worker_->SendMessage(
372 ServiceWorkerMsg_PushEvent(request_id, data));
373 if (status != SERVICE_WORKER_OK) {
374 push_callbacks_.Remove(request_id);
375 RunSoon(base::Bind(callback, status));
379 void ServiceWorkerVersion::AddProcessToWorker(int process_id) {
380 embedded_worker_->AddProcessReference(process_id);
383 void ServiceWorkerVersion::RemoveProcessFromWorker(int process_id) {
384 embedded_worker_->ReleaseProcessReference(process_id);
387 bool ServiceWorkerVersion::HasProcessToRun() const {
388 return embedded_worker_->HasProcessToRun();
391 void ServiceWorkerVersion::AddControllee(
392 ServiceWorkerProviderHost* provider_host) {
393 DCHECK(!ContainsKey(controllee_map_, provider_host));
394 int controllee_id = controllee_by_id_.Add(provider_host);
395 controllee_map_[provider_host] = controllee_id;
396 AddProcessToWorker(provider_host->process_id());
397 if (stop_worker_timer_.IsRunning())
398 stop_worker_timer_.Stop();
401 void ServiceWorkerVersion::RemoveControllee(
402 ServiceWorkerProviderHost* provider_host) {
403 ControlleeMap::iterator found = controllee_map_.find(provider_host);
404 DCHECK(found != controllee_map_.end());
405 controllee_by_id_.Remove(found->second);
406 controllee_map_.erase(found);
407 RemoveProcessFromWorker(provider_host->process_id());
408 if (HasControllee())
409 return;
410 FOR_EACH_OBSERVER(Listener, listeners_, OnNoControllees(this));
411 if (is_doomed_) {
412 DoomInternal();
413 return;
415 ScheduleStopWorker();
418 void ServiceWorkerVersion::AddPotentialControllee(
419 ServiceWorkerProviderHost* provider_host) {
420 AddProcessToWorker(provider_host->process_id());
423 void ServiceWorkerVersion::RemovePotentialControllee(
424 ServiceWorkerProviderHost* provider_host) {
425 RemoveProcessFromWorker(provider_host->process_id());
428 void ServiceWorkerVersion::AddListener(Listener* listener) {
429 listeners_.AddObserver(listener);
432 void ServiceWorkerVersion::RemoveListener(Listener* listener) {
433 listeners_.RemoveObserver(listener);
436 void ServiceWorkerVersion::Doom() {
437 if (is_doomed_)
438 return;
439 is_doomed_ = true;
440 if (!HasControllee())
441 DoomInternal();
444 void ServiceWorkerVersion::OnStarted() {
445 DCHECK_EQ(RUNNING, running_status());
446 if (status() == ACTIVATED && !HasControllee())
447 ScheduleStopWorker();
448 // Fire all start callbacks.
449 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK);
450 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this));
453 void ServiceWorkerVersion::OnStopped() {
454 DCHECK_EQ(STOPPED, running_status());
455 scoped_refptr<ServiceWorkerVersion> protect(this);
457 // Fire all stop callbacks.
458 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK);
460 // Let all start callbacks fail.
461 RunCallbacks(
462 this, &start_callbacks_, SERVICE_WORKER_ERROR_START_WORKER_FAILED);
464 // Let all message callbacks fail (this will also fire and clear all
465 // callbacks for events).
466 // TODO(kinuko): Consider if we want to add queue+resend mechanism here.
467 RunIDMapCallbacks(&activate_callbacks_,
468 &StatusCallback::Run,
469 MakeTuple(SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED));
470 RunIDMapCallbacks(&install_callbacks_,
471 &StatusCallback::Run,
472 MakeTuple(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED));
473 RunIDMapCallbacks(&fetch_callbacks_,
474 &FetchCallback::Run,
475 MakeTuple(SERVICE_WORKER_ERROR_FAILED,
476 SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
477 ServiceWorkerResponse()));
478 RunIDMapCallbacks(&sync_callbacks_,
479 &StatusCallback::Run,
480 MakeTuple(SERVICE_WORKER_ERROR_FAILED));
481 RunIDMapCallbacks(&push_callbacks_,
482 &StatusCallback::Run,
483 MakeTuple(SERVICE_WORKER_ERROR_FAILED));
485 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStopped(this));
488 void ServiceWorkerVersion::OnReportException(
489 const base::string16& error_message,
490 int line_number,
491 int column_number,
492 const GURL& source_url) {
493 FOR_EACH_OBSERVER(
494 Listener,
495 listeners_,
496 OnErrorReported(
497 this, error_message, line_number, column_number, source_url));
500 void ServiceWorkerVersion::OnReportConsoleMessage(int source_identifier,
501 int message_level,
502 const base::string16& message,
503 int line_number,
504 const GURL& source_url) {
505 FOR_EACH_OBSERVER(Listener,
506 listeners_,
507 OnReportConsoleMessage(this,
508 source_identifier,
509 message_level,
510 message,
511 line_number,
512 source_url));
515 bool ServiceWorkerVersion::OnMessageReceived(const IPC::Message& message) {
516 bool handled = true;
517 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerVersion, message)
518 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetClientDocuments,
519 OnGetClientDocuments)
520 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ActivateEventFinished,
521 OnActivateEventFinished)
522 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_InstallEventFinished,
523 OnInstallEventFinished)
524 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FetchEventFinished,
525 OnFetchEventFinished)
526 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SyncEventFinished,
527 OnSyncEventFinished)
528 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished,
529 OnPushEventFinished)
530 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument,
531 OnPostMessageToDocument)
532 IPC_MESSAGE_UNHANDLED(handled = false)
533 IPC_END_MESSAGE_MAP()
534 return handled;
537 void ServiceWorkerVersion::RunStartWorkerCallbacksOnError(
538 ServiceWorkerStatusCode status) {
539 if (status != SERVICE_WORKER_OK)
540 RunCallbacks(this, &start_callbacks_, status);
543 void ServiceWorkerVersion::DispatchInstallEventAfterStartWorker(
544 int active_version_id,
545 const StatusCallback& callback) {
546 DCHECK_EQ(RUNNING, running_status())
547 << "Worker stopped too soon after it was started.";
549 int request_id = install_callbacks_.Add(new StatusCallback(callback));
550 ServiceWorkerStatusCode status = embedded_worker_->SendMessage(
551 ServiceWorkerMsg_InstallEvent(request_id, active_version_id));
552 if (status != SERVICE_WORKER_OK) {
553 install_callbacks_.Remove(request_id);
554 RunSoon(base::Bind(callback, status));
558 void ServiceWorkerVersion::DispatchActivateEventAfterStartWorker(
559 const StatusCallback& callback) {
560 DCHECK_EQ(RUNNING, running_status())
561 << "Worker stopped too soon after it was started.";
563 int request_id = activate_callbacks_.Add(new StatusCallback(callback));
564 ServiceWorkerStatusCode status =
565 embedded_worker_->SendMessage(ServiceWorkerMsg_ActivateEvent(request_id));
566 if (status != SERVICE_WORKER_OK) {
567 activate_callbacks_.Remove(request_id);
568 RunSoon(base::Bind(callback, status));
572 void ServiceWorkerVersion::OnGetClientDocuments(int request_id) {
573 std::vector<int> client_ids;
574 ControlleeByIDMap::iterator it(&controllee_by_id_);
575 while (!it.IsAtEnd()) {
576 client_ids.push_back(it.GetCurrentKey());
577 it.Advance();
579 // Don't bother if it's no longer running.
580 if (running_status() == RUNNING) {
581 embedded_worker_->SendMessage(
582 ServiceWorkerMsg_DidGetClientDocuments(request_id, client_ids));
586 void ServiceWorkerVersion::OnActivateEventFinished(
587 int request_id,
588 blink::WebServiceWorkerEventResult result) {
589 DCHECK(ACTIVATING == status() ||
590 REDUNDANT == status()) << status();
592 StatusCallback* callback = activate_callbacks_.Lookup(request_id);
593 if (!callback) {
594 NOTREACHED() << "Got unexpected message: " << request_id;
595 return;
597 ServiceWorkerStatusCode rv = SERVICE_WORKER_OK;
598 if (result == blink::WebServiceWorkerEventResultRejected ||
599 status() != ACTIVATING) {
600 rv = SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED;
603 scoped_refptr<ServiceWorkerVersion> protect(this);
604 callback->Run(rv);
605 activate_callbacks_.Remove(request_id);
608 void ServiceWorkerVersion::OnInstallEventFinished(
609 int request_id,
610 blink::WebServiceWorkerEventResult result) {
611 DCHECK_EQ(INSTALLING, status()) << status();
613 StatusCallback* callback = install_callbacks_.Lookup(request_id);
614 if (!callback) {
615 NOTREACHED() << "Got unexpected message: " << request_id;
616 return;
618 ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
619 if (result == blink::WebServiceWorkerEventResultRejected)
620 status = SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED;
622 scoped_refptr<ServiceWorkerVersion> protect(this);
623 callback->Run(status);
624 install_callbacks_.Remove(request_id);
627 void ServiceWorkerVersion::OnFetchEventFinished(
628 int request_id,
629 ServiceWorkerFetchEventResult result,
630 const ServiceWorkerResponse& response) {
631 FetchCallback* callback = fetch_callbacks_.Lookup(request_id);
632 if (!callback) {
633 NOTREACHED() << "Got unexpected message: " << request_id;
634 return;
637 scoped_refptr<ServiceWorkerVersion> protect(this);
638 callback->Run(SERVICE_WORKER_OK, result, response);
639 fetch_callbacks_.Remove(request_id);
642 void ServiceWorkerVersion::OnSyncEventFinished(
643 int request_id) {
644 StatusCallback* callback = sync_callbacks_.Lookup(request_id);
645 if (!callback) {
646 NOTREACHED() << "Got unexpected message: " << request_id;
647 return;
650 scoped_refptr<ServiceWorkerVersion> protect(this);
651 callback->Run(SERVICE_WORKER_OK);
652 sync_callbacks_.Remove(request_id);
655 void ServiceWorkerVersion::OnPushEventFinished(
656 int request_id) {
657 StatusCallback* callback = push_callbacks_.Lookup(request_id);
658 if (!callback) {
659 NOTREACHED() << "Got unexpected message: " << request_id;
660 return;
663 scoped_refptr<ServiceWorkerVersion> protect(this);
664 callback->Run(SERVICE_WORKER_OK);
665 push_callbacks_.Remove(request_id);
668 void ServiceWorkerVersion::OnPostMessageToDocument(
669 int client_id,
670 const base::string16& message,
671 const std::vector<int>& sent_message_port_ids) {
672 ServiceWorkerProviderHost* provider_host =
673 controllee_by_id_.Lookup(client_id);
674 if (!provider_host) {
675 // The client may already have been closed, just ignore.
676 return;
678 provider_host->PostMessage(message, sent_message_port_ids);
681 void ServiceWorkerVersion::ScheduleStopWorker() {
682 if (running_status() != RUNNING)
683 return;
684 if (stop_worker_timer_.IsRunning()) {
685 stop_worker_timer_.Reset();
686 return;
688 stop_worker_timer_.Start(
689 FROM_HERE, base::TimeDelta::FromSeconds(kStopWorkerDelay),
690 base::Bind(&ServiceWorkerVersion::StopWorker,
691 weak_factory_.GetWeakPtr(),
692 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)));
695 void ServiceWorkerVersion::DoomInternal() {
696 DCHECK(!HasControllee());
697 SetStatus(REDUNDANT);
698 StopWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
699 if (!context_)
700 return;
701 std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
702 script_cache_map_.GetResources(&resources);
703 context_->storage()->PurgeResources(resources);
706 } // namespace content