OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/pepper/pepper_websocket_host.h" | 5 #include "content/renderer/pepper/pepper_websocket_host.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "content/public/renderer/renderer_ppapi_host.h" | 9 #include "content/public/renderer/renderer_ppapi_host.h" |
10 #include "net/base/net_util.h" | 10 #include "net/base/net_util.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "third_party/WebKit/public/web/WebSocket.h" | 23 #include "third_party/WebKit/public/web/WebSocket.h" |
24 | 24 |
25 using blink::WebArrayBuffer; | 25 using blink::WebArrayBuffer; |
26 using blink::WebDocument; | 26 using blink::WebDocument; |
27 using blink::WebString; | 27 using blink::WebString; |
28 using blink::WebSocket; | 28 using blink::WebSocket; |
29 using blink::WebURL; | 29 using blink::WebURL; |
30 | 30 |
31 namespace content { | 31 namespace content { |
32 | 32 |
33 #define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \ | 33 #define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \ |
34 COMPILE_ASSERT(static_cast<int>(WebSocket::webkit_name) \ | 34 COMPILE_ASSERT( \ |
35 == static_cast<int>(np_name), \ | 35 static_cast<int>(WebSocket::webkit_name) == static_cast<int>(np_name), \ |
36 mismatching_enums) | 36 mismatching_enums) |
37 | 37 |
38 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeNormalClosure, | 38 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeNormalClosure, |
39 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE); | 39 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE); |
40 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeGoingAway, | 40 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeGoingAway, |
41 PP_WEBSOCKETSTATUSCODE_GOING_AWAY); | 41 PP_WEBSOCKETSTATUSCODE_GOING_AWAY); |
42 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeProtocolError, | 42 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeProtocolError, |
43 PP_WEBSOCKETSTATUSCODE_PROTOCOL_ERROR); | 43 PP_WEBSOCKETSTATUSCODE_PROTOCOL_ERROR); |
44 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeUnsupportedData, | 44 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeUnsupportedData, |
45 PP_WEBSOCKETSTATUSCODE_UNSUPPORTED_DATA); | 45 PP_WEBSOCKETSTATUSCODE_UNSUPPORTED_DATA); |
46 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeNoStatusRcvd, | 46 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeNoStatusRcvd, |
(...skipping 10 matching lines...) Expand all Loading... |
57 PP_WEBSOCKETSTATUSCODE_MANDATORY_EXTENSION); | 57 PP_WEBSOCKETSTATUSCODE_MANDATORY_EXTENSION); |
58 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeInternalError, | 58 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeInternalError, |
59 PP_WEBSOCKETSTATUSCODE_INTERNAL_SERVER_ERROR); | 59 PP_WEBSOCKETSTATUSCODE_INTERNAL_SERVER_ERROR); |
60 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeTLSHandshake, | 60 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeTLSHandshake, |
61 PP_WEBSOCKETSTATUSCODE_TLS_HANDSHAKE); | 61 PP_WEBSOCKETSTATUSCODE_TLS_HANDSHAKE); |
62 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeMinimumUserDefined, | 62 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeMinimumUserDefined, |
63 PP_WEBSOCKETSTATUSCODE_USER_REGISTERED_MIN); | 63 PP_WEBSOCKETSTATUSCODE_USER_REGISTERED_MIN); |
64 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeMaximumUserDefined, | 64 COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeMaximumUserDefined, |
65 PP_WEBSOCKETSTATUSCODE_USER_PRIVATE_MAX); | 65 PP_WEBSOCKETSTATUSCODE_USER_PRIVATE_MAX); |
66 | 66 |
67 PepperWebSocketHost::PepperWebSocketHost( | 67 PepperWebSocketHost::PepperWebSocketHost(RendererPpapiHost* host, |
68 RendererPpapiHost* host, | 68 PP_Instance instance, |
69 PP_Instance instance, | 69 PP_Resource resource) |
70 PP_Resource resource) | |
71 : ResourceHost(host->GetPpapiHost(), instance, resource), | 70 : ResourceHost(host->GetPpapiHost(), instance, resource), |
72 renderer_ppapi_host_(host), | 71 renderer_ppapi_host_(host), |
73 connecting_(false), | 72 connecting_(false), |
74 initiating_close_(false), | 73 initiating_close_(false), |
75 accepting_close_(false), | 74 accepting_close_(false), |
76 error_was_received_(false) { | 75 error_was_received_(false) {} |
77 } | |
78 | 76 |
79 PepperWebSocketHost::~PepperWebSocketHost() { | 77 PepperWebSocketHost::~PepperWebSocketHost() { |
80 if (websocket_) | 78 if (websocket_) |
81 websocket_->disconnect(); | 79 websocket_->disconnect(); |
82 } | 80 } |
83 | 81 |
84 int32_t PepperWebSocketHost::OnResourceMessageReceived( | 82 int32_t PepperWebSocketHost::OnResourceMessageReceived( |
85 const IPC::Message& msg, | 83 const IPC::Message& msg, |
86 ppapi::host::HostMessageContext* context) { | 84 ppapi::host::HostMessageContext* context) { |
87 IPC_BEGIN_MESSAGE_MAP(PepperWebSocketHost, msg) | 85 IPC_BEGIN_MESSAGE_MAP(PepperWebSocketHost, msg) |
88 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_Connect, | 86 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_Connect, |
89 OnHostMsgConnect) | 87 OnHostMsgConnect) |
90 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_Close, | 88 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_Close, |
91 OnHostMsgClose) | 89 OnHostMsgClose) |
92 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_SendText, | 90 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_SendText, |
93 OnHostMsgSendText) | 91 OnHostMsgSendText) |
94 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_SendBinary, | 92 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_SendBinary, |
95 OnHostMsgSendBinary) | 93 OnHostMsgSendBinary) |
96 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_Fail, | 94 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_WebSocket_Fail, OnHostMsgFail) |
97 OnHostMsgFail) | |
98 IPC_END_MESSAGE_MAP() | 95 IPC_END_MESSAGE_MAP() |
99 return PP_ERROR_FAILED; | 96 return PP_ERROR_FAILED; |
100 } | 97 } |
101 | 98 |
102 void PepperWebSocketHost::didConnect() { | 99 void PepperWebSocketHost::didConnect() { |
103 std::string protocol; | 100 std::string protocol; |
104 if (websocket_) | 101 if (websocket_) |
105 protocol = websocket_->subprotocol().utf8(); | 102 protocol = websocket_->subprotocol().utf8(); |
106 connecting_ = false; | 103 connecting_ = false; |
107 connect_reply_.params.set_result(PP_OK); | 104 connect_reply_.params.set_result(PP_OK); |
108 host()->SendReply(connect_reply_, | 105 host()->SendReply(connect_reply_, |
109 PpapiPluginMsg_WebSocket_ConnectReply( | 106 PpapiPluginMsg_WebSocket_ConnectReply(url_, protocol)); |
110 url_, | |
111 protocol)); | |
112 } | 107 } |
113 | 108 |
114 void PepperWebSocketHost::didReceiveMessage(const blink::WebString& message) { | 109 void PepperWebSocketHost::didReceiveMessage(const blink::WebString& message) { |
115 // Dispose packets after receiving an error. | 110 // Dispose packets after receiving an error. |
116 if (error_was_received_) | 111 if (error_was_received_) |
117 return; | 112 return; |
118 | 113 |
119 // Send an IPC to transport received data. | 114 // Send an IPC to transport received data. |
120 std::string string_message = message.utf8(); | 115 std::string string_message = message.utf8(); |
121 host()->SendUnsolicitedReply(pp_resource(), | 116 host()->SendUnsolicitedReply( |
122 PpapiPluginMsg_WebSocket_ReceiveTextReply( | 117 pp_resource(), PpapiPluginMsg_WebSocket_ReceiveTextReply(string_message)); |
123 string_message)); | |
124 } | 118 } |
125 | 119 |
126 void PepperWebSocketHost::didReceiveArrayBuffer( | 120 void PepperWebSocketHost::didReceiveArrayBuffer( |
127 const blink::WebArrayBuffer& binaryData) { | 121 const blink::WebArrayBuffer& binaryData) { |
128 // Dispose packets after receiving an error. | 122 // Dispose packets after receiving an error. |
129 if (error_was_received_) | 123 if (error_was_received_) |
130 return; | 124 return; |
131 | 125 |
132 // Send an IPC to transport received data. | 126 // Send an IPC to transport received data. |
133 uint8_t* data = static_cast<uint8_t*>(binaryData.data()); | 127 uint8_t* data = static_cast<uint8_t*>(binaryData.data()); |
134 std::vector<uint8_t> array_message(data, data + binaryData.byteLength()); | 128 std::vector<uint8_t> array_message(data, data + binaryData.byteLength()); |
135 host()->SendUnsolicitedReply(pp_resource(), | 129 host()->SendUnsolicitedReply( |
136 PpapiPluginMsg_WebSocket_ReceiveBinaryReply( | 130 pp_resource(), |
137 array_message)); | 131 PpapiPluginMsg_WebSocket_ReceiveBinaryReply(array_message)); |
138 } | 132 } |
139 | 133 |
140 void PepperWebSocketHost::didReceiveMessageError() { | 134 void PepperWebSocketHost::didReceiveMessageError() { |
141 // Records the error, then stops receiving any frames after this error. | 135 // Records the error, then stops receiving any frames after this error. |
142 // The error must be notified after all queued messages are read. | 136 // The error must be notified after all queued messages are read. |
143 error_was_received_ = true; | 137 error_was_received_ = true; |
144 | 138 |
145 // Send an IPC to report the error. After this IPC, ReceiveTextReply and | 139 // Send an IPC to report the error. After this IPC, ReceiveTextReply and |
146 // ReceiveBinaryReply IPC are not sent anymore because |error_was_received_| | 140 // ReceiveBinaryReply IPC are not sent anymore because |error_was_received_| |
147 // blocks. | 141 // blocks. |
148 host()->SendUnsolicitedReply(pp_resource(), | 142 host()->SendUnsolicitedReply(pp_resource(), |
149 PpapiPluginMsg_WebSocket_ErrorReply()); | 143 PpapiPluginMsg_WebSocket_ErrorReply()); |
150 } | 144 } |
151 | 145 |
152 void PepperWebSocketHost::didUpdateBufferedAmount( | 146 void PepperWebSocketHost::didUpdateBufferedAmount( |
153 unsigned long buffered_amount) { | 147 unsigned long buffered_amount) { |
154 // Send an IPC to update buffered amount. | 148 // Send an IPC to update buffered amount. |
155 host()->SendUnsolicitedReply(pp_resource(), | 149 host()->SendUnsolicitedReply( |
156 PpapiPluginMsg_WebSocket_BufferedAmountReply( | 150 pp_resource(), |
157 buffered_amount)); | 151 PpapiPluginMsg_WebSocket_BufferedAmountReply(buffered_amount)); |
158 } | 152 } |
159 | 153 |
160 void PepperWebSocketHost::didStartClosingHandshake() { | 154 void PepperWebSocketHost::didStartClosingHandshake() { |
161 accepting_close_ = true; | 155 accepting_close_ = true; |
162 | 156 |
163 // Send an IPC to notice that server starts closing handshake. | 157 // Send an IPC to notice that server starts closing handshake. |
164 host()->SendUnsolicitedReply(pp_resource(), | 158 host()->SendUnsolicitedReply( |
165 PpapiPluginMsg_WebSocket_StateReply( | 159 pp_resource(), |
166 PP_WEBSOCKETREADYSTATE_CLOSING)); | 160 PpapiPluginMsg_WebSocket_StateReply(PP_WEBSOCKETREADYSTATE_CLOSING)); |
167 } | 161 } |
168 | 162 |
169 void PepperWebSocketHost::didClose(unsigned long unhandled_buffered_amount, | 163 void PepperWebSocketHost::didClose(unsigned long unhandled_buffered_amount, |
170 ClosingHandshakeCompletionStatus status, | 164 ClosingHandshakeCompletionStatus status, |
171 unsigned short code, | 165 unsigned short code, |
172 const blink::WebString& reason) { | 166 const blink::WebString& reason) { |
173 if (connecting_) { | 167 if (connecting_) { |
174 connecting_ = false; | 168 connecting_ = false; |
175 connect_reply_.params.set_result(PP_ERROR_FAILED); | 169 connect_reply_.params.set_result(PP_ERROR_FAILED); |
176 host()->SendReply( | 170 host()->SendReply( |
177 connect_reply_, | 171 connect_reply_, |
178 PpapiPluginMsg_WebSocket_ConnectReply(url_, std::string())); | 172 PpapiPluginMsg_WebSocket_ConnectReply(url_, std::string())); |
179 } | 173 } |
180 | 174 |
181 // Set close_was_clean_. | 175 // Set close_was_clean_. |
182 bool was_clean = | 176 bool was_clean = (initiating_close_ || accepting_close_) && |
183 (initiating_close_ || accepting_close_) && | 177 !unhandled_buffered_amount && |
184 !unhandled_buffered_amount && | 178 status == WebSocketClient::ClosingHandshakeComplete; |
185 status == WebSocketClient::ClosingHandshakeComplete; | |
186 | 179 |
187 if (initiating_close_) { | 180 if (initiating_close_) { |
188 initiating_close_ = false; | 181 initiating_close_ = false; |
189 close_reply_.params.set_result(PP_OK); | 182 close_reply_.params.set_result(PP_OK); |
190 host()->SendReply(close_reply_, PpapiPluginMsg_WebSocket_CloseReply( | 183 host()->SendReply( |
191 unhandled_buffered_amount, | 184 close_reply_, |
192 was_clean, | 185 PpapiPluginMsg_WebSocket_CloseReply( |
193 code, | 186 unhandled_buffered_amount, was_clean, code, reason.utf8())); |
194 reason.utf8())); | |
195 } else { | 187 } else { |
196 accepting_close_ = false; | 188 accepting_close_ = false; |
197 host()->SendUnsolicitedReply(pp_resource(), | 189 host()->SendUnsolicitedReply( |
198 PpapiPluginMsg_WebSocket_ClosedReply( | 190 pp_resource(), |
199 unhandled_buffered_amount, | 191 PpapiPluginMsg_WebSocket_ClosedReply( |
200 was_clean, | 192 unhandled_buffered_amount, was_clean, code, reason.utf8())); |
201 code, | |
202 reason.utf8())); | |
203 } | 193 } |
204 | 194 |
205 // Disconnect. | 195 // Disconnect. |
206 if (websocket_) | 196 if (websocket_) |
207 websocket_->disconnect(); | 197 websocket_->disconnect(); |
208 } | 198 } |
209 | 199 |
210 int32_t PepperWebSocketHost::OnHostMsgConnect( | 200 int32_t PepperWebSocketHost::OnHostMsgConnect( |
211 ppapi::host::HostMessageContext* context, | 201 ppapi::host::HostMessageContext* context, |
212 const std::string& url, | 202 const std::string& url, |
(...skipping 12 matching lines...) Expand all Loading... |
225 WebURL web_url(gurl); | 215 WebURL web_url(gurl); |
226 | 216 |
227 // Validate protocols. | 217 // Validate protocols. |
228 std::string protocol_string; | 218 std::string protocol_string; |
229 for (std::vector<std::string>::const_iterator vector_it = protocols.begin(); | 219 for (std::vector<std::string>::const_iterator vector_it = protocols.begin(); |
230 vector_it != protocols.end(); | 220 vector_it != protocols.end(); |
231 ++vector_it) { | 221 ++vector_it) { |
232 | 222 |
233 // Check containing characters. | 223 // Check containing characters. |
234 for (std::string::const_iterator string_it = vector_it->begin(); | 224 for (std::string::const_iterator string_it = vector_it->begin(); |
235 string_it != vector_it->end(); | 225 string_it != vector_it->end(); |
236 ++string_it) { | 226 ++string_it) { |
237 uint8_t character = *string_it; | 227 uint8_t character = *string_it; |
238 // WebSocket specification says "(Subprotocol string must consist of) | 228 // WebSocket specification says "(Subprotocol string must consist of) |
239 // characters in the range U+0021 to U+007E not including separator | 229 // characters in the range U+0021 to U+007E not including separator |
240 // characters as defined in [RFC2616]." | 230 // characters as defined in [RFC2616]." |
241 const uint8_t minimumProtocolCharacter = '!'; // U+0021. | 231 const uint8_t minimumProtocolCharacter = '!'; // U+0021. |
242 const uint8_t maximumProtocolCharacter = '~'; // U+007E. | 232 const uint8_t maximumProtocolCharacter = '~'; // U+007E. |
243 if (character < minimumProtocolCharacter || | 233 if (character < minimumProtocolCharacter || |
244 character > maximumProtocolCharacter || | 234 character > maximumProtocolCharacter || character == '"' || |
245 character == '"' || character == '(' || character == ')' || | 235 character == '(' || character == ')' || character == ',' || |
246 character == ',' || character == '/' || | 236 character == '/' || |
247 (character >= ':' && character <= '@') || // U+003A - U+0040 | 237 (character >= ':' && character <= '@') || // U+003A - U+0040 |
248 (character >= '[' && character <= ']') || // U+005B - u+005D | 238 (character >= '[' && character <= ']') || // U+005B - u+005D |
249 character == '{' || character == '}') | 239 character == '{' || |
| 240 character == '}') |
250 return PP_ERROR_BADARGUMENT; | 241 return PP_ERROR_BADARGUMENT; |
251 } | 242 } |
252 // Join protocols with the comma separator. | 243 // Join protocols with the comma separator. |
253 if (vector_it != protocols.begin()) | 244 if (vector_it != protocols.begin()) |
254 protocol_string.append(","); | 245 protocol_string.append(","); |
255 protocol_string.append(*vector_it); | 246 protocol_string.append(*vector_it); |
256 } | 247 } |
257 | 248 |
258 // Convert protocols to WebString. | 249 // Convert protocols to WebString. |
259 WebString web_protocols = WebString::fromUTF8(protocol_string); | 250 WebString web_protocols = WebString::fromUTF8(protocol_string); |
(...skipping 22 matching lines...) Expand all Loading... |
282 int32_t PepperWebSocketHost::OnHostMsgClose( | 273 int32_t PepperWebSocketHost::OnHostMsgClose( |
283 ppapi::host::HostMessageContext* context, | 274 ppapi::host::HostMessageContext* context, |
284 int32_t code, | 275 int32_t code, |
285 const std::string& reason) { | 276 const std::string& reason) { |
286 if (!websocket_) | 277 if (!websocket_) |
287 return PP_ERROR_FAILED; | 278 return PP_ERROR_FAILED; |
288 close_reply_ = context->MakeReplyMessageContext(); | 279 close_reply_ = context->MakeReplyMessageContext(); |
289 initiating_close_ = true; | 280 initiating_close_ = true; |
290 | 281 |
291 blink::WebSocket::CloseEventCode event_code = | 282 blink::WebSocket::CloseEventCode event_code = |
292 static_cast<blink::WebSocket::CloseEventCode>(code); | 283 static_cast<blink::WebSocket::CloseEventCode>(code); |
293 if (code == PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED) { | 284 if (code == PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED) { |
294 // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED and CloseEventCodeNotSpecified are | 285 // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED and CloseEventCodeNotSpecified are |
295 // assigned to different values. A conversion is needed if | 286 // assigned to different values. A conversion is needed if |
296 // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED is specified. | 287 // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED is specified. |
297 event_code = blink::WebSocket::CloseEventCodeNotSpecified; | 288 event_code = blink::WebSocket::CloseEventCodeNotSpecified; |
298 } | 289 } |
299 | 290 |
300 WebString web_reason = WebString::fromUTF8(reason); | 291 WebString web_reason = WebString::fromUTF8(reason); |
301 websocket_->close(event_code, web_reason); | 292 websocket_->close(event_code, web_reason); |
302 return PP_OK_COMPLETIONPENDING; | 293 return PP_OK_COMPLETIONPENDING; |
(...skipping 22 matching lines...) Expand all Loading... |
325 | 316 |
326 int32_t PepperWebSocketHost::OnHostMsgFail( | 317 int32_t PepperWebSocketHost::OnHostMsgFail( |
327 ppapi::host::HostMessageContext* context, | 318 ppapi::host::HostMessageContext* context, |
328 const std::string& message) { | 319 const std::string& message) { |
329 if (websocket_) | 320 if (websocket_) |
330 websocket_->fail(WebString::fromUTF8(message)); | 321 websocket_->fail(WebString::fromUTF8(message)); |
331 return PP_OK; | 322 return PP_OK; |
332 } | 323 } |
333 | 324 |
334 } // namespace content | 325 } // namespace content |
OLD | NEW |