service_worker_provider_host.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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.
4
5#include "content/browser/service_worker/service_worker_provider_host.h"
6
7#include "base/stl_util.h"
8#include "content/browser/message_port_message_filter.h"
9#include "content/browser/service_worker/service_worker_context_core.h"
10#include "content/browser/service_worker/service_worker_context_request_handler.h"
11#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
12#include "content/browser/service_worker/service_worker_dispatcher_host.h"
13#include "content/browser/service_worker/service_worker_handle.h"
14#include "content/browser/service_worker/service_worker_utils.h"
15#include "content/browser/service_worker/service_worker_version.h"
16#include "content/common/service_worker/service_worker_messages.h"
17
18namespace content {
19
20static const int kDocumentMainThreadId = 0;
21
22ServiceWorkerProviderHost::ServiceWorkerProviderHost(
23    int process_id, int provider_id,
24    base::WeakPtr<ServiceWorkerContextCore> context,
25    ServiceWorkerDispatcherHost* dispatcher_host)
26    : process_id_(process_id),
27      provider_id_(provider_id),
28      context_(context),
29      dispatcher_host_(dispatcher_host) {
30}
31
32ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
33  if (active_version_)
34    active_version_->RemoveControllee(this);
35  if (waiting_version_)
36    waiting_version_->RemoveWaitingControllee(this);
37}
38
39void ServiceWorkerProviderHost::SetDocumentUrl(const GURL& url) {
40  DCHECK(!url.has_ref());
41  document_url_ = url;
42}
43
44void ServiceWorkerProviderHost::SetActiveVersion(
45    ServiceWorkerVersion* version) {
46  if (version == active_version_)
47    return;
48  scoped_refptr<ServiceWorkerVersion> previous_version = active_version_;
49  active_version_ = version;
50  if (version)
51    version->AddControllee(this);
52  if (previous_version)
53    previous_version->RemoveControllee(this);
54
55  if (!dispatcher_host_)
56    return;  // Could be NULL in some tests.
57
58  ServiceWorkerObjectInfo info;
59  if (context_ && version) {
60    scoped_ptr<ServiceWorkerHandle> handle =
61        ServiceWorkerHandle::Create(context_, dispatcher_host_,
62                                    kDocumentMainThreadId, version);
63    info = handle->GetObjectInfo();
64    dispatcher_host_->RegisterServiceWorkerHandle(handle.Pass());
65  }
66  dispatcher_host_->Send(
67      new ServiceWorkerMsg_SetCurrentServiceWorker(
68          kDocumentMainThreadId, provider_id(), info));
69}
70
71void ServiceWorkerProviderHost::SetWaitingVersion(
72    ServiceWorkerVersion* version) {
73  if (version == waiting_version_)
74    return;
75  scoped_refptr<ServiceWorkerVersion> previous_version = waiting_version_;
76  waiting_version_ = version;
77  if (version)
78    version->AddWaitingControllee(this);
79  if (previous_version)
80    previous_version->RemoveWaitingControllee(this);
81
82  if (!dispatcher_host_)
83    return;  // Could be NULL in some tests.
84
85  // TODO(kinuko): dispatch pendingchange event to the document.
86}
87
88bool ServiceWorkerProviderHost::SetHostedVersionId(int64 version_id) {
89  if (!context_)
90    return true;  // System is shutting down.
91  if (active_version_)
92    return false;  // Unexpected bad message.
93
94  ServiceWorkerVersion* live_version = context_->GetLiveVersion(version_id);
95  if (!live_version)
96    return true;  // Was deleted before it got started.
97
98  ServiceWorkerVersionInfo info = live_version->GetInfo();
99  if (info.running_status != ServiceWorkerVersion::STARTING ||
100      info.process_id != process_id_) {
101    // If we aren't trying to start this version in our process
102    // something is amiss.
103    return false;
104  }
105
106  running_hosted_version_ = live_version;
107  return true;
108}
109
110scoped_ptr<ServiceWorkerRequestHandler>
111ServiceWorkerProviderHost::CreateRequestHandler(
112    ResourceType::Type resource_type,
113    base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context) {
114  if (IsHostToRunningServiceWorker()) {
115    return scoped_ptr<ServiceWorkerRequestHandler>(
116        new ServiceWorkerContextRequestHandler(
117            context_, AsWeakPtr(), blob_storage_context, resource_type));
118  }
119  if (ServiceWorkerUtils::IsMainResourceType(resource_type) ||
120      active_version()) {
121    return scoped_ptr<ServiceWorkerRequestHandler>(
122        new ServiceWorkerControlleeRequestHandler(
123            context_, AsWeakPtr(), blob_storage_context, resource_type));
124  }
125  return scoped_ptr<ServiceWorkerRequestHandler>();
126}
127
128void ServiceWorkerProviderHost::PostMessage(
129    const base::string16& message,
130    const std::vector<int>& sent_message_port_ids) {
131  if (!dispatcher_host_)
132    return;  // Could be NULL in some tests.
133
134  std::vector<int> new_routing_ids;
135  dispatcher_host_->message_port_message_filter()->
136      UpdateMessagePortsWithNewRoutes(sent_message_port_ids,
137                                      &new_routing_ids);
138
139  dispatcher_host_->Send(
140      new ServiceWorkerMsg_MessageToDocument(
141          kDocumentMainThreadId, provider_id(),
142          message,
143          sent_message_port_ids,
144          new_routing_ids));
145}
146
147}  // namespace content
148