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) { | 77 bool SharedWorkerHost::Send(IPC::Message* message) { |
79 if (!container_render_filter_) { | 78 return worker_render_filter_->Send(message); |
80 delete message; | |
81 return false; | |
82 } | |
83 return container_render_filter_->Send(message); | |
84 } | 79 } |
85 | 80 |
86 void SharedWorkerHost::Start(bool pause_on_start) { | 81 void SharedWorkerHost::Start(bool pause_on_start) { |
87 WorkerProcessMsg_CreateWorker_Params params; | 82 WorkerProcessMsg_CreateWorker_Params params; |
88 params.url = instance_->url(); | 83 params.url = instance_->url(); |
89 params.name = instance_->name(); | 84 params.name = instance_->name(); |
90 params.content_security_policy = instance_->content_security_policy(); | 85 params.content_security_policy = instance_->content_security_policy(); |
91 params.security_policy_type = instance_->security_policy_type(); | 86 params.security_policy_type = instance_->security_policy_type(); |
92 params.creation_address_space = instance_->creation_address_space(); | 87 params.creation_address_space = instance_->creation_address_space(); |
93 params.pause_on_start = pause_on_start; | 88 params.pause_on_start = pause_on_start; |
94 params.route_id = worker_route_id_; | 89 params.route_id = worker_route_id_; |
95 Send(new WorkerProcessMsg_CreateWorker(params)); | 90 Send(new WorkerProcessMsg_CreateWorker(params)); |
96 | 91 |
97 for (const FilterInfo& info : filters_) | 92 for (const FilterInfo& info : filters_) |
98 info.filter()->Send(new ViewMsg_WorkerCreated(info.route_id())); | 93 info.filter()->Send(new ViewMsg_WorkerCreated(info.route_id())); |
99 } | 94 } |
100 | 95 |
101 bool SharedWorkerHost::FilterConnectionMessage( | 96 bool SharedWorkerHost::FilterConnectionMessage( |
102 int route_id, | 97 int route_id, |
103 int sent_message_port_id, | 98 int sent_message_port_id, |
104 SharedWorkerMessageFilter* incoming_filter) { | 99 SharedWorkerMessageFilter* incoming_filter) { |
105 if (!IsAvailable() || !HasFilter(incoming_filter, route_id)) | 100 if (!IsAvailable() || !HasFilter(incoming_filter, route_id)) |
106 return false; | 101 return false; |
107 | 102 |
108 Connect(route_id, sent_message_port_id, incoming_filter); | 103 Connect(route_id, sent_message_port_id, incoming_filter); |
109 return true; | 104 return true; |
110 } | 105 } |
111 | 106 |
112 void SharedWorkerHost::FilterShutdown(SharedWorkerMessageFilter* filter) { | 107 void SharedWorkerHost::FilterShutdown(SharedWorkerMessageFilter* filter) { |
113 if (!instance_) | |
114 return; | |
115 RemoveFilters(filter); | 108 RemoveFilters(filter); |
116 worker_document_set_->RemoveAll(filter); | 109 worker_document_set_->RemoveAll(filter); |
117 if (worker_document_set_->IsEmpty()) { | 110 if (worker_document_set_->IsEmpty()) { |
118 // This worker has no more associated documents - shut it down. | 111 // This worker has no more associated documents - shut it down. |
119 TerminateWorker(); | 112 TerminateWorker(); |
120 } | 113 } |
121 } | 114 } |
122 | 115 |
123 void SharedWorkerHost::DocumentDetached(SharedWorkerMessageFilter* filter, | 116 void SharedWorkerHost::DocumentDetached(SharedWorkerMessageFilter* filter, |
124 unsigned long long document_id) { | 117 unsigned long long document_id) { |
125 if (!instance_) | |
126 return; | |
127 // Walk all instances and remove the document from their document set. | 118 // Walk all instances and remove the document from their document set. |
128 worker_document_set_->Remove(filter, document_id); | 119 worker_document_set_->Remove(filter, document_id); |
129 if (worker_document_set_->IsEmpty()) { | 120 if (worker_document_set_->IsEmpty()) { |
130 // This worker has no more associated documents - shut it down. | 121 // This worker has no more associated documents - shut it down. |
131 TerminateWorker(); | 122 TerminateWorker(); |
132 } | 123 } |
133 } | 124 } |
134 | 125 |
135 void SharedWorkerHost::RenderFrameDetached(int render_process_id, | 126 void SharedWorkerHost::RenderFrameDetached(int render_process_id, |
136 int render_frame_id) { | 127 int render_frame_id) { |
137 if (!instance_) | |
138 return; | |
139 // Walk all instances and remove all the documents in the frame from their | 128 // Walk all instances and remove all the documents in the frame from their |
140 // document set. | 129 // document set. |
141 worker_document_set_->RemoveRenderFrame(render_process_id, render_frame_id); | 130 worker_document_set_->RemoveRenderFrame(render_process_id, render_frame_id); |
142 if (worker_document_set_->IsEmpty()) { | 131 if (worker_document_set_->IsEmpty()) { |
143 // This worker has no more associated documents - shut it down. | 132 // This worker has no more associated documents - shut it down. |
144 TerminateWorker(); | 133 TerminateWorker(); |
145 } | 134 } |
146 } | 135 } |
147 | 136 |
148 void SharedWorkerHost::WorkerContextClosed() { | 137 void SharedWorkerHost::WorkerContextClosed() { |
149 if (!instance_) | |
150 return; | |
151 // Set the closed flag - this will stop any further messages from | 138 // 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, | 139 // being sent to the worker (messages can still be sent from the worker, |
153 // for exception reporting, etc). | 140 // for exception reporting, etc). |
154 closed_ = true; | 141 closed_ = true; |
155 if (!termination_message_sent_) | 142 if (!termination_message_sent_) |
156 NotifyWorkerDestroyed(worker_process_id_, worker_route_id_); | 143 NotifyWorkerDestroyed(worker_process_id_, worker_route_id_); |
157 } | 144 } |
158 | 145 |
159 void SharedWorkerHost::WorkerContextDestroyed() { | |
160 if (!instance_) | |
161 return; | |
162 instance_.reset(); | |
163 worker_document_set_ = nullptr; | |
164 } | |
165 | |
166 void SharedWorkerHost::WorkerReadyForInspection() { | 146 void SharedWorkerHost::WorkerReadyForInspection() { |
167 NotifyWorkerReadyForInspection(worker_process_id_, worker_route_id_); | 147 NotifyWorkerReadyForInspection(worker_process_id_, worker_route_id_); |
168 } | 148 } |
169 | 149 |
170 void SharedWorkerHost::WorkerScriptLoaded() { | 150 void SharedWorkerHost::WorkerScriptLoaded() { |
171 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoaded", | 151 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoaded", |
172 base::TimeTicks::Now() - creation_time_); | 152 base::TimeTicks::Now() - creation_time_); |
173 } | 153 } |
174 | 154 |
175 void SharedWorkerHost::WorkerScriptLoadFailed() { | 155 void SharedWorkerHost::WorkerScriptLoadFailed() { |
176 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoadFailed", | 156 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoadFailed", |
177 base::TimeTicks::Now() - creation_time_); | 157 base::TimeTicks::Now() - creation_time_); |
178 if (!instance_) | |
179 return; | |
180 for (const FilterInfo& info : filters_) | 158 for (const FilterInfo& info : filters_) |
181 info.filter()->Send(new ViewMsg_WorkerScriptLoadFailed(info.route_id())); | 159 info.filter()->Send(new ViewMsg_WorkerScriptLoadFailed(info.route_id())); |
182 } | 160 } |
183 | 161 |
184 void SharedWorkerHost::WorkerConnected(int message_port_id) { | 162 void SharedWorkerHost::WorkerConnected(int message_port_id) { |
185 if (!instance_) | |
186 return; | |
187 for (const FilterInfo& info : filters_) { | 163 for (const FilterInfo& info : filters_) { |
188 if (info.message_port_id() != message_port_id) | 164 if (info.message_port_id() != message_port_id) |
189 continue; | 165 continue; |
190 info.filter()->Send(new ViewMsg_WorkerConnected(info.route_id())); | 166 info.filter()->Send(new ViewMsg_WorkerConnected(info.route_id())); |
191 return; | 167 return; |
192 } | 168 } |
193 } | 169 } |
194 | 170 |
195 void SharedWorkerHost::AllowFileSystem( | 171 void SharedWorkerHost::AllowFileSystem( |
196 const GURL& url, | 172 const GURL& url, |
197 std::unique_ptr<IPC::Message> reply_msg) { | 173 std::unique_ptr<IPC::Message> reply_msg) { |
198 if (!instance_) | |
199 return; | |
200 GetContentClient()->browser()->AllowWorkerFileSystem( | 174 GetContentClient()->browser()->AllowWorkerFileSystem( |
201 url, | 175 url, |
202 instance_->resource_context(), | 176 instance_->resource_context(), |
203 GetRenderFrameIDsForWorker(), | 177 GetRenderFrameIDsForWorker(), |
204 base::Bind(&SharedWorkerHost::AllowFileSystemResponse, | 178 base::Bind(&SharedWorkerHost::AllowFileSystemResponse, |
205 weak_factory_.GetWeakPtr(), | 179 weak_factory_.GetWeakPtr(), |
206 base::Passed(&reply_msg))); | 180 base::Passed(&reply_msg))); |
207 } | 181 } |
208 | 182 |
209 void SharedWorkerHost::AllowFileSystemResponse( | 183 void SharedWorkerHost::AllowFileSystemResponse( |
210 std::unique_ptr<IPC::Message> reply_msg, | 184 std::unique_ptr<IPC::Message> reply_msg, |
211 bool allowed) { | 185 bool allowed) { |
212 WorkerProcessHostMsg_RequestFileSystemAccessSync::WriteReplyParams( | 186 WorkerProcessHostMsg_RequestFileSystemAccessSync::WriteReplyParams( |
213 reply_msg.get(), | 187 reply_msg.get(), |
214 allowed); | 188 allowed); |
215 Send(reply_msg.release()); | 189 Send(reply_msg.release()); |
216 } | 190 } |
217 | 191 |
218 void SharedWorkerHost::AllowIndexedDB(const GURL& url, | 192 void SharedWorkerHost::AllowIndexedDB(const GURL& url, |
219 const base::string16& name, | 193 const base::string16& name, |
220 bool* result) { | 194 bool* result) { |
221 if (!instance_) | |
222 return; | |
223 *result = GetContentClient()->browser()->AllowWorkerIndexedDB( | 195 *result = GetContentClient()->browser()->AllowWorkerIndexedDB( |
224 url, name, instance_->resource_context(), GetRenderFrameIDsForWorker()); | 196 url, name, instance_->resource_context(), GetRenderFrameIDsForWorker()); |
225 } | 197 } |
226 | 198 |
227 void SharedWorkerHost::TerminateWorker() { | 199 void SharedWorkerHost::TerminateWorker() { |
228 termination_message_sent_ = true; | 200 termination_message_sent_ = true; |
229 if (!closed_) | 201 if (!closed_) |
230 NotifyWorkerDestroyed(worker_process_id_, worker_route_id_); | 202 NotifyWorkerDestroyed(worker_process_id_, worker_route_id_); |
231 Send(new WorkerMsg_TerminateWorkerContext(worker_route_id_)); | 203 Send(new WorkerMsg_TerminateWorkerContext(worker_route_id_)); |
232 } | 204 } |
233 | 205 |
234 std::vector<std::pair<int, int> > | 206 std::vector<std::pair<int, int> > |
235 SharedWorkerHost::GetRenderFrameIDsForWorker() { | 207 SharedWorkerHost::GetRenderFrameIDsForWorker() { |
236 std::vector<std::pair<int, int> > result; | 208 std::vector<std::pair<int, int> > result; |
237 if (!instance_) | |
238 return result; | |
239 const WorkerDocumentSet::DocumentInfoSet& documents = | 209 const WorkerDocumentSet::DocumentInfoSet& documents = |
240 worker_document_set_->documents(); | 210 worker_document_set_->documents(); |
241 for (const WorkerDocumentSet::DocumentInfo& doc : documents) { | 211 for (const WorkerDocumentSet::DocumentInfo& doc : documents) { |
242 result.push_back( | 212 result.push_back( |
243 std::make_pair(doc.render_process_id(), doc.render_frame_id())); | 213 std::make_pair(doc.render_process_id(), doc.render_frame_id())); |
244 } | 214 } |
245 return result; | 215 return result; |
246 } | 216 } |
247 | 217 |
248 bool SharedWorkerHost::IsAvailable() const { | 218 bool SharedWorkerHost::IsAvailable() const { |
249 return instance_ && !termination_message_sent_ && !closed_; | 219 return !termination_message_sent_ && !closed_; |
250 } | 220 } |
251 | 221 |
252 void SharedWorkerHost::AddFilter(SharedWorkerMessageFilter* filter, | 222 void SharedWorkerHost::AddFilter(SharedWorkerMessageFilter* filter, |
253 int route_id) { | 223 int route_id) { |
254 CHECK(filter); | 224 CHECK(filter); |
255 if (!HasFilter(filter, route_id)) { | 225 if (!HasFilter(filter, route_id)) { |
256 FilterInfo info(filter, route_id); | 226 FilterInfo info(filter, route_id); |
257 filters_.push_back(info); | 227 filters_.push_back(info); |
258 } | 228 } |
259 } | 229 } |
260 | 230 |
261 void SharedWorkerHost::RemoveFilters(SharedWorkerMessageFilter* filter) { | 231 void SharedWorkerHost::RemoveFilters(SharedWorkerMessageFilter* filter) { |
262 for (FilterList::iterator i = filters_.begin(); i != filters_.end();) { | 232 for (FilterList::iterator i = filters_.begin(); i != filters_.end();) { |
263 if (i->filter() == filter) | 233 if (i->filter() == filter) |
264 i = filters_.erase(i); | 234 i = filters_.erase(i); |
265 else | 235 else |
266 ++i; | 236 ++i; |
267 } | 237 } |
268 } | 238 } |
269 | 239 |
270 bool SharedWorkerHost::HasFilter(SharedWorkerMessageFilter* filter, | 240 bool SharedWorkerHost::HasFilter(SharedWorkerMessageFilter* filter, |
271 int route_id) const { | 241 int route_id) const { |
272 for (FilterList::const_iterator i = filters_.begin(); i != filters_.end(); | 242 for (const FilterInfo& info : filters_) { |
273 ++i) { | 243 if (info.filter() == filter && info.route_id() == route_id) |
274 if (i->filter() == filter && i->route_id() == route_id) | |
275 return true; | 244 return true; |
276 } | 245 } |
277 return false; | 246 return false; |
278 } | 247 } |
279 | 248 |
280 void SharedWorkerHost::Connect(int route_id, | 249 void SharedWorkerHost::Connect(int route_id, |
281 int sent_message_port_id, | 250 int sent_message_port_id, |
282 SharedWorkerMessageFilter* incoming_filter) { | 251 SharedWorkerMessageFilter* incoming_filter) { |
283 DCHECK(IsAvailable()); | 252 DCHECK(IsAvailable()); |
284 DCHECK(HasFilter(incoming_filter, route_id)); | 253 DCHECK(HasFilter(incoming_filter, route_id)); |
285 DCHECK(container_render_filter_); | 254 DCHECK(worker_render_filter_); |
286 | 255 |
287 int new_routing_id = container_render_filter_->GetNextRoutingID(); | 256 int new_routing_id = worker_render_filter_->GetNextRoutingID(); |
288 MessagePortService::GetInstance()->UpdateMessagePort( | 257 MessagePortService::GetInstance()->UpdateMessagePort( |
289 sent_message_port_id, | 258 sent_message_port_id, |
290 container_render_filter_->message_port_message_filter(), new_routing_id); | 259 worker_render_filter_->message_port_message_filter(), new_routing_id); |
291 SetMessagePortID(incoming_filter, route_id, sent_message_port_id); | 260 SetMessagePortID(incoming_filter, route_id, sent_message_port_id); |
292 Send(new WorkerMsg_Connect(worker_route_id_, sent_message_port_id, | 261 Send(new WorkerMsg_Connect(worker_route_id_, sent_message_port_id, |
293 new_routing_id)); | 262 new_routing_id)); |
294 | 263 |
295 // Send any queued messages for the sent port. | 264 // Send any queued messages for the sent port. |
296 MessagePortService::GetInstance()->SendQueuedMessagesIfPossible( | 265 MessagePortService::GetInstance()->SendQueuedMessagesIfPossible( |
297 sent_message_port_id); | 266 sent_message_port_id); |
298 } | 267 } |
299 | 268 |
300 void SharedWorkerHost::SetMessagePortID(SharedWorkerMessageFilter* filter, | 269 void SharedWorkerHost::SetMessagePortID(SharedWorkerMessageFilter* filter, |
301 int route_id, | 270 int route_id, |
302 int message_port_id) { | 271 int message_port_id) { |
303 for (FilterList::iterator i = filters_.begin(); i != filters_.end(); ++i) { | 272 for (FilterInfo& info : filters_) { |
304 if (i->filter() == filter && i->route_id() == route_id) { | 273 if (info.filter() == filter && info.route_id() == route_id) { |
305 i->set_message_port_id(message_port_id); | 274 info.set_message_port_id(message_port_id); |
306 return; | 275 return; |
307 } | 276 } |
308 } | 277 } |
309 } | 278 } |
310 | 279 |
311 } // namespace content | 280 } // namespace content |
OLD | NEW |