Home | History | Annotate | Download | only in shared_worker
      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
      3 // found in the LICENSE file.
      4 
      5 #include "content/renderer/shared_worker/embedded_shared_worker_stub.h"
      6 
      7 #include "base/message_loop/message_loop_proxy.h"
      8 #include "content/child/appcache/appcache_dispatcher.h"
      9 #include "content/child/appcache/web_application_cache_host_impl.h"
     10 #include "content/child/scoped_child_process_reference.h"
     11 #include "content/child/shared_worker_devtools_agent.h"
     12 #include "content/child/webmessageportchannel_impl.h"
     13 #include "content/common/worker_messages.h"
     14 #include "content/renderer/render_thread_impl.h"
     15 #include "content/renderer/shared_worker/embedded_shared_worker_permission_client_proxy.h"
     16 #include "ipc/ipc_message_macros.h"
     17 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
     18 #include "third_party/WebKit/public/web/WebSharedWorker.h"
     19 #include "third_party/WebKit/public/web/WebSharedWorkerClient.h"
     20 
     21 namespace content {
     22 
     23 namespace {
     24 
     25 class SharedWorkerWebApplicationCacheHostImpl
     26     : public WebApplicationCacheHostImpl {
     27  public:
     28   SharedWorkerWebApplicationCacheHostImpl(
     29       blink::WebApplicationCacheHostClient* client)
     30       : WebApplicationCacheHostImpl(client,
     31                                     RenderThreadImpl::current()
     32                                         ->appcache_dispatcher()
     33                                         ->backend_proxy()) {}
     34 
     35   // Main resource loading is different for workers. The main resource is
     36   // loaded by the worker using WorkerScriptLoader.
     37   // These overrides are stubbed out.
     38   virtual void willStartMainResourceRequest(
     39       blink::WebURLRequest&,
     40       const blink::WebApplicationCacheHost*) {}
     41   virtual void didReceiveResponseForMainResource(const blink::WebURLResponse&) {
     42   }
     43   virtual void didReceiveDataForMainResource(const char* data, int len) {}
     44   virtual void didFinishLoadingMainResource(bool success) {}
     45 
     46   // Cache selection is also different for workers. We know at construction
     47   // time what cache to select and do so then.
     48   // These overrides are stubbed out.
     49   virtual void selectCacheWithoutManifest() {}
     50   virtual bool selectCacheWithManifest(const blink::WebURL& manifestURL) {
     51     return true;
     52   }
     53 };
     54 }
     55 
     56 EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
     57     const GURL& url,
     58     const base::string16& name,
     59     const base::string16& content_security_policy,
     60     blink::WebContentSecurityPolicyType security_policy_type,
     61     bool pause_on_start,
     62     int route_id)
     63     : route_id_(route_id), name_(name), runing_(false), url_(url) {
     64   RenderThreadImpl::current()->AddEmbeddedWorkerRoute(route_id_, this);
     65   impl_ = blink::WebSharedWorker::create(this);
     66   if (pause_on_start) {
     67     // Pause worker context when it starts and wait until either DevTools client
     68     // is attached or explicit resume notification is received.
     69     impl_->pauseWorkerContextOnStart();
     70   }
     71   worker_devtools_agent_.reset(
     72       new SharedWorkerDevToolsAgent(route_id, impl_));
     73   impl_->startWorkerContext(url, name_,
     74                             content_security_policy, security_policy_type);
     75 }
     76 
     77 EmbeddedSharedWorkerStub::~EmbeddedSharedWorkerStub() {
     78   RenderThreadImpl::current()->RemoveEmbeddedWorkerRoute(route_id_);
     79 }
     80 
     81 bool EmbeddedSharedWorkerStub::OnMessageReceived(
     82     const IPC::Message& message) {
     83   if (worker_devtools_agent_->OnMessageReceived(message))
     84     return true;
     85   bool handled = true;
     86   IPC_BEGIN_MESSAGE_MAP(EmbeddedSharedWorkerStub, message)
     87     IPC_MESSAGE_HANDLER(WorkerMsg_TerminateWorkerContext,
     88                         OnTerminateWorkerContext)
     89     IPC_MESSAGE_HANDLER(WorkerMsg_Connect, OnConnect)
     90     IPC_MESSAGE_UNHANDLED(handled = false)
     91   IPC_END_MESSAGE_MAP()
     92   return handled;
     93 }
     94 
     95 void EmbeddedSharedWorkerStub::OnChannelError() {
     96   OnTerminateWorkerContext();
     97 }
     98 
     99 void EmbeddedSharedWorkerStub::workerScriptLoaded() {
    100   Send(new WorkerHostMsg_WorkerScriptLoaded(route_id_));
    101   runing_ = true;
    102   // Process any pending connections.
    103   for (PendingChannelList::const_iterator iter = pending_channels_.begin();
    104        iter != pending_channels_.end();
    105        ++iter) {
    106     ConnectToChannel(*iter);
    107   }
    108   pending_channels_.clear();
    109 }
    110 
    111 void EmbeddedSharedWorkerStub::workerScriptLoadFailed() {
    112   Send(new WorkerHostMsg_WorkerScriptLoadFailed(route_id_));
    113   for (PendingChannelList::const_iterator iter = pending_channels_.begin();
    114        iter != pending_channels_.end();
    115        ++iter) {
    116     blink::WebMessagePortChannel* channel = *iter;
    117     channel->destroy();
    118   }
    119   pending_channels_.clear();
    120   Shutdown();
    121 }
    122 
    123 void EmbeddedSharedWorkerStub::workerContextClosed() {
    124   Send(new WorkerHostMsg_WorkerContextClosed(route_id_));
    125 }
    126 
    127 void EmbeddedSharedWorkerStub::workerContextDestroyed() {
    128   Send(new WorkerHostMsg_WorkerContextDestroyed(route_id_));
    129   Shutdown();
    130 }
    131 
    132 void EmbeddedSharedWorkerStub::selectAppCacheID(long long app_cache_id) {
    133   if (app_cache_host_) {
    134     // app_cache_host_ could become stale as it's owned by blink's
    135     // DocumentLoader. This method is assumed to be called while it's valid.
    136     app_cache_host_->backend()->SelectCacheForSharedWorker(
    137         app_cache_host_->host_id(), app_cache_id);
    138   }
    139 }
    140 
    141 blink::WebNotificationPresenter*
    142 EmbeddedSharedWorkerStub::notificationPresenter() {
    143   // TODO(horo): delete this method if we have no plan to implement this.
    144   NOTREACHED();
    145   return NULL;
    146 }
    147 
    148 blink::WebApplicationCacheHost*
    149 EmbeddedSharedWorkerStub::createApplicationCacheHost(
    150     blink::WebApplicationCacheHostClient* client) {
    151   app_cache_host_ = new SharedWorkerWebApplicationCacheHostImpl(client);
    152   return app_cache_host_;
    153 }
    154 
    155 blink::WebWorkerPermissionClientProxy*
    156     EmbeddedSharedWorkerStub::createWorkerPermissionClientProxy(
    157     const blink::WebSecurityOrigin& origin) {
    158   return new EmbeddedSharedWorkerPermissionClientProxy(
    159       GURL(origin.toString()),
    160       origin.isUnique(),
    161       route_id_,
    162       ChildThread::current()->thread_safe_sender());
    163 }
    164 
    165 void EmbeddedSharedWorkerStub::dispatchDevToolsMessage(
    166       const blink::WebString& message) {
    167   worker_devtools_agent_->SendDevToolsMessage(message);
    168 }
    169 
    170 void EmbeddedSharedWorkerStub::saveDevToolsAgentState(
    171       const blink::WebString& state) {
    172   worker_devtools_agent_->SaveDevToolsAgentState(state);
    173 }
    174 
    175 void EmbeddedSharedWorkerStub::Shutdown() {
    176   delete this;
    177 }
    178 
    179 bool EmbeddedSharedWorkerStub::Send(IPC::Message* message) {
    180   return RenderThreadImpl::current()->Send(message);
    181 }
    182 
    183 void EmbeddedSharedWorkerStub::ConnectToChannel(
    184     WebMessagePortChannelImpl* channel) {
    185   impl_->connect(channel);
    186   Send(
    187       new WorkerHostMsg_WorkerConnected(channel->message_port_id(), route_id_));
    188 }
    189 
    190 void EmbeddedSharedWorkerStub::OnConnect(int sent_message_port_id,
    191                                          int routing_id) {
    192   WebMessagePortChannelImpl* channel =
    193       new WebMessagePortChannelImpl(routing_id,
    194                                     sent_message_port_id,
    195                                     base::MessageLoopProxy::current().get());
    196   if (runing_) {
    197     ConnectToChannel(channel);
    198   } else {
    199     // If two documents try to load a SharedWorker at the same time, the
    200     // WorkerMsg_Connect for one of the documents can come in before the
    201     // worker is started. Just queue up the connect and deliver it once the
    202     // worker starts.
    203     pending_channels_.push_back(channel);
    204   }
    205 }
    206 
    207 void EmbeddedSharedWorkerStub::OnTerminateWorkerContext() {
    208   runing_ = false;
    209   impl_->terminateWorkerContext();
    210 }
    211 
    212 }  // namespace content
    213