• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/embedded_worker_registry.h"
6 
7 #include "base/bind_helpers.h"
8 #include "base/stl_util.h"
9 #include "content/browser/renderer_host/render_widget_helper.h"
10 #include "content/browser/service_worker/embedded_worker_instance.h"
11 #include "content/browser/service_worker/service_worker_context_core.h"
12 #include "content/browser/service_worker/service_worker_context_wrapper.h"
13 #include "content/common/service_worker/embedded_worker_messages.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "ipc/ipc_message.h"
16 #include "ipc/ipc_sender.h"
17 
18 namespace content {
19 
EmbeddedWorkerRegistry(base::WeakPtr<ServiceWorkerContextCore> context)20 EmbeddedWorkerRegistry::EmbeddedWorkerRegistry(
21     base::WeakPtr<ServiceWorkerContextCore> context)
22     : context_(context), next_embedded_worker_id_(0) {
23 }
24 
CreateWorker()25 scoped_ptr<EmbeddedWorkerInstance> EmbeddedWorkerRegistry::CreateWorker() {
26   scoped_ptr<EmbeddedWorkerInstance> worker(
27       new EmbeddedWorkerInstance(context_, next_embedded_worker_id_));
28   worker_map_[next_embedded_worker_id_++] = worker.get();
29   return worker.Pass();
30 }
31 
StopWorker(int process_id,int embedded_worker_id)32 ServiceWorkerStatusCode EmbeddedWorkerRegistry::StopWorker(
33     int process_id, int embedded_worker_id) {
34   return Send(process_id,
35               new EmbeddedWorkerMsg_StopWorker(embedded_worker_id));
36 }
37 
OnMessageReceived(const IPC::Message & message)38 bool EmbeddedWorkerRegistry::OnMessageReceived(const IPC::Message& message) {
39   // TODO(kinuko): Move all EmbeddedWorker message handling from
40   // ServiceWorkerDispatcherHost.
41 
42   WorkerInstanceMap::iterator found = worker_map_.find(message.routing_id());
43   if (found == worker_map_.end()) {
44     LOG(ERROR) << "Worker " << message.routing_id() << " not registered";
45     return false;
46   }
47   return found->second->OnMessageReceived(message);
48 }
49 
Shutdown()50 void EmbeddedWorkerRegistry::Shutdown() {
51   for (WorkerInstanceMap::iterator it = worker_map_.begin();
52        it != worker_map_.end();
53        ++it) {
54     it->second->Stop();
55   }
56 }
57 
OnWorkerScriptLoaded(int process_id,int embedded_worker_id)58 void EmbeddedWorkerRegistry::OnWorkerScriptLoaded(int process_id,
59                                                   int embedded_worker_id) {
60   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
61   if (found == worker_map_.end()) {
62     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
63     return;
64   }
65   if (found->second->process_id() != process_id) {
66     LOG(ERROR) << "Incorrect embedded_worker_id";
67     return;
68   }
69   found->second->OnScriptLoaded();
70 }
71 
OnWorkerScriptLoadFailed(int process_id,int embedded_worker_id)72 void EmbeddedWorkerRegistry::OnWorkerScriptLoadFailed(int process_id,
73                                                       int embedded_worker_id) {
74   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
75   if (found == worker_map_.end()) {
76     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
77     return;
78   }
79   if (found->second->process_id() != process_id) {
80     LOG(ERROR) << "Incorrect embedded_worker_id";
81     return;
82   }
83   found->second->OnScriptLoadFailed();
84 }
85 
OnWorkerStarted(int process_id,int thread_id,int embedded_worker_id)86 void EmbeddedWorkerRegistry::OnWorkerStarted(
87     int process_id, int thread_id, int embedded_worker_id) {
88   DCHECK(!ContainsKey(worker_process_map_, process_id) ||
89          worker_process_map_[process_id].count(embedded_worker_id) == 0);
90   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
91   if (found == worker_map_.end()) {
92     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
93     return;
94   }
95   if (found->second->process_id() != process_id) {
96     LOG(ERROR) << "Incorrect embedded_worker_id";
97     return;
98   }
99   worker_process_map_[process_id].insert(embedded_worker_id);
100   found->second->OnStarted(thread_id);
101 }
102 
OnWorkerStopped(int process_id,int embedded_worker_id)103 void EmbeddedWorkerRegistry::OnWorkerStopped(
104     int process_id, int embedded_worker_id) {
105   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
106   if (found == worker_map_.end()) {
107     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
108     return;
109   }
110   if (found->second->process_id() != process_id) {
111     LOG(ERROR) << "Incorrect embedded_worker_id";
112     return;
113   }
114   worker_process_map_[process_id].erase(embedded_worker_id);
115   found->second->OnStopped();
116 }
117 
OnReportException(int embedded_worker_id,const base::string16 & error_message,int line_number,int column_number,const GURL & source_url)118 void EmbeddedWorkerRegistry::OnReportException(
119     int embedded_worker_id,
120     const base::string16& error_message,
121     int line_number,
122     int column_number,
123     const GURL& source_url) {
124   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
125   if (found == worker_map_.end()) {
126     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
127     return;
128   }
129   found->second->OnReportException(
130       error_message, line_number, column_number, source_url);
131 }
132 
OnReportConsoleMessage(int embedded_worker_id,int source_identifier,int message_level,const base::string16 & message,int line_number,const GURL & source_url)133 void EmbeddedWorkerRegistry::OnReportConsoleMessage(
134     int embedded_worker_id,
135     int source_identifier,
136     int message_level,
137     const base::string16& message,
138     int line_number,
139     const GURL& source_url) {
140   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
141   if (found == worker_map_.end()) {
142     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
143     return;
144   }
145   found->second->OnReportConsoleMessage(
146       source_identifier, message_level, message, line_number, source_url);
147 }
148 
AddChildProcessSender(int process_id,IPC::Sender * sender)149 void EmbeddedWorkerRegistry::AddChildProcessSender(
150     int process_id, IPC::Sender* sender) {
151   process_sender_map_[process_id] = sender;
152   DCHECK(!ContainsKey(worker_process_map_, process_id));
153 }
154 
RemoveChildProcessSender(int process_id)155 void EmbeddedWorkerRegistry::RemoveChildProcessSender(int process_id) {
156   process_sender_map_.erase(process_id);
157   std::map<int, std::set<int> >::iterator found =
158       worker_process_map_.find(process_id);
159   if (found != worker_process_map_.end()) {
160     const std::set<int>& worker_set = worker_process_map_[process_id];
161     for (std::set<int>::const_iterator it = worker_set.begin();
162          it != worker_set.end();
163          ++it) {
164       int embedded_worker_id = *it;
165       DCHECK(ContainsKey(worker_map_, embedded_worker_id));
166       worker_map_[embedded_worker_id]->OnStopped();
167     }
168     worker_process_map_.erase(found);
169   }
170 }
171 
GetWorker(int embedded_worker_id)172 EmbeddedWorkerInstance* EmbeddedWorkerRegistry::GetWorker(
173     int embedded_worker_id) {
174   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
175   if (found == worker_map_.end())
176     return NULL;
177   return found->second;
178 }
179 
~EmbeddedWorkerRegistry()180 EmbeddedWorkerRegistry::~EmbeddedWorkerRegistry() {
181   Shutdown();
182 }
183 
SendStartWorker(scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,const StatusCallback & callback,int process_id)184 void EmbeddedWorkerRegistry::SendStartWorker(
185     scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
186     const StatusCallback& callback,
187     int process_id) {
188   // The ServiceWorkerDispatcherHost is supposed to be created when the process
189   // is created, and keep an entry in process_sender_map_ for its whole
190   // lifetime.
191   DCHECK(ContainsKey(process_sender_map_, process_id));
192   callback.Run(Send(process_id, new EmbeddedWorkerMsg_StartWorker(*params)));
193 }
194 
Send(int process_id,IPC::Message * message_ptr)195 ServiceWorkerStatusCode EmbeddedWorkerRegistry::Send(
196     int process_id, IPC::Message* message_ptr) {
197   scoped_ptr<IPC::Message> message(message_ptr);
198   if (!context_)
199     return SERVICE_WORKER_ERROR_ABORT;
200   ProcessToSenderMap::iterator found = process_sender_map_.find(process_id);
201   if (found == process_sender_map_.end())
202     return SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND;
203   if (!found->second->Send(message.release()))
204     return SERVICE_WORKER_ERROR_IPC_FAILED;
205   return SERVICE_WORKER_OK;
206 }
207 
RemoveWorker(int process_id,int embedded_worker_id)208 void EmbeddedWorkerRegistry::RemoveWorker(int process_id,
209                                           int embedded_worker_id) {
210   DCHECK(ContainsKey(worker_map_, embedded_worker_id));
211   worker_map_.erase(embedded_worker_id);
212   worker_process_map_.erase(process_id);
213 }
214 
215 }  // namespace content
216