Home | History | Annotate | Download | only in service_worker
      1 // Copyright 2013 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/service_worker/embedded_worker_registry.h"
      6 
      7 #include "base/bind_helpers.h"
      8 #include "base/stl_util.h"
      9 #include "content/browser/renderer_host/render_widget_helper.h"
     10 #include "content/browser/service_worker/embedded_worker_instance.h"
     11 #include "content/browser/service_worker/service_worker_context_core.h"
     12 #include "content/browser/service_worker/service_worker_context_wrapper.h"
     13 #include "content/common/service_worker/embedded_worker_messages.h"
     14 #include "content/public/browser/browser_thread.h"
     15 #include "ipc/ipc_message.h"
     16 #include "ipc/ipc_sender.h"
     17 
     18 namespace content {
     19 
     20 EmbeddedWorkerRegistry::EmbeddedWorkerRegistry(
     21     base::WeakPtr<ServiceWorkerContextCore> context)
     22     : context_(context), next_embedded_worker_id_(0) {
     23 }
     24 
     25 scoped_ptr<EmbeddedWorkerInstance> EmbeddedWorkerRegistry::CreateWorker() {
     26   scoped_ptr<EmbeddedWorkerInstance> worker(
     27       new EmbeddedWorkerInstance(context_, next_embedded_worker_id_));
     28   worker_map_[next_embedded_worker_id_++] = worker.get();
     29   return worker.Pass();
     30 }
     31 
     32 ServiceWorkerStatusCode EmbeddedWorkerRegistry::StopWorker(
     33     int process_id, int embedded_worker_id) {
     34   return Send(process_id,
     35               new EmbeddedWorkerMsg_StopWorker(embedded_worker_id));
     36 }
     37 
     38 bool EmbeddedWorkerRegistry::OnMessageReceived(const IPC::Message& message) {
     39   // TODO(kinuko): Move all EmbeddedWorker message handling from
     40   // ServiceWorkerDispatcherHost.
     41 
     42   WorkerInstanceMap::iterator found = worker_map_.find(message.routing_id());
     43   if (found == worker_map_.end()) {
     44     LOG(ERROR) << "Worker " << message.routing_id() << " not registered";
     45     return false;
     46   }
     47   return found->second->OnMessageReceived(message);
     48 }
     49 
     50 void EmbeddedWorkerRegistry::Shutdown() {
     51   for (WorkerInstanceMap::iterator it = worker_map_.begin();
     52        it != worker_map_.end();
     53        ++it) {
     54     it->second->Stop();
     55   }
     56 }
     57 
     58 void EmbeddedWorkerRegistry::OnWorkerScriptLoaded(int process_id,
     59                                                   int embedded_worker_id) {
     60   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
     61   if (found == worker_map_.end()) {
     62     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
     63     return;
     64   }
     65   if (found->second->process_id() != process_id) {
     66     LOG(ERROR) << "Incorrect embedded_worker_id";
     67     return;
     68   }
     69   found->second->OnScriptLoaded();
     70 }
     71 
     72 void EmbeddedWorkerRegistry::OnWorkerScriptLoadFailed(int process_id,
     73                                                       int embedded_worker_id) {
     74   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
     75   if (found == worker_map_.end()) {
     76     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
     77     return;
     78   }
     79   if (found->second->process_id() != process_id) {
     80     LOG(ERROR) << "Incorrect embedded_worker_id";
     81     return;
     82   }
     83   found->second->OnScriptLoadFailed();
     84 }
     85 
     86 void EmbeddedWorkerRegistry::OnWorkerStarted(
     87     int process_id, int thread_id, int embedded_worker_id) {
     88   DCHECK(!ContainsKey(worker_process_map_, process_id) ||
     89          worker_process_map_[process_id].count(embedded_worker_id) == 0);
     90   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
     91   if (found == worker_map_.end()) {
     92     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
     93     return;
     94   }
     95   if (found->second->process_id() != process_id) {
     96     LOG(ERROR) << "Incorrect embedded_worker_id";
     97     return;
     98   }
     99   worker_process_map_[process_id].insert(embedded_worker_id);
    100   found->second->OnStarted(thread_id);
    101 }
    102 
    103 void EmbeddedWorkerRegistry::OnWorkerStopped(
    104     int process_id, int embedded_worker_id) {
    105   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
    106   if (found == worker_map_.end()) {
    107     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
    108     return;
    109   }
    110   if (found->second->process_id() != process_id) {
    111     LOG(ERROR) << "Incorrect embedded_worker_id";
    112     return;
    113   }
    114   worker_process_map_[process_id].erase(embedded_worker_id);
    115   found->second->OnStopped();
    116 }
    117 
    118 void EmbeddedWorkerRegistry::OnReportException(
    119     int embedded_worker_id,
    120     const base::string16& error_message,
    121     int line_number,
    122     int column_number,
    123     const GURL& source_url) {
    124   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
    125   if (found == worker_map_.end()) {
    126     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
    127     return;
    128   }
    129   found->second->OnReportException(
    130       error_message, line_number, column_number, source_url);
    131 }
    132 
    133 void EmbeddedWorkerRegistry::OnReportConsoleMessage(
    134     int embedded_worker_id,
    135     int source_identifier,
    136     int message_level,
    137     const base::string16& message,
    138     int line_number,
    139     const GURL& source_url) {
    140   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
    141   if (found == worker_map_.end()) {
    142     LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
    143     return;
    144   }
    145   found->second->OnReportConsoleMessage(
    146       source_identifier, message_level, message, line_number, source_url);
    147 }
    148 
    149 void EmbeddedWorkerRegistry::AddChildProcessSender(
    150     int process_id, IPC::Sender* sender) {
    151   process_sender_map_[process_id] = sender;
    152   DCHECK(!ContainsKey(worker_process_map_, process_id));
    153 }
    154 
    155 void EmbeddedWorkerRegistry::RemoveChildProcessSender(int process_id) {
    156   process_sender_map_.erase(process_id);
    157   std::map<int, std::set<int> >::iterator found =
    158       worker_process_map_.find(process_id);
    159   if (found != worker_process_map_.end()) {
    160     const std::set<int>& worker_set = worker_process_map_[process_id];
    161     for (std::set<int>::const_iterator it = worker_set.begin();
    162          it != worker_set.end();
    163          ++it) {
    164       int embedded_worker_id = *it;
    165       DCHECK(ContainsKey(worker_map_, embedded_worker_id));
    166       worker_map_[embedded_worker_id]->OnStopped();
    167     }
    168     worker_process_map_.erase(found);
    169   }
    170 }
    171 
    172 EmbeddedWorkerInstance* EmbeddedWorkerRegistry::GetWorker(
    173     int embedded_worker_id) {
    174   WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
    175   if (found == worker_map_.end())
    176     return NULL;
    177   return found->second;
    178 }
    179 
    180 EmbeddedWorkerRegistry::~EmbeddedWorkerRegistry() {
    181   Shutdown();
    182 }
    183 
    184 void EmbeddedWorkerRegistry::SendStartWorker(
    185     scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
    186     const StatusCallback& callback,
    187     int process_id) {
    188   // The ServiceWorkerDispatcherHost is supposed to be created when the process
    189   // is created, and keep an entry in process_sender_map_ for its whole
    190   // lifetime.
    191   DCHECK(ContainsKey(process_sender_map_, process_id));
    192   callback.Run(Send(process_id, new EmbeddedWorkerMsg_StartWorker(*params)));
    193 }
    194 
    195 ServiceWorkerStatusCode EmbeddedWorkerRegistry::Send(
    196     int process_id, IPC::Message* message_ptr) {
    197   scoped_ptr<IPC::Message> message(message_ptr);
    198   if (!context_)
    199     return SERVICE_WORKER_ERROR_ABORT;
    200   ProcessToSenderMap::iterator found = process_sender_map_.find(process_id);
    201   if (found == process_sender_map_.end())
    202     return SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND;
    203   if (!found->second->Send(message.release()))
    204     return SERVICE_WORKER_ERROR_IPC_FAILED;
    205   return SERVICE_WORKER_OK;
    206 }
    207 
    208 void EmbeddedWorkerRegistry::RemoveWorker(int process_id,
    209                                           int embedded_worker_id) {
    210   DCHECK(ContainsKey(worker_map_, embedded_worker_id));
    211   worker_map_.erase(embedded_worker_id);
    212   worker_process_map_.erase(process_id);
    213 }
    214 
    215 }  // namespace content
    216