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