1 // Copyright (c) 2011 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.
5 #include "content/renderer/websharedworker_proxy.h"
6 #include "content/common/child_thread.h"
7 #include "content/common/view_messages.h"
8 #include "content/common/webmessageportchannel_impl.h"
9 #include "content/common/worker_messages.h"
10 #include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h"
11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSharedWorkerClient.h"
15 WebSharedWorkerProxy::WebSharedWorkerProxy(ChildThread
* child_thread
,
16 unsigned long long document_id
,
19 int render_view_route_id
)
20 : route_id_(exists
? route_id
: MSG_ROUTING_NONE
),
21 render_view_route_id_(render_view_route_id
),
22 child_thread_(child_thread
),
23 document_id_(document_id
),
24 pending_route_id_(route_id
),
25 connect_listener_(NULL
) {
26 if (route_id_
!= MSG_ROUTING_NONE
)
27 child_thread_
->AddRoute(route_id_
, this);
30 WebSharedWorkerProxy::~WebSharedWorkerProxy() {
33 // Free up any unsent queued messages.
34 for (size_t i
= 0; i
< queued_messages_
.size(); ++i
)
35 delete queued_messages_
[i
];
38 void WebSharedWorkerProxy::Disconnect() {
39 if (route_id_
== MSG_ROUTING_NONE
)
42 // So the messages from WorkerContext (like WorkerContextDestroyed) do not
43 // come after nobody is listening. Since Worker and WorkerContext can
44 // terminate independently, already sent messages may still be in the pipe.
45 child_thread_
->RemoveRoute(route_id_
);
47 route_id_
= MSG_ROUTING_NONE
;
50 void WebSharedWorkerProxy::CreateWorkerContext(
51 const GURL
& script_url
,
54 const string16
& user_agent
,
55 const string16
& source_code
,
56 const string16
& content_security_policy
,
57 WebKit::WebContentSecurityPolicyType policy_type
,
59 int64 script_resource_appcache_id
) {
60 DCHECK(route_id_
== MSG_ROUTING_NONE
);
61 ViewHostMsg_CreateWorker_Params params
;
62 params
.url
= script_url
;
64 params
.document_id
= document_id_
;
65 params
.render_view_route_id
= render_view_route_id_
;
66 params
.route_id
= pending_route_id
;
67 params
.script_resource_appcache_id
= script_resource_appcache_id
;
68 IPC::Message
* create_message
= new ViewHostMsg_CreateWorker(
70 child_thread_
->Send(create_message
);
71 if (route_id_
== MSG_ROUTING_NONE
)
74 child_thread_
->AddRoute(route_id_
, this);
76 // We make sure that the start message is the first, since postMessage or
77 // connect might have already been called.
78 queued_messages_
.insert(queued_messages_
.begin(),
79 new WorkerMsg_StartWorkerContext(
80 route_id_
, script_url
, user_agent
, source_code
,
81 content_security_policy
, policy_type
));
84 bool WebSharedWorkerProxy::IsStarted() {
85 // Worker is started if we have a route ID and there are no queued messages
86 // (meaning we've sent the WorkerMsg_StartWorkerContext already).
87 return (route_id_
!= MSG_ROUTING_NONE
&& queued_messages_
.empty());
90 bool WebSharedWorkerProxy::Send(IPC::Message
* message
) {
91 // It's possible that messages will be sent before the worker is created, in
92 // which case route_id_ will be none. Or the worker object can be interacted
93 // with before the browser process told us that it started, in which case we
94 // also want to queue the message.
96 queued_messages_
.push_back(message
);
100 // For now we proxy all messages to the worker process through the browser.
101 // Revisit if we find this slow.
102 // TODO(jabdelmalek): handle sync messages if we need them.
103 IPC::Message
* wrapped_msg
= new ViewHostMsg_ForwardToWorker(*message
);
105 return child_thread_
->Send(wrapped_msg
);
108 void WebSharedWorkerProxy::SendQueuedMessages() {
109 DCHECK(queued_messages_
.size());
110 std::vector
<IPC::Message
*> queued_messages
= queued_messages_
;
111 queued_messages_
.clear();
112 for (size_t i
= 0; i
< queued_messages
.size(); ++i
) {
113 queued_messages
[i
]->set_routing_id(route_id_
);
114 Send(queued_messages
[i
]);
118 bool WebSharedWorkerProxy::isStarted() {
122 void WebSharedWorkerProxy::startWorkerContext(
123 const WebKit::WebURL
& script_url
,
124 const WebKit::WebString
& name
,
125 const WebKit::WebString
& user_agent
,
126 const WebKit::WebString
& source_code
,
127 const WebKit::WebString
& content_security_policy
,
128 WebKit::WebContentSecurityPolicyType policy_type
,
129 long long script_resource_appcache_id
) {
130 DCHECK(!isStarted());
132 script_url
, true, name
, user_agent
, source_code
, content_security_policy
,
133 policy_type
, pending_route_id_
, script_resource_appcache_id
);
136 void WebSharedWorkerProxy::terminateWorkerContext() {
137 // This API should only be invoked from worker context.
141 void WebSharedWorkerProxy::clientDestroyed() {
142 // This API should only be invoked from worker context.
146 void WebSharedWorkerProxy::connect(WebKit::WebMessagePortChannel
* channel
,
147 ConnectListener
* listener
) {
148 WebMessagePortChannelImpl
* webchannel
=
149 static_cast<WebMessagePortChannelImpl
*>(channel
);
151 int message_port_id
= webchannel
->message_port_id();
152 DCHECK(message_port_id
!= MSG_ROUTING_NONE
);
153 webchannel
->QueueMessages();
155 Send(new WorkerMsg_Connect(route_id_
, message_port_id
, MSG_ROUTING_NONE
));
156 if (HasQueuedMessages()) {
157 connect_listener_
= listener
;
159 listener
->connected();
160 // The listener may free this object, so do not access the object after
165 bool WebSharedWorkerProxy::OnMessageReceived(const IPC::Message
& message
) {
167 IPC_BEGIN_MESSAGE_MAP(WebSharedWorkerProxy
, message
)
168 IPC_MESSAGE_HANDLER(ViewMsg_WorkerCreated
, OnWorkerCreated
)
169 IPC_MESSAGE_UNHANDLED(handled
= false)
170 IPC_END_MESSAGE_MAP()
174 void WebSharedWorkerProxy::OnWorkerCreated() {
175 // The worker is created - now send off the CreateWorkerContext message and
176 // any other queued messages
177 SendQueuedMessages();
179 // Inform any listener that the pending connect event has been sent
180 // (this can result in this object being freed).
181 if (connect_listener_
) {
182 connect_listener_
->connected();
186 } // namespace content