OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/shared_worker/shared_worker_host.h" | 5 #include "content/browser/shared_worker/shared_worker_host.h" |
6 | 6 |
7 #include "base/metrics/histogram_macros.h" | 7 #include "base/metrics/histogram_macros.h" |
8 #include "content/browser/devtools/shared_worker_devtools_manager.h" | 8 #include "content/browser/devtools/shared_worker_devtools_manager.h" |
9 #include "content/browser/message_port_message_filter.h" | 9 #include "content/browser/message_port_message_filter.h" |
10 #include "content/browser/message_port_service.h" | 10 #include "content/browser/message_port_service.h" |
11 #include "content/browser/shared_worker/shared_worker_instance.h" | 11 #include "content/browser/shared_worker/shared_worker_instance.h" |
12 #include "content/browser/shared_worker/shared_worker_message_filter.h" | 12 #include "content/browser/shared_worker/shared_worker_message_filter.h" |
13 #include "content/browser/shared_worker/shared_worker_service_impl.h" | 13 #include "content/browser/shared_worker/shared_worker_service_impl.h" |
14 #include "content/browser/shared_worker/worker_document_set.h" | |
15 #include "content/common/view_messages.h" | 14 #include "content/common/view_messages.h" |
16 #include "content/common/worker_messages.h" | 15 #include "content/common/worker_messages.h" |
17 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
18 #include "content/public/browser/content_browser_client.h" | 17 #include "content/public/browser/content_browser_client.h" |
19 #include "content/public/browser/render_process_host.h" | 18 #include "content/public/browser/render_process_host.h" |
20 #include "content/public/common/content_client.h" | 19 #include "content/public/common/content_client.h" |
21 | 20 |
22 namespace content { | 21 namespace content { |
23 namespace { | 22 namespace { |
24 | 23 |
(...skipping 23 matching lines...) Expand all Loading... |
48 worker_process_id, worker_route_id); | 47 worker_process_id, worker_route_id); |
49 } | 48 } |
50 | 49 |
51 } // namespace | 50 } // namespace |
52 | 51 |
53 SharedWorkerHost::SharedWorkerHost(SharedWorkerInstance* instance, | 52 SharedWorkerHost::SharedWorkerHost(SharedWorkerInstance* instance, |
54 SharedWorkerMessageFilter* filter, | 53 SharedWorkerMessageFilter* filter, |
55 int worker_route_id) | 54 int worker_route_id) |
56 : instance_(instance), | 55 : instance_(instance), |
57 worker_document_set_(new WorkerDocumentSet()), | 56 worker_document_set_(new WorkerDocumentSet()), |
58 container_render_filter_(filter), | 57 worker_render_filter_(filter), |
59 worker_process_id_(filter->render_process_id()), | 58 worker_process_id_(filter->render_process_id()), |
60 worker_route_id_(worker_route_id), | 59 worker_route_id_(worker_route_id), |
61 termination_message_sent_(false), | |
62 closed_(false), | |
63 creation_time_(base::TimeTicks::Now()), | 60 creation_time_(base::TimeTicks::Now()), |
64 weak_factory_(this) { | 61 weak_factory_(this) { |
65 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 62 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 63 DCHECK(instance_); |
| 64 DCHECK(worker_render_filter_); |
66 } | 65 } |
67 | 66 |
68 SharedWorkerHost::~SharedWorkerHost() { | 67 SharedWorkerHost::~SharedWorkerHost() { |
69 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 68 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
70 UMA_HISTOGRAM_LONG_TIMES("SharedWorker.TimeToDeleted", | 69 UMA_HISTOGRAM_LONG_TIMES("SharedWorker.TimeToDeleted", |
71 base::TimeTicks::Now() - creation_time_); | 70 base::TimeTicks::Now() - creation_time_); |
72 if (!closed_ && !termination_message_sent_) | 71 if (!closed_ && !termination_message_sent_) |
73 NotifyWorkerDestroyed(worker_process_id_, worker_route_id_); | 72 NotifyWorkerDestroyed(worker_process_id_, worker_route_id_); |
74 SharedWorkerServiceImpl::GetInstance()->NotifyWorkerDestroyed( | 73 SharedWorkerServiceImpl::GetInstance()->NotifyWorkerDestroyed( |
75 worker_process_id_, worker_route_id_); | 74 worker_process_id_, worker_route_id_); |
76 } | 75 } |
77 | 76 |
78 bool SharedWorkerHost::Send(IPC::Message* message) { | |
79 if (!container_render_filter_) { | |
80 delete message; | |
81 return false; | |
82 } | |
83 return container_render_filter_->Send(message); | |
84 } | |
85 | |
86 void SharedWorkerHost::Start(bool pause_on_start) { | 77 void SharedWorkerHost::Start(bool pause_on_start) { |
87 WorkerProcessMsg_CreateWorker_Params params; | 78 WorkerProcessMsg_CreateWorker_Params params; |
88 params.url = instance_->url(); | 79 params.url = instance_->url(); |
89 params.name = instance_->name(); | 80 params.name = instance_->name(); |
90 params.content_security_policy = instance_->content_security_policy(); | 81 params.content_security_policy = instance_->content_security_policy(); |
91 params.security_policy_type = instance_->security_policy_type(); | 82 params.security_policy_type = instance_->security_policy_type(); |
92 params.creation_address_space = instance_->creation_address_space(); | 83 params.creation_address_space = instance_->creation_address_space(); |
93 params.pause_on_start = pause_on_start; | 84 params.pause_on_start = pause_on_start; |
94 params.route_id = worker_route_id_; | 85 params.route_id = worker_route_id_; |
95 Send(new WorkerProcessMsg_CreateWorker(params)); | 86 Send(new WorkerProcessMsg_CreateWorker(params)); |
96 | 87 |
97 for (const FilterInfo& info : filters_) | 88 for (const FilterInfo& info : filters_) |
98 info.filter()->Send(new ViewMsg_WorkerCreated(info.route_id())); | 89 info.filter()->Send(new ViewMsg_WorkerCreated(info.route_id())); |
99 } | 90 } |
100 | 91 |
101 bool SharedWorkerHost::FilterConnectionMessage( | 92 bool SharedWorkerHost::FilterConnectionMessage( |
102 int route_id, | 93 int route_id, |
103 int sent_message_port_id, | 94 int sent_message_port_id, |
104 SharedWorkerMessageFilter* incoming_filter) { | 95 SharedWorkerMessageFilter* incoming_filter) { |
105 if (!IsAvailable() || !HasFilter(incoming_filter, route_id)) | 96 if (!IsAvailable() || !HasFilter(incoming_filter, route_id)) |
106 return false; | 97 return false; |
107 | 98 |
108 Connect(route_id, sent_message_port_id, incoming_filter); | 99 Connect(route_id, sent_message_port_id, incoming_filter); |
109 return true; | 100 return true; |
110 } | 101 } |
111 | 102 |
112 void SharedWorkerHost::FilterShutdown(SharedWorkerMessageFilter* filter) { | 103 void SharedWorkerHost::FilterShutdown(SharedWorkerMessageFilter* filter) { |
113 if (!instance_) | |
114 return; | |
115 RemoveFilters(filter); | 104 RemoveFilters(filter); |
116 worker_document_set_->RemoveAll(filter); | 105 worker_document_set_->RemoveAll(filter); |
117 if (worker_document_set_->IsEmpty()) { | 106 if (worker_document_set_->IsEmpty()) { |
118 // This worker has no more associated documents - shut it down. | 107 // This worker has no more associated documents - shut it down. |
119 TerminateWorker(); | 108 TerminateWorker(); |
120 } | 109 } |
121 } | 110 } |
122 | 111 |
123 void SharedWorkerHost::DocumentDetached(SharedWorkerMessageFilter* filter, | 112 void SharedWorkerHost::DocumentDetached(SharedWorkerMessageFilter* filter, |
124 unsigned long long document_id) { | 113 unsigned long long document_id) { |
125 if (!instance_) | |
126 return; | |
127 // Walk all instances and remove the document from their document set. | 114 // Walk all instances and remove the document from their document set. |
128 worker_document_set_->Remove(filter, document_id); | 115 worker_document_set_->Remove(filter, document_id); |
129 if (worker_document_set_->IsEmpty()) { | 116 if (worker_document_set_->IsEmpty()) { |
130 // This worker has no more associated documents - shut it down. | 117 // This worker has no more associated documents - shut it down. |
131 TerminateWorker(); | 118 TerminateWorker(); |
132 } | 119 } |
133 } | 120 } |
134 | 121 |
135 void SharedWorkerHost::RenderFrameDetached(int render_process_id, | 122 void SharedWorkerHost::RenderFrameDetached(int render_process_id, |
136 int render_frame_id) { | 123 int render_frame_id) { |
137 if (!instance_) | |
138 return; | |
139 // Walk all instances and remove all the documents in the frame from their | 124 // Walk all instances and remove all the documents in the frame from their |
140 // document set. | 125 // document set. |
141 worker_document_set_->RemoveRenderFrame(render_process_id, render_frame_id); | 126 worker_document_set_->RemoveRenderFrame(render_process_id, render_frame_id); |
142 if (worker_document_set_->IsEmpty()) { | 127 if (worker_document_set_->IsEmpty()) { |
143 // This worker has no more associated documents - shut it down. | 128 // This worker has no more associated documents - shut it down. |
144 TerminateWorker(); | 129 TerminateWorker(); |
145 } | 130 } |
146 } | 131 } |
147 | 132 |
148 void SharedWorkerHost::WorkerContextClosed() { | 133 void SharedWorkerHost::WorkerContextClosed() { |
149 if (!instance_) | |
150 return; | |
151 // Set the closed flag - this will stop any further messages from | 134 // Set the closed flag - this will stop any further messages from |
152 // being sent to the worker (messages can still be sent from the worker, | 135 // being sent to the worker (messages can still be sent from the worker, |
153 // for exception reporting, etc). | 136 // for exception reporting, etc). |
154 closed_ = true; | 137 closed_ = true; |
155 if (!termination_message_sent_) | 138 if (!termination_message_sent_) |
156 NotifyWorkerDestroyed(worker_process_id_, worker_route_id_); | 139 NotifyWorkerDestroyed(worker_process_id_, worker_route_id_); |
157 } | 140 } |
158 | 141 |
159 void SharedWorkerHost::WorkerContextDestroyed() { | |
160 if (!instance_) | |
161 return; | |
162 instance_.reset(); | |
163 worker_document_set_ = nullptr; | |
164 } | |
165 | |
166 void SharedWorkerHost::WorkerReadyForInspection() { | 142 void SharedWorkerHost::WorkerReadyForInspection() { |
167 NotifyWorkerReadyForInspection(worker_process_id_, worker_route_id_); | 143 NotifyWorkerReadyForInspection(worker_process_id_, worker_route_id_); |
168 } | 144 } |
169 | 145 |
170 void SharedWorkerHost::WorkerScriptLoaded() { | 146 void SharedWorkerHost::WorkerScriptLoaded() { |
171 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoaded", | 147 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoaded", |
172 base::TimeTicks::Now() - creation_time_); | 148 base::TimeTicks::Now() - creation_time_); |
173 } | 149 } |
174 | 150 |
175 void SharedWorkerHost::WorkerScriptLoadFailed() { | 151 void SharedWorkerHost::WorkerScriptLoadFailed() { |
176 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoadFailed", | 152 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoadFailed", |
177 base::TimeTicks::Now() - creation_time_); | 153 base::TimeTicks::Now() - creation_time_); |
178 if (!instance_) | |
179 return; | |
180 for (const FilterInfo& info : filters_) | 154 for (const FilterInfo& info : filters_) |
181 info.filter()->Send(new ViewMsg_WorkerScriptLoadFailed(info.route_id())); | 155 info.filter()->Send(new ViewMsg_WorkerScriptLoadFailed(info.route_id())); |
182 } | 156 } |
183 | 157 |
184 void SharedWorkerHost::WorkerConnected(int message_port_id) { | 158 void SharedWorkerHost::WorkerConnected(int message_port_id) { |
185 if (!instance_) | |
186 return; | |
187 for (const FilterInfo& info : filters_) { | 159 for (const FilterInfo& info : filters_) { |
188 if (info.message_port_id() != message_port_id) | 160 if (info.message_port_id() != message_port_id) |
189 continue; | 161 continue; |
190 info.filter()->Send(new ViewMsg_WorkerConnected(info.route_id())); | 162 info.filter()->Send(new ViewMsg_WorkerConnected(info.route_id())); |
191 return; | 163 return; |
192 } | 164 } |
193 } | 165 } |
194 | 166 |
195 void SharedWorkerHost::AllowFileSystem( | 167 void SharedWorkerHost::AllowFileSystem( |
196 const GURL& url, | 168 const GURL& url, |
197 std::unique_ptr<IPC::Message> reply_msg) { | 169 std::unique_ptr<IPC::Message> reply_msg) { |
198 if (!instance_) | |
199 return; | |
200 GetContentClient()->browser()->AllowWorkerFileSystem( | 170 GetContentClient()->browser()->AllowWorkerFileSystem( |
201 url, | 171 url, |
202 instance_->resource_context(), | 172 instance_->resource_context(), |
203 GetRenderFrameIDsForWorker(), | 173 GetRenderFrameIDsForWorker(), |
204 base::Bind(&SharedWorkerHost::AllowFileSystemResponse, | 174 base::Bind(&SharedWorkerHost::AllowFileSystemResponse, |
205 weak_factory_.GetWeakPtr(), | 175 weak_factory_.GetWeakPtr(), |
206 base::Passed(&reply_msg))); | 176 base::Passed(&reply_msg))); |
207 } | 177 } |
208 | 178 |
209 void SharedWorkerHost::AllowFileSystemResponse( | 179 void SharedWorkerHost::AllowFileSystemResponse( |
210 std::unique_ptr<IPC::Message> reply_msg, | 180 std::unique_ptr<IPC::Message> reply_msg, |
211 bool allowed) { | 181 bool allowed) { |
212 WorkerProcessHostMsg_RequestFileSystemAccessSync::WriteReplyParams( | 182 WorkerProcessHostMsg_RequestFileSystemAccessSync::WriteReplyParams( |
213 reply_msg.get(), | 183 reply_msg.get(), |
214 allowed); | 184 allowed); |
215 Send(reply_msg.release()); | 185 Send(reply_msg.release()); |
216 } | 186 } |
217 | 187 |
218 void SharedWorkerHost::AllowIndexedDB(const GURL& url, | 188 void SharedWorkerHost::AllowIndexedDB(const GURL& url, |
219 const base::string16& name, | 189 const base::string16& name, |
220 bool* result) { | 190 bool* result) { |
221 if (!instance_) | |
222 return; | |
223 *result = GetContentClient()->browser()->AllowWorkerIndexedDB( | 191 *result = GetContentClient()->browser()->AllowWorkerIndexedDB( |
224 url, name, instance_->resource_context(), GetRenderFrameIDsForWorker()); | 192 url, name, instance_->resource_context(), GetRenderFrameIDsForWorker()); |
225 } | 193 } |
226 | 194 |
227 void SharedWorkerHost::TerminateWorker() { | 195 void SharedWorkerHost::TerminateWorker() { |
228 termination_message_sent_ = true; | 196 termination_message_sent_ = true; |
229 if (!closed_) | 197 if (!closed_) |
230 NotifyWorkerDestroyed(worker_process_id_, worker_route_id_); | 198 NotifyWorkerDestroyed(worker_process_id_, worker_route_id_); |
231 Send(new WorkerMsg_TerminateWorkerContext(worker_route_id_)); | 199 Send(new WorkerMsg_TerminateWorkerContext(worker_route_id_)); |
232 } | 200 } |
233 | 201 |
234 std::vector<std::pair<int, int> > | 202 std::vector<std::pair<int, int> > |
235 SharedWorkerHost::GetRenderFrameIDsForWorker() { | 203 SharedWorkerHost::GetRenderFrameIDsForWorker() { |
236 std::vector<std::pair<int, int> > result; | 204 std::vector<std::pair<int, int> > result; |
237 if (!instance_) | |
238 return result; | |
239 const WorkerDocumentSet::DocumentInfoSet& documents = | 205 const WorkerDocumentSet::DocumentInfoSet& documents = |
240 worker_document_set_->documents(); | 206 worker_document_set_->documents(); |
241 for (const WorkerDocumentSet::DocumentInfo& doc : documents) { | 207 for (const WorkerDocumentSet::DocumentInfo& doc : documents) { |
242 result.push_back( | 208 result.push_back( |
243 std::make_pair(doc.render_process_id(), doc.render_frame_id())); | 209 std::make_pair(doc.render_process_id(), doc.render_frame_id())); |
244 } | 210 } |
245 return result; | 211 return result; |
246 } | 212 } |
247 | 213 |
248 bool SharedWorkerHost::IsAvailable() const { | 214 bool SharedWorkerHost::IsAvailable() const { |
249 return instance_ && !termination_message_sent_ && !closed_; | 215 return !termination_message_sent_ && !closed_; |
250 } | 216 } |
251 | 217 |
252 void SharedWorkerHost::AddFilter(SharedWorkerMessageFilter* filter, | 218 void SharedWorkerHost::AddFilter(SharedWorkerMessageFilter* filter, |
253 int route_id) { | 219 int route_id) { |
254 CHECK(filter); | 220 CHECK(filter); |
255 if (!HasFilter(filter, route_id)) { | 221 if (!HasFilter(filter, route_id)) { |
256 FilterInfo info(filter, route_id); | 222 FilterInfo info(filter, route_id); |
257 filters_.push_back(info); | 223 filters_.push_back(info); |
258 } | 224 } |
259 } | 225 } |
260 | 226 |
261 void SharedWorkerHost::RemoveFilters(SharedWorkerMessageFilter* filter) { | 227 void SharedWorkerHost::RemoveFilters(SharedWorkerMessageFilter* filter) { |
262 for (FilterList::iterator i = filters_.begin(); i != filters_.end();) { | 228 for (FilterList::iterator i = filters_.begin(); i != filters_.end();) { |
263 if (i->filter() == filter) | 229 if (i->filter() == filter) |
264 i = filters_.erase(i); | 230 i = filters_.erase(i); |
265 else | 231 else |
266 ++i; | 232 ++i; |
267 } | 233 } |
268 } | 234 } |
269 | 235 |
270 bool SharedWorkerHost::HasFilter(SharedWorkerMessageFilter* filter, | 236 bool SharedWorkerHost::HasFilter(SharedWorkerMessageFilter* filter, |
271 int route_id) const { | 237 int route_id) const { |
272 for (FilterList::const_iterator i = filters_.begin(); i != filters_.end(); | 238 for (const FilterInfo& info : filters_) { |
273 ++i) { | 239 if (info.filter() == filter && info.route_id() == route_id) |
274 if (i->filter() == filter && i->route_id() == route_id) | |
275 return true; | 240 return true; |
276 } | 241 } |
277 return false; | 242 return false; |
278 } | 243 } |
279 | 244 |
280 void SharedWorkerHost::Connect(int route_id, | 245 void SharedWorkerHost::Connect(int route_id, |
281 int sent_message_port_id, | 246 int sent_message_port_id, |
282 SharedWorkerMessageFilter* incoming_filter) { | 247 SharedWorkerMessageFilter* incoming_filter) { |
283 DCHECK(IsAvailable()); | 248 DCHECK(IsAvailable()); |
284 DCHECK(HasFilter(incoming_filter, route_id)); | 249 DCHECK(HasFilter(incoming_filter, route_id)); |
285 DCHECK(container_render_filter_); | 250 DCHECK(worker_render_filter_); |
286 | 251 |
287 int new_routing_id = container_render_filter_->GetNextRoutingID(); | 252 int new_routing_id = worker_render_filter_->GetNextRoutingID(); |
288 MessagePortService::GetInstance()->UpdateMessagePort( | 253 MessagePortService::GetInstance()->UpdateMessagePort( |
289 sent_message_port_id, | 254 sent_message_port_id, |
290 container_render_filter_->message_port_message_filter(), new_routing_id); | 255 worker_render_filter_->message_port_message_filter(), new_routing_id); |
291 SetMessagePortID(incoming_filter, route_id, sent_message_port_id); | 256 SetMessagePortID(incoming_filter, route_id, sent_message_port_id); |
292 Send(new WorkerMsg_Connect(worker_route_id_, sent_message_port_id, | 257 Send(new WorkerMsg_Connect(worker_route_id_, sent_message_port_id, |
293 new_routing_id)); | 258 new_routing_id)); |
294 | 259 |
295 // Send any queued messages for the sent port. | 260 // Send any queued messages for the sent port. |
296 MessagePortService::GetInstance()->SendQueuedMessagesIfPossible( | 261 MessagePortService::GetInstance()->SendQueuedMessagesIfPossible( |
297 sent_message_port_id); | 262 sent_message_port_id); |
298 } | 263 } |
299 | 264 |
300 void SharedWorkerHost::SetMessagePortID(SharedWorkerMessageFilter* filter, | 265 void SharedWorkerHost::SetMessagePortID(SharedWorkerMessageFilter* filter, |
301 int route_id, | 266 int route_id, |
302 int message_port_id) { | 267 int message_port_id) { |
303 for (FilterList::iterator i = filters_.begin(); i != filters_.end(); ++i) { | 268 for (FilterInfo& info : filters_) { |
304 if (i->filter() == filter && i->route_id() == route_id) { | 269 if (info.filter() == filter && info.route_id() == route_id) { |
305 i->set_message_port_id(message_port_id); | 270 info.set_message_port_id(message_port_id); |
306 return; | 271 return; |
307 } | 272 } |
308 } | 273 } |
309 } | 274 } |
310 | 275 |
| 276 bool SharedWorkerHost::Send(IPC::Message* message) { |
| 277 return worker_render_filter_->Send(message); |
| 278 } |
| 279 |
311 } // namespace content | 280 } // namespace content |
OLD | NEW |