Home | History | Annotate | Download | only in worker
      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/worker/websharedworker_stub.h"
      6 
      7 #include "base/command_line.h"
      8 #include "base/compiler_specific.h"
      9 #include "content/child/child_process.h"
     10 #include "content/child/child_thread.h"
     11 #include "content/child/fileapi/file_system_dispatcher.h"
     12 #include "content/child/shared_worker_devtools_agent.h"
     13 #include "content/child/webmessageportchannel_impl.h"
     14 #include "content/common/worker_messages.h"
     15 #include "content/public/common/content_switches.h"
     16 #include "content/worker/worker_thread.h"
     17 #include "third_party/WebKit/public/platform/WebString.h"
     18 #include "third_party/WebKit/public/platform/WebURL.h"
     19 #include "third_party/WebKit/public/web/WebSharedWorker.h"
     20 
     21 namespace content {
     22 
     23 WebSharedWorkerStub::WebSharedWorkerStub(
     24     const GURL& url,
     25     const base::string16& name,
     26     const base::string16& content_security_policy,
     27     blink::WebContentSecurityPolicyType security_policy_type,
     28     bool pause_on_start,
     29     int route_id)
     30     : route_id_(route_id),
     31       client_(route_id, this),
     32       running_(false),
     33       url_(url) {
     34 
     35   WorkerThread* worker_thread = WorkerThread::current();
     36   DCHECK(worker_thread);
     37   worker_thread->AddWorkerStub(this);
     38   // Start processing incoming IPCs for this worker.
     39   worker_thread->GetRouter()->AddRoute(route_id_, this);
     40 
     41   // TODO(atwilson): Add support for NaCl when they support MessagePorts.
     42   impl_ = blink::WebSharedWorker::create(client());
     43   if (pause_on_start) {
     44     // Pause worker context when it starts and wait until either DevTools client
     45     // is attached or explicit resume notification is received.
     46     impl_->pauseWorkerContextOnStart();
     47   }
     48 
     49   worker_devtools_agent_.reset(new SharedWorkerDevToolsAgent(route_id, impl_));
     50   client()->set_devtools_agent(worker_devtools_agent_.get());
     51   impl_->startWorkerContext(url_, name,
     52                             content_security_policy, security_policy_type);
     53 }
     54 
     55 WebSharedWorkerStub::~WebSharedWorkerStub() {
     56   impl_->clientDestroyed();
     57   WorkerThread* worker_thread = WorkerThread::current();
     58   DCHECK(worker_thread);
     59   worker_thread->RemoveWorkerStub(this);
     60   worker_thread->GetRouter()->RemoveRoute(route_id_);
     61 }
     62 
     63 void WebSharedWorkerStub::Shutdown() {
     64   // The worker has exited - free ourselves and the client.
     65   delete this;
     66 }
     67 
     68 void WebSharedWorkerStub::EnsureWorkerContextTerminates() {
     69   client_.EnsureWorkerContextTerminates();
     70 }
     71 
     72 bool WebSharedWorkerStub::OnMessageReceived(const IPC::Message& message) {
     73   if (worker_devtools_agent_->OnMessageReceived(message))
     74     return true;
     75 
     76   bool handled = true;
     77   IPC_BEGIN_MESSAGE_MAP(WebSharedWorkerStub, message)
     78     IPC_MESSAGE_HANDLER(WorkerMsg_TerminateWorkerContext,
     79                         OnTerminateWorkerContext)
     80     IPC_MESSAGE_HANDLER(WorkerMsg_Connect, OnConnect)
     81     IPC_MESSAGE_UNHANDLED(handled = false)
     82   IPC_END_MESSAGE_MAP()
     83   return handled;
     84 }
     85 
     86 void WebSharedWorkerStub::OnChannelError() {
     87     OnTerminateWorkerContext();
     88 }
     89 
     90 const GURL& WebSharedWorkerStub::url() {
     91   return url_;
     92 }
     93 
     94 void WebSharedWorkerStub::OnConnect(int sent_message_port_id, int routing_id) {
     95   WebMessagePortChannelImpl* channel =
     96       new WebMessagePortChannelImpl(routing_id,
     97                                     sent_message_port_id,
     98                                     base::MessageLoopProxy::current().get());
     99   if (running_) {
    100     impl_->connect(channel);
    101     WorkerThread::current()->Send(
    102         new WorkerHostMsg_WorkerConnected(channel->message_port_id(),
    103                                           route_id_));
    104   } else {
    105     // If two documents try to load a SharedWorker at the same time, the
    106     // WorkerMsg_Connect for one of the documents can come in before the
    107     // worker is started. Just queue up the connect and deliver it once the
    108     // worker starts.
    109     pending_channels_.push_back(channel);
    110   }
    111 }
    112 
    113 void WebSharedWorkerStub::OnTerminateWorkerContext() {
    114   running_ = false;
    115   // Call the client to make sure context exits.
    116   EnsureWorkerContextTerminates();
    117   // This may call "delete this" via WorkerScriptLoadFailed and Shutdown.
    118   impl_->terminateWorkerContext();
    119 }
    120 
    121 void WebSharedWorkerStub::WorkerScriptLoaded() {
    122   running_ = true;
    123   // Process any pending connections.
    124   for (PendingChannelList::const_iterator iter = pending_channels_.begin();
    125        iter != pending_channels_.end();
    126        ++iter) {
    127     impl_->connect(*iter);
    128     WorkerThread::current()->Send(
    129         new WorkerHostMsg_WorkerConnected((*iter)->message_port_id(),
    130                                           route_id_));
    131   }
    132   pending_channels_.clear();
    133 }
    134 
    135 void WebSharedWorkerStub::WorkerScriptLoadFailed() {
    136   for (PendingChannelList::const_iterator iter = pending_channels_.begin();
    137        iter != pending_channels_.end();
    138        ++iter) {
    139     blink::WebMessagePortChannel* channel = *iter;
    140     channel->destroy();
    141   }
    142   pending_channels_.clear();
    143   Shutdown();
    144 }
    145 
    146 }  // namespace content
    147