service_worker_provider_host.cc revision 010d83a9304c5a91596085d917d248abff47903a
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 (pending_version_)
36    pending_version_->RemovePendingControllee(this);
37}
38
39void ServiceWorkerProviderHost::SetActiveVersion(
40    ServiceWorkerVersion* version) {
41  if (version == active_version_)
42    return;
43  scoped_refptr<ServiceWorkerVersion> previous_version = active_version_;
44  active_version_ = version;
45  if (version)
46    version->AddControllee(this);
47  if (previous_version)
48    previous_version->RemoveControllee(this);
49
50  if (!dispatcher_host_)
51    return;  // Could be NULL in some tests.
52
53  ServiceWorkerObjectInfo info;
54  if (context_ && version) {
55    scoped_ptr<ServiceWorkerHandle> handle =
56        ServiceWorkerHandle::Create(context_, dispatcher_host_,
57                                    kDocumentMainThreadId, version);
58    info = handle->GetObjectInfo();
59    dispatcher_host_->RegisterServiceWorkerHandle(handle.Pass());
60  }
61  dispatcher_host_->Send(
62      new ServiceWorkerMsg_SetCurrentServiceWorker(
63          kDocumentMainThreadId, provider_id(), info));
64}
65
66void ServiceWorkerProviderHost::SetPendingVersion(
67    ServiceWorkerVersion* version) {
68  if (version == pending_version_)
69    return;
70  scoped_refptr<ServiceWorkerVersion> previous_version = pending_version_;
71  pending_version_ = version;
72  if (version)
73    version->AddPendingControllee(this);
74  if (previous_version)
75    previous_version->RemovePendingControllee(this);
76
77  if (!dispatcher_host_)
78    return;  // Could be NULL in some tests.
79
80  // TODO(kinuko): dispatch pendingchange event to the document.
81}
82
83bool ServiceWorkerProviderHost::SetHostedVersionId(int64 version_id) {
84  if (!context_)
85    return true;  // System is shutting down.
86  if (active_version_)
87    return false;  // Unexpected bad message.
88
89  ServiceWorkerVersion* live_version = context_->GetLiveVersion(version_id);
90  if (!live_version)
91    return true;  // Was deleted before it got started.
92
93  ServiceWorkerVersionInfo info = live_version->GetInfo();
94  if (info.running_status != ServiceWorkerVersion::STARTING ||
95      info.process_id != process_id_) {
96    // If we aren't trying to start this version in our process
97    // something is amiss.
98    return false;
99  }
100
101  running_hosted_version_ = live_version;
102  return true;
103}
104
105scoped_ptr<ServiceWorkerRequestHandler>
106ServiceWorkerProviderHost::CreateRequestHandler(
107    ResourceType::Type resource_type) {
108  if (IsHostToRunningServiceWorker()) {
109    return scoped_ptr<ServiceWorkerRequestHandler>(
110        new ServiceWorkerContextRequestHandler(
111            context_, AsWeakPtr(), resource_type));
112  }
113  if (ServiceWorkerUtils::IsMainResourceType(resource_type) ||
114      active_version()) {
115    return scoped_ptr<ServiceWorkerRequestHandler>(
116        new ServiceWorkerControlleeRequestHandler(
117            context_, AsWeakPtr(), resource_type));
118  }
119  return scoped_ptr<ServiceWorkerRequestHandler>();
120}
121
122void ServiceWorkerProviderHost::PostMessage(
123    const base::string16& message,
124    const std::vector<int>& sent_message_port_ids) {
125  if (!dispatcher_host_)
126    return;  // Could be NULL in some tests.
127
128  std::vector<int> new_routing_ids;
129  dispatcher_host_->message_port_message_filter()->
130      UpdateMessagePortsWithNewRoutes(sent_message_port_ids,
131                                      &new_routing_ids);
132
133  dispatcher_host_->Send(
134      new ServiceWorkerMsg_MessageToDocument(
135          kDocumentMainThreadId, provider_id(),
136          message,
137          sent_message_port_ids,
138          new_routing_ids));
139}
140
141}  // namespace content
142