| 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 |