• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SharedWorkerWebApplicationCacheHostImpl(blink::WebApplicationCacheHostClient * client)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.
willStartMainResourceRequest(blink::WebURLRequest &,const blink::WebApplicationCacheHost *)38   virtual void willStartMainResourceRequest(
39       blink::WebURLRequest&,
40       const blink::WebApplicationCacheHost*) {}
didReceiveResponseForMainResource(const blink::WebURLResponse &)41   virtual void didReceiveResponseForMainResource(const blink::WebURLResponse&) {
42   }
didReceiveDataForMainResource(const char * data,int len)43   virtual void didReceiveDataForMainResource(const char* data, int len) {}
didFinishLoadingMainResource(bool success)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.
selectCacheWithoutManifest()49   virtual void selectCacheWithoutManifest() {}
selectCacheWithManifest(const blink::WebURL & manifestURL)50   virtual bool selectCacheWithManifest(const blink::WebURL& manifestURL) {
51     return true;
52   }
53 };
54 }
55 
EmbeddedSharedWorkerStub(const GURL & url,const base::string16 & name,const base::string16 & content_security_policy,blink::WebContentSecurityPolicyType security_policy_type,bool pause_on_start,int route_id)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 
~EmbeddedSharedWorkerStub()77 EmbeddedSharedWorkerStub::~EmbeddedSharedWorkerStub() {
78   RenderThreadImpl::current()->RemoveEmbeddedWorkerRoute(route_id_);
79 }
80 
OnMessageReceived(const IPC::Message & message)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 
OnChannelError()95 void EmbeddedSharedWorkerStub::OnChannelError() {
96   OnTerminateWorkerContext();
97 }
98 
workerReadyForInspection()99 void EmbeddedSharedWorkerStub::workerReadyForInspection() {
100   Send(new WorkerHostMsg_WorkerReadyForInspection(route_id_));
101 }
102 
workerScriptLoaded()103 void EmbeddedSharedWorkerStub::workerScriptLoaded() {
104   Send(new WorkerHostMsg_WorkerScriptLoaded(route_id_));
105   runing_ = true;
106   // Process any pending connections.
107   for (PendingChannelList::const_iterator iter = pending_channels_.begin();
108        iter != pending_channels_.end();
109        ++iter) {
110     ConnectToChannel(*iter);
111   }
112   pending_channels_.clear();
113 }
114 
workerScriptLoadFailed()115 void EmbeddedSharedWorkerStub::workerScriptLoadFailed() {
116   Send(new WorkerHostMsg_WorkerScriptLoadFailed(route_id_));
117   for (PendingChannelList::const_iterator iter = pending_channels_.begin();
118        iter != pending_channels_.end();
119        ++iter) {
120     blink::WebMessagePortChannel* channel = *iter;
121     channel->destroy();
122   }
123   pending_channels_.clear();
124   Shutdown();
125 }
126 
workerContextClosed()127 void EmbeddedSharedWorkerStub::workerContextClosed() {
128   Send(new WorkerHostMsg_WorkerContextClosed(route_id_));
129 }
130 
workerContextDestroyed()131 void EmbeddedSharedWorkerStub::workerContextDestroyed() {
132   Send(new WorkerHostMsg_WorkerContextDestroyed(route_id_));
133   Shutdown();
134 }
135 
selectAppCacheID(long long app_cache_id)136 void EmbeddedSharedWorkerStub::selectAppCacheID(long long app_cache_id) {
137   if (app_cache_host_) {
138     // app_cache_host_ could become stale as it's owned by blink's
139     // DocumentLoader. This method is assumed to be called while it's valid.
140     app_cache_host_->backend()->SelectCacheForSharedWorker(
141         app_cache_host_->host_id(), app_cache_id);
142   }
143 }
144 
145 blink::WebNotificationPresenter*
notificationPresenter()146 EmbeddedSharedWorkerStub::notificationPresenter() {
147   // TODO(horo): delete this method if we have no plan to implement this.
148   NOTREACHED();
149   return NULL;
150 }
151 
152 blink::WebApplicationCacheHost*
createApplicationCacheHost(blink::WebApplicationCacheHostClient * client)153 EmbeddedSharedWorkerStub::createApplicationCacheHost(
154     blink::WebApplicationCacheHostClient* client) {
155   app_cache_host_ = new SharedWorkerWebApplicationCacheHostImpl(client);
156   return app_cache_host_;
157 }
158 
159 blink::WebWorkerPermissionClientProxy*
createWorkerPermissionClientProxy(const blink::WebSecurityOrigin & origin)160     EmbeddedSharedWorkerStub::createWorkerPermissionClientProxy(
161     const blink::WebSecurityOrigin& origin) {
162   return new EmbeddedSharedWorkerPermissionClientProxy(
163       GURL(origin.toString()),
164       origin.isUnique(),
165       route_id_,
166       ChildThread::current()->thread_safe_sender());
167 }
168 
dispatchDevToolsMessage(const blink::WebString & message)169 void EmbeddedSharedWorkerStub::dispatchDevToolsMessage(
170       const blink::WebString& message) {
171   worker_devtools_agent_->SendDevToolsMessage(message);
172 }
173 
saveDevToolsAgentState(const blink::WebString & state)174 void EmbeddedSharedWorkerStub::saveDevToolsAgentState(
175       const blink::WebString& state) {
176   worker_devtools_agent_->SaveDevToolsAgentState(state);
177 }
178 
Shutdown()179 void EmbeddedSharedWorkerStub::Shutdown() {
180   delete this;
181 }
182 
Send(IPC::Message * message)183 bool EmbeddedSharedWorkerStub::Send(IPC::Message* message) {
184   return RenderThreadImpl::current()->Send(message);
185 }
186 
ConnectToChannel(WebMessagePortChannelImpl * channel)187 void EmbeddedSharedWorkerStub::ConnectToChannel(
188     WebMessagePortChannelImpl* channel) {
189   impl_->connect(channel);
190   Send(
191       new WorkerHostMsg_WorkerConnected(channel->message_port_id(), route_id_));
192 }
193 
OnConnect(int sent_message_port_id,int routing_id)194 void EmbeddedSharedWorkerStub::OnConnect(int sent_message_port_id,
195                                          int routing_id) {
196   WebMessagePortChannelImpl* channel =
197       new WebMessagePortChannelImpl(routing_id,
198                                     sent_message_port_id,
199                                     base::MessageLoopProxy::current().get());
200   if (runing_) {
201     ConnectToChannel(channel);
202   } else {
203     // If two documents try to load a SharedWorker at the same time, the
204     // WorkerMsg_Connect for one of the documents can come in before the
205     // worker is started. Just queue up the connect and deliver it once the
206     // worker starts.
207     pending_channels_.push_back(channel);
208   }
209 }
210 
OnTerminateWorkerContext()211 void EmbeddedSharedWorkerStub::OnTerminateWorkerContext() {
212   runing_ = false;
213   impl_->terminateWorkerContext();
214 }
215 
216 }  // namespace content
217