| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "content/browser/worker_host/worker_service_impl.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/command_line.h" | |
| 10 #include "base/logging.h" | |
| 11 #include "base/threading/thread.h" | |
| 12 #include "content/browser/devtools/worker_devtools_manager.h" | |
| 13 #include "content/browser/renderer_host/render_widget_host_impl.h" | |
| 14 #include "content/browser/shared_worker/shared_worker_service_impl.h" | |
| 15 #include "content/browser/worker_host/worker_message_filter.h" | |
| 16 #include "content/browser/worker_host/worker_process_host.h" | |
| 17 #include "content/common/view_messages.h" | |
| 18 #include "content/common/worker_messages.h" | |
| 19 #include "content/public/browser/child_process_data.h" | |
| 20 #include "content/public/browser/notification_service.h" | |
| 21 #include "content/public/browser/notification_types.h" | |
| 22 #include "content/public/browser/render_frame_host.h" | |
| 23 #include "content/public/browser/render_process_host.h" | |
| 24 #include "content/public/browser/render_view_host.h" | |
| 25 #include "content/public/browser/render_widget_host.h" | |
| 26 #include "content/public/browser/render_widget_host_iterator.h" | |
| 27 #include "content/public/browser/render_widget_host_view.h" | |
| 28 #include "content/public/browser/resource_context.h" | |
| 29 #include "content/public/browser/web_contents.h" | |
| 30 #include "content/public/browser/worker_service_observer.h" | |
| 31 #include "content/public/common/content_switches.h" | |
| 32 #include "content/public/common/process_type.h" | |
| 33 | |
| 34 namespace content { | |
| 35 | |
| 36 namespace { | |
| 37 void AddRenderFrameID(std::set<std::pair<int, int> >* visible_frame_ids, | |
| 38 RenderFrameHost* rfh) { | |
| 39 visible_frame_ids->insert( | |
| 40 std::pair<int, int>(rfh->GetProcess()->GetID(), | |
| 41 rfh->GetRoutingID())); | |
| 42 } | |
| 43 } | |
| 44 | |
| 45 const int WorkerServiceImpl::kMaxWorkersWhenSeparate = 64; | |
| 46 const int WorkerServiceImpl::kMaxWorkersPerFrameWhenSeparate = 16; | |
| 47 | |
| 48 class WorkerPrioritySetter | |
| 49 : public NotificationObserver, | |
| 50 public base::RefCountedThreadSafe<WorkerPrioritySetter, | |
| 51 BrowserThread::DeleteOnUIThread> { | |
| 52 public: | |
| 53 WorkerPrioritySetter(); | |
| 54 | |
| 55 // Posts a task to the UI thread to register to receive notifications. | |
| 56 void Initialize(); | |
| 57 | |
| 58 // Invoked by WorkerServiceImpl when a worker process is created. | |
| 59 void NotifyWorkerProcessCreated(); | |
| 60 | |
| 61 private: | |
| 62 friend class base::RefCountedThreadSafe<WorkerPrioritySetter>; | |
| 63 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | |
| 64 friend class base::DeleteHelper<WorkerPrioritySetter>; | |
| 65 virtual ~WorkerPrioritySetter(); | |
| 66 | |
| 67 // Posts a task to perform a worker priority update. | |
| 68 void PostTaskToGatherAndUpdateWorkerPriorities(); | |
| 69 | |
| 70 // Gathers up a list of the visible tabs and then updates priorities for | |
| 71 // all the shared workers. | |
| 72 void GatherVisibleIDsAndUpdateWorkerPriorities(); | |
| 73 | |
| 74 // Registers as an observer to receive notifications about | |
| 75 // widgets being shown. | |
| 76 void RegisterObserver(); | |
| 77 | |
| 78 // Sets priorities for shared workers given a set of visible frames (as a | |
| 79 // std::set of std::pair<render_process, render_frame> ids. | |
| 80 void UpdateWorkerPrioritiesFromVisibleSet( | |
| 81 const std::set<std::pair<int, int> >* visible); | |
| 82 | |
| 83 // Called to refresh worker priorities when focus changes between tabs. | |
| 84 void OnRenderWidgetVisibilityChanged(std::pair<int, int>); | |
| 85 | |
| 86 // NotificationObserver implementation. | |
| 87 virtual void Observe(int type, | |
| 88 const NotificationSource& source, | |
| 89 const NotificationDetails& details) OVERRIDE; | |
| 90 | |
| 91 NotificationRegistrar registrar_; | |
| 92 }; | |
| 93 | |
| 94 WorkerPrioritySetter::WorkerPrioritySetter() { | |
| 95 } | |
| 96 | |
| 97 WorkerPrioritySetter::~WorkerPrioritySetter() { | |
| 98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 99 } | |
| 100 | |
| 101 void WorkerPrioritySetter::Initialize() { | |
| 102 BrowserThread::PostTask( | |
| 103 BrowserThread::UI, FROM_HERE, | |
| 104 base::Bind(&WorkerPrioritySetter::RegisterObserver, this)); | |
| 105 } | |
| 106 | |
| 107 void WorkerPrioritySetter::NotifyWorkerProcessCreated() { | |
| 108 PostTaskToGatherAndUpdateWorkerPriorities(); | |
| 109 } | |
| 110 | |
| 111 void WorkerPrioritySetter::PostTaskToGatherAndUpdateWorkerPriorities() { | |
| 112 BrowserThread::PostTask( | |
| 113 BrowserThread::UI, FROM_HERE, | |
| 114 base::Bind( | |
| 115 &WorkerPrioritySetter::GatherVisibleIDsAndUpdateWorkerPriorities, | |
| 116 this)); | |
| 117 } | |
| 118 | |
| 119 void WorkerPrioritySetter::GatherVisibleIDsAndUpdateWorkerPriorities() { | |
| 120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 121 std::set<std::pair<int, int> >* visible_frame_ids = | |
| 122 new std::set<std::pair<int, int> >(); | |
| 123 | |
| 124 // Gather up all the visible renderer process/view pairs | |
| 125 scoped_ptr<RenderWidgetHostIterator> widgets( | |
| 126 RenderWidgetHost::GetRenderWidgetHosts()); | |
| 127 while (RenderWidgetHost* widget = widgets->GetNextHost()) { | |
| 128 if (widget->GetProcess()->VisibleWidgetCount() == 0) | |
| 129 continue; | |
| 130 if (!widget->IsRenderView()) | |
| 131 continue; | |
| 132 | |
| 133 RenderWidgetHostView* widget_view = widget->GetView(); | |
| 134 if (!widget_view || !widget_view->IsShowing()) | |
| 135 continue; | |
| 136 RenderViewHost* rvh = RenderViewHost::From(widget); | |
| 137 WebContents* web_contents = WebContents::FromRenderViewHost(rvh); | |
| 138 if (!web_contents) | |
| 139 continue; | |
| 140 web_contents->ForEachFrame( | |
| 141 base::Bind(&AddRenderFrameID, visible_frame_ids)); | |
| 142 } | |
| 143 | |
| 144 BrowserThread::PostTask( | |
| 145 BrowserThread::IO, FROM_HERE, | |
| 146 base::Bind(&WorkerPrioritySetter::UpdateWorkerPrioritiesFromVisibleSet, | |
| 147 this, base::Owned(visible_frame_ids))); | |
| 148 } | |
| 149 | |
| 150 void WorkerPrioritySetter::UpdateWorkerPrioritiesFromVisibleSet( | |
| 151 const std::set<std::pair<int, int> >* visible_frame_ids) { | |
| 152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 153 | |
| 154 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | |
| 155 if (!iter->process_launched()) | |
| 156 continue; | |
| 157 bool throttle = true; | |
| 158 | |
| 159 for (WorkerProcessHost::Instances::const_iterator instance = | |
| 160 iter->instances().begin(); instance != iter->instances().end(); | |
| 161 ++instance) { | |
| 162 | |
| 163 // This code assumes one worker per process | |
| 164 WorkerProcessHost::Instances::const_iterator first_instance = | |
| 165 iter->instances().begin(); | |
| 166 if (first_instance == iter->instances().end()) | |
| 167 continue; | |
| 168 | |
| 169 WorkerDocumentSet::DocumentInfoSet::const_iterator info = | |
| 170 first_instance->worker_document_set()->documents().begin(); | |
| 171 | |
| 172 for (; info != first_instance->worker_document_set()->documents().end(); | |
| 173 ++info) { | |
| 174 std::pair<int, int> id( | |
| 175 info->render_process_id(), info->render_frame_id()); | |
| 176 if (visible_frame_ids->find(id) != visible_frame_ids->end()) { | |
| 177 throttle = false; | |
| 178 break; | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 if (!throttle ) { | |
| 183 break; | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 iter->SetBackgrounded(throttle); | |
| 188 } | |
| 189 } | |
| 190 | |
| 191 void WorkerPrioritySetter::OnRenderWidgetVisibilityChanged( | |
| 192 std::pair<int, int> id) { | |
| 193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 194 std::set<std::pair<int, int> > visible_frame_ids; | |
| 195 | |
| 196 visible_frame_ids.insert(id); | |
| 197 | |
| 198 UpdateWorkerPrioritiesFromVisibleSet(&visible_frame_ids); | |
| 199 } | |
| 200 | |
| 201 void WorkerPrioritySetter::RegisterObserver() { | |
| 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 203 registrar_.Add(this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, | |
| 204 NotificationService::AllBrowserContextsAndSources()); | |
| 205 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CREATED, | |
| 206 NotificationService::AllBrowserContextsAndSources()); | |
| 207 } | |
| 208 | |
| 209 void WorkerPrioritySetter::Observe(int type, | |
| 210 const NotificationSource& source, const NotificationDetails& details) { | |
| 211 if (type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED) { | |
| 212 bool visible = *Details<bool>(details).ptr(); | |
| 213 | |
| 214 if (visible) { | |
| 215 int render_widget_id = | |
| 216 Source<RenderWidgetHost>(source).ptr()->GetRoutingID(); | |
| 217 int render_process_pid = | |
| 218 Source<RenderWidgetHost>(source).ptr()->GetProcess()->GetID(); | |
| 219 | |
| 220 BrowserThread::PostTask( | |
| 221 BrowserThread::IO, FROM_HERE, | |
| 222 base::Bind(&WorkerPrioritySetter::OnRenderWidgetVisibilityChanged, | |
| 223 this, std::pair<int, int>(render_process_pid, render_widget_id))); | |
| 224 } | |
| 225 } | |
| 226 else if (type == NOTIFICATION_RENDERER_PROCESS_CREATED) { | |
| 227 PostTaskToGatherAndUpdateWorkerPriorities(); | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 WorkerService* WorkerService::GetInstance() { | |
| 232 if (EmbeddedSharedWorkerEnabled()) | |
| 233 return SharedWorkerServiceImpl::GetInstance(); | |
| 234 else | |
| 235 return WorkerServiceImpl::GetInstance(); | |
| 236 } | |
| 237 | |
| 238 bool WorkerService::EmbeddedSharedWorkerEnabled() { | |
| 239 static bool disabled = CommandLine::ForCurrentProcess()->HasSwitch( | |
| 240 switches::kDisableEmbeddedSharedWorker); | |
| 241 return !disabled; | |
| 242 } | |
| 243 | |
| 244 WorkerServiceImpl* WorkerServiceImpl::GetInstance() { | |
| 245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 246 return Singleton<WorkerServiceImpl>::get(); | |
| 247 } | |
| 248 | |
| 249 WorkerServiceImpl::WorkerServiceImpl() | |
| 250 : priority_setter_(new WorkerPrioritySetter()), | |
| 251 next_worker_route_id_(0) { | |
| 252 priority_setter_->Initialize(); | |
| 253 } | |
| 254 | |
| 255 WorkerServiceImpl::~WorkerServiceImpl() { | |
| 256 // The observers in observers_ can't be used here because they might be | |
| 257 // gone already. | |
| 258 } | |
| 259 | |
| 260 void WorkerServiceImpl::PerformTeardownForTesting() { | |
| 261 priority_setter_ = NULL; | |
| 262 } | |
| 263 | |
| 264 void WorkerServiceImpl::OnWorkerMessageFilterClosing( | |
| 265 WorkerMessageFilter* filter) { | |
| 266 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | |
| 267 iter->FilterShutdown(filter); | |
| 268 } | |
| 269 | |
| 270 // See if that process had any queued workers. | |
| 271 for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); | |
| 272 i != queued_workers_.end();) { | |
| 273 i->RemoveFilters(filter); | |
| 274 if (i->NumFilters() == 0) { | |
| 275 i = queued_workers_.erase(i); | |
| 276 } else { | |
| 277 ++i; | |
| 278 } | |
| 279 } | |
| 280 | |
| 281 // Either a worker proceess has shut down, in which case we can start one of | |
| 282 // the queued workers, or a renderer has shut down, in which case it doesn't | |
| 283 // affect anything. We call this function in both scenarios because then we | |
| 284 // don't have to keep track which filters are from worker processes. | |
| 285 TryStartingQueuedWorker(); | |
| 286 } | |
| 287 | |
| 288 void WorkerServiceImpl::CreateWorker( | |
| 289 const ViewHostMsg_CreateWorker_Params& params, | |
| 290 int route_id, | |
| 291 WorkerMessageFilter* filter, | |
| 292 ResourceContext* resource_context, | |
| 293 const WorkerStoragePartition& partition, | |
| 294 bool* url_mismatch) { | |
| 295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 296 *url_mismatch = false; | |
| 297 WorkerProcessHost::WorkerInstance* existing_instance = | |
| 298 FindSharedWorkerInstance( | |
| 299 params.url, params.name, partition, resource_context); | |
| 300 if (existing_instance) { | |
| 301 if (params.url != existing_instance->url()) { | |
| 302 *url_mismatch = true; | |
| 303 return; | |
| 304 } | |
| 305 if (existing_instance->load_failed()) { | |
| 306 filter->Send(new ViewMsg_WorkerScriptLoadFailed(route_id)); | |
| 307 return; | |
| 308 } | |
| 309 existing_instance->AddFilter(filter, route_id); | |
| 310 existing_instance->worker_document_set()->Add( | |
| 311 filter, params.document_id, filter->render_process_id(), | |
| 312 params.render_frame_route_id); | |
| 313 filter->Send(new ViewMsg_WorkerCreated(route_id)); | |
| 314 return; | |
| 315 } | |
| 316 for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); | |
| 317 i != queued_workers_.end(); ++i) { | |
| 318 if (i->Matches(params.url, params.name, partition, resource_context) && | |
| 319 params.url != i->url()) { | |
| 320 *url_mismatch = true; | |
| 321 return; | |
| 322 } | |
| 323 } | |
| 324 | |
| 325 // Generate a unique route id for the browser-worker communication that's | |
| 326 // unique among all worker processes. That way when the worker process sends | |
| 327 // a wrapped IPC message through us, we know which WorkerProcessHost to give | |
| 328 // it to. | |
| 329 WorkerProcessHost::WorkerInstance instance( | |
| 330 params.url, | |
| 331 params.name, | |
| 332 params.content_security_policy, | |
| 333 params.security_policy_type, | |
| 334 next_worker_route_id(), | |
| 335 params.render_frame_route_id, | |
| 336 resource_context, | |
| 337 partition); | |
| 338 instance.AddFilter(filter, route_id); | |
| 339 instance.worker_document_set()->Add( | |
| 340 filter, params.document_id, filter->render_process_id(), | |
| 341 params.render_frame_route_id); | |
| 342 | |
| 343 CreateWorkerFromInstance(instance); | |
| 344 } | |
| 345 | |
| 346 void WorkerServiceImpl::ForwardToWorker(const IPC::Message& message, | |
| 347 WorkerMessageFilter* filter) { | |
| 348 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | |
| 349 if (iter->FilterMessage(message, filter)) | |
| 350 return; | |
| 351 } | |
| 352 | |
| 353 // TODO(jabdelmalek): tell filter that callee is gone | |
| 354 } | |
| 355 | |
| 356 void WorkerServiceImpl::DocumentDetached(unsigned long long document_id, | |
| 357 WorkerMessageFilter* filter) { | |
| 358 // Any associated shared workers can be shut down. | |
| 359 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) | |
| 360 iter->DocumentDetached(filter, document_id); | |
| 361 | |
| 362 // Remove any queued shared workers for this document. | |
| 363 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); | |
| 364 iter != queued_workers_.end();) { | |
| 365 | |
| 366 iter->worker_document_set()->Remove(filter, document_id); | |
| 367 if (iter->worker_document_set()->IsEmpty()) { | |
| 368 iter = queued_workers_.erase(iter); | |
| 369 continue; | |
| 370 } | |
| 371 ++iter; | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 bool WorkerServiceImpl::CreateWorkerFromInstance( | |
| 376 WorkerProcessHost::WorkerInstance instance) { | |
| 377 if (!CanCreateWorkerProcess(instance)) { | |
| 378 queued_workers_.push_back(instance); | |
| 379 return true; | |
| 380 } | |
| 381 | |
| 382 // Remove any queued instances of this worker and copy over the filter to | |
| 383 // this instance. | |
| 384 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); | |
| 385 iter != queued_workers_.end();) { | |
| 386 if (iter->Matches(instance.url(), instance.name(), | |
| 387 instance.partition(), instance.resource_context())) { | |
| 388 DCHECK(iter->NumFilters() == 1); | |
| 389 DCHECK_EQ(instance.url(), iter->url()); | |
| 390 WorkerProcessHost::WorkerInstance::FilterInfo filter_info = | |
| 391 iter->GetFilter(); | |
| 392 instance.AddFilter(filter_info.filter(), filter_info.route_id()); | |
| 393 iter = queued_workers_.erase(iter); | |
| 394 } else { | |
| 395 ++iter; | |
| 396 } | |
| 397 } | |
| 398 | |
| 399 WorkerMessageFilter* first_filter = instance.filters().begin()->filter(); | |
| 400 WorkerProcessHost* worker = new WorkerProcessHost( | |
| 401 instance.resource_context(), instance.partition()); | |
| 402 // TODO(atwilson): This won't work if the message is from a worker process. | |
| 403 // We don't support that yet though (this message is only sent from | |
| 404 // renderers) but when we do, we'll need to add code to pass in the current | |
| 405 // worker's document set for nested workers. | |
| 406 if (!worker->Init(first_filter->render_process_id(), | |
| 407 instance.render_frame_id())) { | |
| 408 delete worker; | |
| 409 return false; | |
| 410 } | |
| 411 | |
| 412 worker->CreateWorker( | |
| 413 instance, | |
| 414 WorkerDevToolsManager::GetInstance()->WorkerCreated(worker, instance)); | |
| 415 FOR_EACH_OBSERVER( | |
| 416 WorkerServiceObserver, observers_, | |
| 417 WorkerCreated(instance.url(), instance.name(), worker->GetData().id, | |
| 418 instance.worker_route_id())); | |
| 419 return true; | |
| 420 } | |
| 421 | |
| 422 bool WorkerServiceImpl::CanCreateWorkerProcess( | |
| 423 const WorkerProcessHost::WorkerInstance& instance) { | |
| 424 // Worker can be fired off if *any* parent has room. | |
| 425 const WorkerDocumentSet::DocumentInfoSet& parents = | |
| 426 instance.worker_document_set()->documents(); | |
| 427 | |
| 428 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = | |
| 429 parents.begin(); | |
| 430 parent_iter != parents.end(); ++parent_iter) { | |
| 431 bool hit_total_worker_limit = false; | |
| 432 if (FrameCanCreateWorkerProcess(parent_iter->render_process_id(), | |
| 433 parent_iter->render_frame_id(), | |
| 434 &hit_total_worker_limit)) { | |
| 435 return true; | |
| 436 } | |
| 437 // Return false if already at the global worker limit (no need to continue | |
| 438 // checking parent tabs). | |
| 439 if (hit_total_worker_limit) | |
| 440 return false; | |
| 441 } | |
| 442 // If we've reached here, none of the parent tabs is allowed to create an | |
| 443 // instance. | |
| 444 return false; | |
| 445 } | |
| 446 | |
| 447 bool WorkerServiceImpl::FrameCanCreateWorkerProcess( | |
| 448 int render_process_id, | |
| 449 int render_frame_id, | |
| 450 bool* hit_total_worker_limit) { | |
| 451 int total_workers = 0; | |
| 452 int workers_per_tab = 0; | |
| 453 *hit_total_worker_limit = false; | |
| 454 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | |
| 455 for (WorkerProcessHost::Instances::const_iterator cur_instance = | |
| 456 iter->instances().begin(); | |
| 457 cur_instance != iter->instances().end(); ++cur_instance) { | |
| 458 total_workers++; | |
| 459 if (total_workers >= kMaxWorkersWhenSeparate) { | |
| 460 *hit_total_worker_limit = true; | |
| 461 return false; | |
| 462 } | |
| 463 if (cur_instance->FrameIsParent(render_process_id, render_frame_id)) { | |
| 464 workers_per_tab++; | |
| 465 if (workers_per_tab >= kMaxWorkersPerFrameWhenSeparate) | |
| 466 return false; | |
| 467 } | |
| 468 } | |
| 469 } | |
| 470 | |
| 471 return true; | |
| 472 } | |
| 473 | |
| 474 void WorkerServiceImpl::TryStartingQueuedWorker() { | |
| 475 if (queued_workers_.empty()) | |
| 476 return; | |
| 477 | |
| 478 for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); | |
| 479 i != queued_workers_.end();) { | |
| 480 if (CanCreateWorkerProcess(*i)) { | |
| 481 WorkerProcessHost::WorkerInstance instance = *i; | |
| 482 queued_workers_.erase(i); | |
| 483 CreateWorkerFromInstance(instance); | |
| 484 | |
| 485 // CreateWorkerFromInstance can modify the queued_workers_ list when it | |
| 486 // coalesces queued instances after starting a shared worker, so we | |
| 487 // have to rescan the list from the beginning (our iterator is now | |
| 488 // invalid). This is not a big deal as having any queued workers will be | |
| 489 // rare in practice so the list will be small. | |
| 490 i = queued_workers_.begin(); | |
| 491 } else { | |
| 492 ++i; | |
| 493 } | |
| 494 } | |
| 495 } | |
| 496 | |
| 497 bool WorkerServiceImpl::GetRendererForWorker(int worker_process_id, | |
| 498 int* render_process_id, | |
| 499 int* render_frame_id) const { | |
| 500 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | |
| 501 if (iter.GetData().id != worker_process_id) | |
| 502 continue; | |
| 503 | |
| 504 // This code assumes one worker per process, see function comment in header! | |
| 505 WorkerProcessHost::Instances::const_iterator first_instance = | |
| 506 iter->instances().begin(); | |
| 507 if (first_instance == iter->instances().end()) | |
| 508 return false; | |
| 509 | |
| 510 WorkerDocumentSet::DocumentInfoSet::const_iterator info = | |
| 511 first_instance->worker_document_set()->documents().begin(); | |
| 512 *render_process_id = info->render_process_id(); | |
| 513 *render_frame_id = info->render_frame_id(); | |
| 514 return true; | |
| 515 } | |
| 516 return false; | |
| 517 } | |
| 518 | |
| 519 const WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindWorkerInstance( | |
| 520 int worker_process_id) { | |
| 521 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | |
| 522 if (iter.GetData().id != worker_process_id) | |
| 523 continue; | |
| 524 | |
| 525 WorkerProcessHost::Instances::const_iterator instance = | |
| 526 iter->instances().begin(); | |
| 527 return instance == iter->instances().end() ? NULL : &*instance; | |
| 528 } | |
| 529 return NULL; | |
| 530 } | |
| 531 | |
| 532 bool WorkerServiceImpl::TerminateWorker(int process_id, int route_id) { | |
| 533 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | |
| 534 if (iter.GetData().id == process_id) { | |
| 535 iter->TerminateWorker(route_id); | |
| 536 return true; | |
| 537 } | |
| 538 } | |
| 539 return false; | |
| 540 } | |
| 541 | |
| 542 std::vector<WorkerService::WorkerInfo> WorkerServiceImpl::GetWorkers() { | |
| 543 std::vector<WorkerService::WorkerInfo> results; | |
| 544 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | |
| 545 const WorkerProcessHost::Instances& instances = (*iter)->instances(); | |
| 546 for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); | |
| 547 i != instances.end(); ++i) { | |
| 548 WorkerService::WorkerInfo info; | |
| 549 info.url = i->url(); | |
| 550 info.name = i->name(); | |
| 551 info.route_id = i->worker_route_id(); | |
| 552 info.process_id = iter.GetData().id; | |
| 553 info.handle = iter.GetData().handle; | |
| 554 results.push_back(info); | |
| 555 } | |
| 556 } | |
| 557 return results; | |
| 558 } | |
| 559 | |
| 560 void WorkerServiceImpl::AddObserver(WorkerServiceObserver* observer) { | |
| 561 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 562 observers_.AddObserver(observer); | |
| 563 } | |
| 564 | |
| 565 void WorkerServiceImpl::RemoveObserver(WorkerServiceObserver* observer) { | |
| 566 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 567 observers_.RemoveObserver(observer); | |
| 568 } | |
| 569 | |
| 570 void WorkerServiceImpl::NotifyWorkerDestroyed( | |
| 571 WorkerProcessHost* process, | |
| 572 int worker_route_id) { | |
| 573 WorkerDevToolsManager::GetInstance()->WorkerDestroyed( | |
| 574 process, worker_route_id); | |
| 575 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, | |
| 576 WorkerDestroyed(process->GetData().id, worker_route_id)); | |
| 577 } | |
| 578 | |
| 579 void WorkerServiceImpl::NotifyWorkerProcessCreated() { | |
| 580 priority_setter_->NotifyWorkerProcessCreated(); | |
| 581 } | |
| 582 | |
| 583 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( | |
| 584 const GURL& url, | |
| 585 const base::string16& name, | |
| 586 const WorkerStoragePartition& partition, | |
| 587 ResourceContext* resource_context) { | |
| 588 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | |
| 589 for (WorkerProcessHost::Instances::iterator instance_iter = | |
| 590 iter->mutable_instances().begin(); | |
| 591 instance_iter != iter->mutable_instances().end(); | |
| 592 ++instance_iter) { | |
| 593 if (instance_iter->Matches(url, name, partition, resource_context)) | |
| 594 return &(*instance_iter); | |
| 595 } | |
| 596 } | |
| 597 return NULL; | |
| 598 } | |
| 599 | |
| 600 } // namespace content | |
| OLD | NEW |