OLD | NEW |
---|---|
(Empty) | |
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/renderer/pepper/pepper_websocket_host.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "content/public/renderer/renderer_ppapi_host.h" | |
10 #include "net/base/net_util.h" | |
11 #include "ppapi/c/pp_errors.h" | |
12 #include "ppapi/c/ppb_websocket.h" | |
13 #include "ppapi/host/dispatch_host_message.h" | |
14 #include "ppapi/host/host_message_context.h" | |
15 #include "ppapi/host/ppapi_host.h" | |
16 #include "ppapi/proxy/ppapi_messages.h" | |
17 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | |
18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" | |
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebArrayBuffer.h" | |
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | |
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" | |
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" | |
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSocket.h" | |
24 | |
25 using WebKit::WebArrayBuffer; | |
26 using WebKit::WebDocument; | |
27 using WebKit::WebString; | |
28 using WebKit::WebSocket; | |
29 using WebKit::WebURL; | |
30 | |
31 namespace content { | |
32 | |
33 PepperWebSocketHost::PepperWebSocketHost( | |
34 RendererPpapiHost* host, | |
35 PP_Instance instance, | |
36 PP_Resource resource) | |
37 : ResourceHost(host->GetPpapiHost(), instance, resource), | |
38 renderer_ppapi_host_(host), | |
39 initiating_close_(false), | |
40 accepting_close_(false), | |
41 error_was_received_(false) { | |
42 } | |
43 | |
44 PepperWebSocketHost::~PepperWebSocketHost() { | |
45 if (websocket_.get()) | |
46 websocket_->disconnect(); | |
47 } | |
48 | |
49 int32_t PepperWebSocketHost::OnResourceMessageReceived( | |
50 const IPC::Message& msg, | |
51 ppapi::host::HostMessageContext* context) { | |
52 IPC_BEGIN_MESSAGE_MAP(PepperWebSocketHost, msg) | |
53 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_Connect, | |
54 OnHostMsgConnect) | |
55 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_Close, | |
56 OnHostMsgClose) | |
57 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_SendText, | |
58 OnHostMsgSendText) | |
59 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_SendBinary, | |
60 OnHostMsgSendBinary) | |
61 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_Fail, | |
62 OnHostMsgFail) | |
63 IPC_END_MESSAGE_MAP() | |
64 return PP_ERROR_FAILED; | |
65 } | |
66 | |
67 void PepperWebSocketHost::didConnect() { | |
68 std::string protocol; | |
69 if (websocket_.get()) | |
70 protocol = websocket_->subprotocol().utf8(); | |
71 connect_reply_.set_result(PP_OK); | |
72 host()->SendReply(connect_reply_, | |
73 PpapiPluginMsg_WebSocket_ConnectReply( | |
74 "", | |
brettw
2012/10/03 04:54:02
I prefer std::string() over ""
Takashi Toyoshima
2012/10/03 11:42:20
OK. I replaced all "" with std::string() in this c
| |
75 protocol)); | |
76 } | |
77 | |
78 void PepperWebSocketHost::didReceiveMessage(const WebKit::WebString& message) { | |
79 // Dispose packets after receiving an error. | |
80 if (error_was_received_) | |
81 return; | |
82 | |
83 // Send an IPC to transport received data. | |
84 std::string string_message = message.utf8(); | |
85 host()->SendUnsolicitedReply(pp_resource(), | |
86 PpapiPluginMsg_WebSocket_ReceiveTextReply( | |
87 string_message)); | |
88 } | |
89 | |
90 void PepperWebSocketHost::didReceiveArrayBuffer( | |
91 const WebKit::WebArrayBuffer& binaryData) { | |
92 // Dispose packets after receiving an error. | |
93 if (error_was_received_) | |
94 return; | |
95 | |
96 // Send an IPC to transport received data. | |
97 uint8_t* data = static_cast<uint8_t*>(binaryData.data()); | |
98 std::vector<uint8_t> array_message(data, data + binaryData.byteLength()); | |
99 host()->SendUnsolicitedReply(pp_resource(), | |
100 PpapiPluginMsg_WebSocket_ReceiveBinaryReply( | |
101 array_message)); | |
102 } | |
103 | |
104 void PepperWebSocketHost::didReceiveMessageError() { | |
105 error_was_received_ = true; | |
106 | |
107 // Send an IPC to report error. | |
108 host()->SendUnsolicitedReply(pp_resource(), | |
109 PpapiPluginMsg_WebSocket_ErrorReply()); | |
110 } | |
111 | |
112 void PepperWebSocketHost::didUpdateBufferedAmount( | |
113 unsigned long buffered_amount) { | |
114 // Send an IPC to update buffered amount. | |
115 host()->SendUnsolicitedReply(pp_resource(), | |
116 PpapiPluginMsg_WebSocket_BufferedAmountReply( | |
117 buffered_amount)); | |
118 } | |
119 | |
120 void PepperWebSocketHost::didStartClosingHandshake() { | |
121 accepting_close_ = true; | |
122 | |
123 // Send an IPC to notice that server starts closing handshake. | |
124 host()->SendUnsolicitedReply(pp_resource(), | |
125 PpapiPluginMsg_WebSocket_StateReply( | |
126 PP_WEBSOCKETREADYSTATE_CLOSING)); | |
127 } | |
128 | |
129 void PepperWebSocketHost::didClose(unsigned long unhandled_buffered_amount, | |
130 ClosingHandshakeCompletionStatus status, | |
131 unsigned short code, | |
132 const WebKit::WebString& reason) { | |
133 // Set close_was_clean_. | |
134 bool was_clean = | |
135 (initiating_close_ || accepting_close_) && | |
136 !unhandled_buffered_amount && | |
137 status == WebSocketClient::ClosingHandshakeComplete; | |
138 | |
139 if (initiating_close_) { | |
140 initiating_close_ = false; | |
141 close_reply_.set_result(PP_OK); | |
142 host()->SendReply(close_reply_, PpapiPluginMsg_WebSocket_CloseReply( | |
143 unhandled_buffered_amount, | |
144 was_clean, | |
145 code, | |
146 reason.utf8())); | |
147 } else { | |
148 accepting_close_ = false; | |
149 host()->SendUnsolicitedReply(pp_resource(), | |
150 PpapiPluginMsg_WebSocket_ClosedReply( | |
151 unhandled_buffered_amount, | |
brettw
2012/10/03 04:54:02
Can you indent these one more space (so 4 extra fr
Takashi Toyoshima
2012/10/03 11:42:20
Done.
| |
152 was_clean, | |
153 code, | |
154 reason.utf8())); | |
155 } | |
156 | |
157 // Disconnect. | |
158 if (websocket_.get()) | |
159 websocket_->disconnect(); | |
160 } | |
161 | |
162 int32_t PepperWebSocketHost::OnHostMsgConnect( | |
163 ppapi::host::HostMessageContext* context, | |
164 const std::string& url, | |
165 const std::string& protocols) { | |
166 std::string spec; | |
167 connect_reply_ = context->MakeReplyParams(); | |
168 int32_t result = DoConnect(url, protocols, &spec); | |
169 connect_reply_.set_result(DoConnect(url, protocols, &spec)); | |
170 host()->SendReply(connect_reply_, | |
171 PpapiPluginMsg_WebSocket_ConnectReply(spec, "")); | |
172 return result; | |
173 } | |
174 | |
175 int32_t PepperWebSocketHost::OnHostMsgClose( | |
176 ppapi::host::HostMessageContext* context, | |
177 int32_t code, | |
178 const std::string& reason) { | |
179 close_reply_ = context->MakeReplyParams(); | |
180 if (!websocket_.get()) { | |
181 close_reply_.set_result(PP_ERROR_FAILED); | |
182 host()->SendReply(close_reply_, | |
183 PpapiPluginMsg_WebSocket_CloseReply(0, false, 0, "")); | |
184 } | |
185 initiating_close_ = true; | |
186 WebString web_reason = WebString::fromUTF8(reason); | |
187 websocket_->close(code, web_reason); | |
188 return PP_OK_COMPLETIONPENDING; | |
189 } | |
190 | |
191 int32_t PepperWebSocketHost::OnHostMsgSendText( | |
192 ppapi::host::HostMessageContext* context, | |
193 const std::string& message) { | |
194 if (websocket_.get()) { | |
195 WebString web_message = WebString::fromUTF8(message); | |
196 websocket_->sendText(web_message); | |
197 } | |
198 return PP_OK; | |
199 } | |
200 | |
201 int32_t PepperWebSocketHost::OnHostMsgSendBinary( | |
202 ppapi::host::HostMessageContext* context, | |
203 const std::vector<uint8_t>& message) { | |
204 if (websocket_.get()) { | |
205 WebArrayBuffer web_message = WebArrayBuffer::create(message.size(), 1); | |
206 memcpy(web_message.data(), &message.front(), message.size()); | |
207 websocket_->sendArrayBuffer(web_message); | |
208 } | |
209 return PP_OK; | |
210 } | |
211 | |
212 int32_t PepperWebSocketHost::OnHostMsgFail( | |
213 ppapi::host::HostMessageContext* context, | |
214 const std::string& message) { | |
215 if (websocket_.get()) | |
216 websocket_->fail(WebString::fromUTF8(message)); | |
217 return PP_OK; | |
218 } | |
219 | |
220 int32_t PepperWebSocketHost::DoConnect(const std::string& url, | |
221 const std::string& protocols, | |
222 std::string* spec) { | |
223 // Validate url and convert it to WebURL. | |
224 GURL gurl(url); | |
225 *spec = gurl.spec(); | |
226 if (!gurl.is_valid()) | |
227 return PP_ERROR_BADARGUMENT; | |
228 if (!gurl.SchemeIs("ws") && !gurl.SchemeIs("wss")) | |
229 return PP_ERROR_BADARGUMENT; | |
230 if (gurl.has_ref()) | |
231 return PP_ERROR_BADARGUMENT; | |
232 if (!net::IsPortAllowedByDefault(gurl.IntPort())) | |
233 return PP_ERROR_BADARGUMENT; | |
234 WebURL web_url(gurl); | |
235 | |
236 // Convert protocols to WebString. | |
237 WebString web_protocols = WebString::fromUTF8(protocols); | |
238 | |
239 // Create WebKit::WebSocket object and connect. | |
240 WebKit::WebPluginContainer* container = | |
241 renderer_ppapi_host_->GetContainerForInstance(pp_instance()); | |
242 if (!container) | |
243 return PP_ERROR_BADARGUMENT; | |
244 // TODO(toyoshim) Remove following WebDocument object copy. | |
245 WebDocument document = container->element().document(); | |
246 websocket_.reset(WebSocket::create(document, this)); | |
247 DCHECK(websocket_.get()); | |
248 if (!websocket_.get()) | |
249 return PP_ERROR_NOTSUPPORTED; | |
250 | |
251 // Set receiving binary object type. | |
252 websocket_->setBinaryType(WebSocket::BinaryTypeArrayBuffer); | |
253 | |
254 websocket_->connect(web_url, web_protocols); | |
255 return PP_OK_COMPLETIONPENDING; | |
256 } | |
257 | |
258 } // namespace content | |
OLD | NEW |