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.h" | 7 #include "base/metrics/histogram.h" |
8 #include "content/browser/frame_host/render_frame_host_delegate.h" | 8 #include "content/browser/frame_host/render_frame_host_delegate.h" |
9 #include "content/browser/frame_host/render_frame_host_impl.h" | 9 #include "content/browser/frame_host/render_frame_host_impl.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/worker_host/worker_document_set.h" |
13 #include "content/common/view_messages.h" | 14 #include "content/common/view_messages.h" |
14 #include "content/common/worker_messages.h" | 15 #include "content/common/worker_messages.h" |
15 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
16 #include "content/public/browser/content_browser_client.h" | 17 #include "content/public/browser/content_browser_client.h" |
17 #include "content/public/common/content_client.h" | 18 #include "content/public/common/content_client.h" |
18 | 19 |
19 namespace content { | 20 namespace content { |
20 namespace { | 21 namespace { |
21 | 22 |
22 // Notifies RenderViewHost that one or more worker objects crashed. | 23 // Notifies RenderViewHost that one or more worker objects crashed. |
23 void WorkerCrashCallback(int render_process_unique_id, int render_frame_id) { | 24 void WorkerCrashCallback(int render_process_unique_id, int render_frame_id) { |
24 RenderFrameHostImpl* host = | 25 RenderFrameHostImpl* host = |
25 RenderFrameHostImpl::FromID(render_process_unique_id, render_frame_id); | 26 RenderFrameHostImpl::FromID(render_process_unique_id, render_frame_id); |
26 if (host) | 27 if (host) |
27 host->delegate()->WorkerCrashed(host); | 28 host->delegate()->WorkerCrashed(host); |
28 } | 29 } |
29 | 30 |
30 } // namespace | 31 } // namespace |
31 | 32 |
32 SharedWorkerHost::SharedWorkerHost(SharedWorkerInstance* instance) | 33 SharedWorkerHost::SharedWorkerHost(SharedWorkerInstance* instance) |
33 : instance_(instance), | 34 : instance_(instance), |
| 35 worker_document_set_(new WorkerDocumentSet()), |
34 container_render_filter_(NULL), | 36 container_render_filter_(NULL), |
35 worker_route_id_(MSG_ROUTING_NONE), | 37 worker_route_id_(MSG_ROUTING_NONE), |
| 38 load_failed_(false), |
| 39 closed_(false), |
36 creation_time_(base::TimeTicks::Now()) { | 40 creation_time_(base::TimeTicks::Now()) { |
37 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
38 } | 42 } |
39 | 43 |
40 SharedWorkerHost::~SharedWorkerHost() { | 44 SharedWorkerHost::~SharedWorkerHost() { |
41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 45 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
42 UMA_HISTOGRAM_LONG_TIMES("SharedWorker.TimeToDeleted", | 46 UMA_HISTOGRAM_LONG_TIMES("SharedWorker.TimeToDeleted", |
43 base::TimeTicks::Now() - creation_time_); | 47 base::TimeTicks::Now() - creation_time_); |
44 // If we crashed, tell the RenderViewHosts. | 48 // If we crashed, tell the RenderViewHosts. |
45 if (instance_ && !instance_->load_failed()) { | 49 if (instance_ && !load_failed_) { |
46 const WorkerDocumentSet::DocumentInfoSet& parents = | 50 const WorkerDocumentSet::DocumentInfoSet& parents = |
47 instance_->worker_document_set()->documents(); | 51 worker_document_set_->documents(); |
48 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = | 52 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = |
49 parents.begin(); | 53 parents.begin(); |
50 parent_iter != parents.end(); | 54 parent_iter != parents.end(); |
51 ++parent_iter) { | 55 ++parent_iter) { |
52 BrowserThread::PostTask(BrowserThread::UI, | 56 BrowserThread::PostTask(BrowserThread::UI, |
53 FROM_HERE, | 57 FROM_HERE, |
54 base::Bind(&WorkerCrashCallback, | 58 base::Bind(&WorkerCrashCallback, |
55 parent_iter->render_process_id(), | 59 parent_iter->render_process_id(), |
56 parent_iter->render_frame_id())); | 60 parent_iter->render_frame_id())); |
57 } | 61 } |
(...skipping 15 matching lines...) Expand all Loading... |
73 worker_route_id_ = filter->GetNextRoutingID(); | 77 worker_route_id_ = filter->GetNextRoutingID(); |
74 | 78 |
75 WorkerProcessMsg_CreateWorker_Params params; | 79 WorkerProcessMsg_CreateWorker_Params params; |
76 params.url = instance_->url(); | 80 params.url = instance_->url(); |
77 params.name = instance_->name(); | 81 params.name = instance_->name(); |
78 params.content_security_policy = instance_->content_security_policy(); | 82 params.content_security_policy = instance_->content_security_policy(); |
79 params.security_policy_type = instance_->security_policy_type(); | 83 params.security_policy_type = instance_->security_policy_type(); |
80 params.route_id = worker_route_id_; | 84 params.route_id = worker_route_id_; |
81 Send(new WorkerProcessMsg_CreateWorker(params)); | 85 Send(new WorkerProcessMsg_CreateWorker(params)); |
82 | 86 |
83 for (SharedWorkerInstance::FilterList::const_iterator i = | 87 for (FilterList::const_iterator i = filters_.begin(); i != filters_.end(); |
84 instance_->filters().begin(); | 88 ++i) { |
85 i != instance_->filters().end(); ++i) { | |
86 i->filter()->Send(new ViewMsg_WorkerCreated(i->route_id())); | 89 i->filter()->Send(new ViewMsg_WorkerCreated(i->route_id())); |
87 } | 90 } |
88 } | 91 } |
89 | 92 |
90 bool SharedWorkerHost::FilterMessage(const IPC::Message& message, | 93 bool SharedWorkerHost::FilterMessage(const IPC::Message& message, |
91 SharedWorkerMessageFilter* filter) { | 94 SharedWorkerMessageFilter* filter) { |
92 if (!instance_) | 95 if (!instance_) |
93 return false; | 96 return false; |
94 | 97 |
95 if (!instance_->closed() && | 98 if (!closed_ && HasFilter(filter, message.routing_id())) { |
96 instance_->HasFilter(filter, message.routing_id())) { | |
97 RelayMessage(message, filter); | 99 RelayMessage(message, filter); |
98 return true; | 100 return true; |
99 } | 101 } |
100 | 102 |
101 return false; | 103 return false; |
102 } | 104 } |
103 | 105 |
104 void SharedWorkerHost::FilterShutdown(SharedWorkerMessageFilter* filter) { | 106 void SharedWorkerHost::FilterShutdown(SharedWorkerMessageFilter* filter) { |
105 if (!instance_) | 107 if (!instance_) |
106 return; | 108 return; |
107 instance_->RemoveFilters(filter); | 109 RemoveFilters(filter); |
108 instance_->worker_document_set()->RemoveAll(filter); | 110 worker_document_set_->RemoveAll(filter); |
109 if (instance_->worker_document_set()->IsEmpty()) { | 111 if (worker_document_set_->IsEmpty()) { |
110 // This worker has no more associated documents - shut it down. | 112 // This worker has no more associated documents - shut it down. |
111 Send(new WorkerMsg_TerminateWorkerContext(worker_route_id_)); | 113 Send(new WorkerMsg_TerminateWorkerContext(worker_route_id_)); |
112 } | 114 } |
113 } | 115 } |
114 | 116 |
115 void SharedWorkerHost::DocumentDetached(SharedWorkerMessageFilter* filter, | 117 void SharedWorkerHost::DocumentDetached(SharedWorkerMessageFilter* filter, |
116 unsigned long long document_id) { | 118 unsigned long long document_id) { |
117 if (!instance_) | 119 if (!instance_) |
118 return; | 120 return; |
119 // Walk all instances and remove the document from their document set. | 121 // Walk all instances and remove the document from their document set. |
120 instance_->worker_document_set()->Remove(filter, document_id); | 122 worker_document_set_->Remove(filter, document_id); |
121 if (instance_->worker_document_set()->IsEmpty()) { | 123 if (worker_document_set_->IsEmpty()) { |
122 // This worker has no more associated documents - shut it down. | 124 // This worker has no more associated documents - shut it down. |
123 Send(new WorkerMsg_TerminateWorkerContext(worker_route_id_)); | 125 Send(new WorkerMsg_TerminateWorkerContext(worker_route_id_)); |
124 } | 126 } |
125 } | 127 } |
126 | 128 |
127 void SharedWorkerHost::WorkerContextClosed() { | 129 void SharedWorkerHost::WorkerContextClosed() { |
128 if (!instance_) | 130 if (!instance_) |
129 return; | 131 return; |
130 // Set the closed flag - this will stop any further messages from | 132 // Set the closed flag - this will stop any further messages from |
131 // being sent to the worker (messages can still be sent from the worker, | 133 // being sent to the worker (messages can still be sent from the worker, |
132 // for exception reporting, etc). | 134 // for exception reporting, etc). |
133 instance_->set_closed(true); | 135 closed_ = true; |
134 } | 136 } |
135 | 137 |
136 void SharedWorkerHost::WorkerContextDestroyed() { | 138 void SharedWorkerHost::WorkerContextDestroyed() { |
137 if (!instance_) | 139 if (!instance_) |
138 return; | 140 return; |
139 instance_.reset(); | 141 instance_.reset(); |
| 142 worker_document_set_ = NULL; |
140 } | 143 } |
141 | 144 |
142 void SharedWorkerHost::WorkerScriptLoaded() { | 145 void SharedWorkerHost::WorkerScriptLoaded() { |
143 // TODO(horo): implement this. | 146 // TODO(horo): implement this. |
144 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoaded", | 147 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoaded", |
145 base::TimeTicks::Now() - creation_time_); | 148 base::TimeTicks::Now() - creation_time_); |
146 } | 149 } |
147 | 150 |
148 void SharedWorkerHost::WorkerScriptLoadFailed() { | 151 void SharedWorkerHost::WorkerScriptLoadFailed() { |
149 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoadFailed", | 152 UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoadFailed", |
150 base::TimeTicks::Now() - creation_time_); | 153 base::TimeTicks::Now() - creation_time_); |
151 if (!instance_) | 154 if (!instance_) |
152 return; | 155 return; |
153 instance_->set_load_failed(true); | 156 load_failed_ = true; |
154 for (SharedWorkerInstance::FilterList::const_iterator i = | 157 for (FilterList::const_iterator i = filters_.begin(); i != filters_.end(); |
155 instance_->filters().begin(); | 158 ++i) { |
156 i != instance_->filters().end(); ++i) { | |
157 i->filter()->Send(new ViewMsg_WorkerScriptLoadFailed(i->route_id())); | 159 i->filter()->Send(new ViewMsg_WorkerScriptLoadFailed(i->route_id())); |
158 } | 160 } |
159 } | 161 } |
160 | 162 |
161 void SharedWorkerHost::WorkerConnected(int message_port_id) { | 163 void SharedWorkerHost::WorkerConnected(int message_port_id) { |
162 if (!instance_) | 164 if (!instance_) |
163 return; | 165 return; |
164 for (SharedWorkerInstance::FilterList::const_iterator i = | 166 for (FilterList::const_iterator i = filters_.begin(); i != filters_.end(); |
165 instance_->filters().begin(); | 167 ++i) { |
166 i != instance_->filters().end(); ++i) { | |
167 if (i->message_port_id() != message_port_id) | 168 if (i->message_port_id() != message_port_id) |
168 continue; | 169 continue; |
169 i->filter()->Send(new ViewMsg_WorkerConnected(i->route_id())); | 170 i->filter()->Send(new ViewMsg_WorkerConnected(i->route_id())); |
170 return; | 171 return; |
171 } | 172 } |
172 } | 173 } |
173 | 174 |
174 void SharedWorkerHost::AllowDatabase(const GURL& url, | 175 void SharedWorkerHost::AllowDatabase(const GURL& url, |
175 const base::string16& name, | 176 const base::string16& name, |
176 const base::string16& display_name, | 177 const base::string16& display_name, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 if (!WorkerMsg_Connect::Read( | 217 if (!WorkerMsg_Connect::Read( |
217 &message, &sent_message_port_id, &new_routing_id)) { | 218 &message, &sent_message_port_id, &new_routing_id)) { |
218 return; | 219 return; |
219 } | 220 } |
220 DCHECK(container_render_filter_); | 221 DCHECK(container_render_filter_); |
221 new_routing_id = container_render_filter_->GetNextRoutingID(); | 222 new_routing_id = container_render_filter_->GetNextRoutingID(); |
222 MessagePortService::GetInstance()->UpdateMessagePort( | 223 MessagePortService::GetInstance()->UpdateMessagePort( |
223 sent_message_port_id, | 224 sent_message_port_id, |
224 container_render_filter_->message_port_message_filter(), | 225 container_render_filter_->message_port_message_filter(), |
225 new_routing_id); | 226 new_routing_id); |
226 instance_->SetMessagePortID(incoming_filter, | 227 SetMessagePortID( |
227 message.routing_id(), | 228 incoming_filter, message.routing_id(), sent_message_port_id); |
228 sent_message_port_id); | |
229 // Resend the message with the new routing id. | 229 // Resend the message with the new routing id. |
230 Send(new WorkerMsg_Connect( | 230 Send(new WorkerMsg_Connect( |
231 worker_route_id_, sent_message_port_id, new_routing_id)); | 231 worker_route_id_, sent_message_port_id, new_routing_id)); |
232 | 232 |
233 // Send any queued messages for the sent port. | 233 // Send any queued messages for the sent port. |
234 MessagePortService::GetInstance()->SendQueuedMessagesIfPossible( | 234 MessagePortService::GetInstance()->SendQueuedMessagesIfPossible( |
235 sent_message_port_id); | 235 sent_message_port_id); |
236 } else { | 236 } else { |
237 IPC::Message* new_message = new IPC::Message(message); | 237 IPC::Message* new_message = new IPC::Message(message); |
238 new_message->set_routing_id(worker_route_id_); | 238 new_message->set_routing_id(worker_route_id_); |
239 Send(new_message); | 239 Send(new_message); |
240 return; | 240 return; |
241 } | 241 } |
242 } | 242 } |
243 | 243 |
244 void SharedWorkerHost::TerminateWorker() { | 244 void SharedWorkerHost::TerminateWorker() { |
245 Send(new WorkerMsg_TerminateWorkerContext(worker_route_id_)); | 245 Send(new WorkerMsg_TerminateWorkerContext(worker_route_id_)); |
246 } | 246 } |
247 | 247 |
248 std::vector<std::pair<int, int> > | 248 std::vector<std::pair<int, int> > |
249 SharedWorkerHost::GetRenderFrameIDsForWorker() { | 249 SharedWorkerHost::GetRenderFrameIDsForWorker() { |
250 std::vector<std::pair<int, int> > result; | 250 std::vector<std::pair<int, int> > result; |
251 if (!instance_) | 251 if (!instance_) |
252 return result; | 252 return result; |
253 const WorkerDocumentSet::DocumentInfoSet& documents = | 253 const WorkerDocumentSet::DocumentInfoSet& documents = |
254 instance_->worker_document_set()->documents(); | 254 worker_document_set_->documents(); |
255 for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc = | 255 for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc = |
256 documents.begin(); | 256 documents.begin(); |
257 doc != documents.end(); | 257 doc != documents.end(); |
258 ++doc) { | 258 ++doc) { |
259 result.push_back( | 259 result.push_back( |
260 std::make_pair(doc->render_process_id(), doc->render_frame_id())); | 260 std::make_pair(doc->render_process_id(), doc->render_frame_id())); |
261 } | 261 } |
262 return result; | 262 return result; |
263 } | 263 } |
264 | 264 |
| 265 void SharedWorkerHost::AddFilter(SharedWorkerMessageFilter* filter, |
| 266 int route_id) { |
| 267 CHECK(filter); |
| 268 if (!HasFilter(filter, route_id)) { |
| 269 FilterInfo info(filter, route_id); |
| 270 filters_.push_back(info); |
| 271 } |
| 272 } |
| 273 |
| 274 void SharedWorkerHost::RemoveFilters(SharedWorkerMessageFilter* filter) { |
| 275 for (FilterList::iterator i = filters_.begin(); i != filters_.end();) { |
| 276 if (i->filter() == filter) |
| 277 i = filters_.erase(i); |
| 278 else |
| 279 ++i; |
| 280 } |
| 281 } |
| 282 |
| 283 bool SharedWorkerHost::HasFilter(SharedWorkerMessageFilter* filter, |
| 284 int route_id) const { |
| 285 for (FilterList::const_iterator i = filters_.begin(); i != filters_.end(); |
| 286 ++i) { |
| 287 if (i->filter() == filter && i->route_id() == route_id) |
| 288 return true; |
| 289 } |
| 290 return false; |
| 291 } |
| 292 |
| 293 void SharedWorkerHost::SetMessagePortID(SharedWorkerMessageFilter* filter, |
| 294 int route_id, |
| 295 int message_port_id) { |
| 296 for (FilterList::iterator i = filters_.begin(); i != filters_.end(); ++i) { |
| 297 if (i->filter() == filter && i->route_id() == route_id) { |
| 298 i->set_message_port_id(message_port_id); |
| 299 return; |
| 300 } |
| 301 } |
| 302 } |
| 303 |
265 } // namespace content | 304 } // namespace content |
OLD | NEW |