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 3// found in the LICENSE file. 4 5#include "content/child/service_worker/service_worker_provider_context.h" 6 7#include "base/bind.h" 8#include "base/message_loop/message_loop_proxy.h" 9#include "base/stl_util.h" 10#include "content/child/child_thread.h" 11#include "content/child/service_worker/service_worker_dispatcher.h" 12#include "content/child/service_worker/service_worker_handle_reference.h" 13#include "content/child/thread_safe_sender.h" 14#include "content/child/worker_task_runner.h" 15#include "content/common/service_worker/service_worker_messages.h" 16 17namespace content { 18 19ServiceWorkerProviderContext::ServiceWorkerProviderContext(int provider_id) 20 : provider_id_(provider_id), 21 main_thread_loop_proxy_(base::MessageLoopProxy::current()) { 22 if (!ChildThread::current()) 23 return; // May be null in some tests. 24 thread_safe_sender_ = ChildThread::current()->thread_safe_sender(); 25 ServiceWorkerDispatcher* dispatcher = 26 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance( 27 thread_safe_sender_); 28 DCHECK(dispatcher); 29 dispatcher->AddProviderContext(this); 30} 31 32ServiceWorkerProviderContext::~ServiceWorkerProviderContext() { 33 if (ServiceWorkerDispatcher* dispatcher = 34 ServiceWorkerDispatcher::GetThreadSpecificInstance()) { 35 dispatcher->RemoveProviderContext(this); 36 } 37} 38 39ServiceWorkerHandleReference* ServiceWorkerProviderContext::waiting() { 40 DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread()); 41 return waiting_.get(); 42} 43 44ServiceWorkerHandleReference* ServiceWorkerProviderContext::current() { 45 DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread()); 46 return current_.get(); 47} 48 49void ServiceWorkerProviderContext::OnServiceWorkerStateChanged( 50 int handle_id, 51 blink::WebServiceWorkerState state) { 52 ServiceWorkerHandleReference* which = NULL; 53 if (handle_id == current_handle_id()) { 54 which = current_.get(); 55 } else if (handle_id == waiting_handle_id()) { 56 which = waiting_.get(); 57 } 58 59 // We should only get messages for ServiceWorkers associated with 60 // this provider. 61 DCHECK(which); 62 63 which->set_state(state); 64 65 // TODO(kinuko): We can forward the message to other threads here 66 // when we support navigator.serviceWorker in dedicated workers. 67} 68 69void ServiceWorkerProviderContext::OnSetWaitingServiceWorker( 70 int provider_id, 71 const ServiceWorkerObjectInfo& info) { 72 DCHECK_EQ(provider_id_, provider_id); 73 waiting_ = ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_); 74} 75 76void ServiceWorkerProviderContext::OnSetCurrentServiceWorker( 77 int provider_id, 78 const ServiceWorkerObjectInfo& info) { 79 DCHECK_EQ(provider_id_, provider_id); 80 81 // This context is is the primary owner of this handle, keeps the 82 // initial reference until it goes away. 83 current_ = ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_); 84 85 // TODO(kinuko): We can forward the message to other threads here 86 // when we support navigator.serviceWorker in dedicated workers. 87} 88 89int ServiceWorkerProviderContext::current_handle_id() const { 90 DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread()); 91 return current_ ? current_->info().handle_id : kInvalidServiceWorkerHandleId; 92} 93 94int ServiceWorkerProviderContext::waiting_handle_id() const { 95 DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread()); 96 return waiting_ ? waiting_->info().handle_id : kInvalidServiceWorkerHandleId; 97} 98 99} // namespace content 100