OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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 "webkit/plugins/ppapi/ppb_websocket_impl.h" | 5 #include "webkit/plugins/ppapi/ppb_websocket_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
| 9 #include "base/basictypes.h" |
9 #include "base/logging.h" | 10 #include "base/logging.h" |
10 #include "googleurl/src/gurl.h" | 11 #include "googleurl/src/gurl.h" |
11 #include "net/base/net_util.h" | 12 #include "net/base/net_util.h" |
12 #include "ppapi/c/pp_completion_callback.h" | 13 #include "ppapi/c/pp_completion_callback.h" |
13 #include "ppapi/c/pp_errors.h" | 14 #include "ppapi/c/pp_errors.h" |
14 #include "ppapi/c/pp_var.h" | 15 #include "ppapi/c/pp_var.h" |
15 #include "ppapi/c/ppb_var.h" | 16 #include "ppapi/c/ppb_var.h" |
16 #include "ppapi/shared_impl/var.h" | 17 #include "ppapi/shared_impl/var.h" |
17 #include "ppapi/shared_impl/var_tracker.h" | 18 #include "ppapi/shared_impl/var_tracker.h" |
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h" | 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h" |
(...skipping 11 matching lines...) Expand all Loading... |
30 using ppapi::StringVar; | 31 using ppapi::StringVar; |
31 using ppapi::thunk::PPB_WebSocket_API; | 32 using ppapi::thunk::PPB_WebSocket_API; |
32 using ppapi::VarTracker; | 33 using ppapi::VarTracker; |
33 using WebKit::WebData; | 34 using WebKit::WebData; |
34 using WebKit::WebDocument; | 35 using WebKit::WebDocument; |
35 using WebKit::WebString; | 36 using WebKit::WebString; |
36 using WebKit::WebSocket; | 37 using WebKit::WebSocket; |
37 using WebKit::WebSocketClient; | 38 using WebKit::WebSocketClient; |
38 using WebKit::WebURL; | 39 using WebKit::WebURL; |
39 | 40 |
40 static const uint32_t kMaxReasonSizeInBytes = 123; | 41 namespace { |
| 42 |
| 43 const uint32_t kMaxReasonSizeInBytes = 123; |
| 44 const size_t kHybiBaseFramingOverhead = 2; |
| 45 const size_t kHybiMaskingKeyLength = 4; |
| 46 const size_t kMinimumPayloadSizeWithTwoByteExtendedPayloadLength = 126; |
| 47 const size_t kMinimumPayloadSizeWithEightByteExtendedPayloadLength = 0x10000; |
| 48 |
| 49 uint64_t SaturateAdd(uint64_t a, uint64_t b) { |
| 50 if (kuint64max - a < b) |
| 51 return kuint64max; |
| 52 return a + b; |
| 53 } |
| 54 |
| 55 uint64_t GetFrameSize(uint64_t payload_size) { |
| 56 if (!payload_size) |
| 57 return 0; |
| 58 |
| 59 uint64_t overhead = kHybiBaseFramingOverhead + kHybiMaskingKeyLength; |
| 60 if (payload_size > kMinimumPayloadSizeWithEightByteExtendedPayloadLength) |
| 61 overhead += 8; |
| 62 else if (payload_size > kMinimumPayloadSizeWithTwoByteExtendedPayloadLength) |
| 63 overhead += 2; |
| 64 return SaturateAdd(payload_size, overhead); |
| 65 } |
| 66 |
| 67 } // namespace |
41 | 68 |
42 namespace webkit { | 69 namespace webkit { |
43 namespace ppapi { | 70 namespace ppapi { |
44 | 71 |
45 PPB_WebSocket_Impl::PPB_WebSocket_Impl(PP_Instance instance) | 72 PPB_WebSocket_Impl::PPB_WebSocket_Impl(PP_Instance instance) |
46 : Resource(instance), | 73 : Resource(instance), |
47 state_(PP_WEBSOCKETREADYSTATE_INVALID_DEV), | 74 state_(PP_WEBSOCKETREADYSTATE_INVALID_DEV), |
48 receive_callback_var_(NULL), | 75 receive_callback_var_(NULL), |
49 wait_for_receive_(false), | 76 wait_for_receive_(false), |
50 close_code_(0), | 77 close_code_(0), |
51 close_was_clean_(PP_FALSE) { | 78 close_was_clean_(PP_FALSE), |
| 79 buffered_amount_(0), |
| 80 buffered_amount_after_close_(0) { |
52 empty_string_ = new StringVar( | 81 empty_string_ = new StringVar( |
53 PpapiGlobals::Get()->GetModuleForInstance(instance), "", 0); | 82 PpapiGlobals::Get()->GetModuleForInstance(instance), "", 0); |
54 } | 83 } |
55 | 84 |
56 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() { | 85 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() { |
57 if (websocket_.get()) | 86 if (websocket_.get()) |
58 websocket_->disconnect(); | 87 websocket_->disconnect(); |
59 | 88 |
60 // Clean up received and unread messages | 89 // Clean up received and unread messages |
61 VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker(); | 90 VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker(); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 if (!websocket_.get()) | 267 if (!websocket_.get()) |
239 return PP_ERROR_FAILED; | 268 return PP_ERROR_FAILED; |
240 | 269 |
241 // Check state. | 270 // Check state. |
242 if (state_ == PP_WEBSOCKETREADYSTATE_INVALID_DEV || | 271 if (state_ == PP_WEBSOCKETREADYSTATE_INVALID_DEV || |
243 state_ == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) | 272 state_ == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) |
244 return PP_ERROR_BADARGUMENT; | 273 return PP_ERROR_BADARGUMENT; |
245 | 274 |
246 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV || | 275 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV || |
247 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) { | 276 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) { |
248 // TODO(toyoshim): Handle bufferedAmount here. | 277 // Handle buffered_amount_after_close_. |
| 278 uint64_t payload_size = 0; |
| 279 if (message.type == PP_VARTYPE_STRING) { |
| 280 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); |
| 281 if (message_string) |
| 282 payload_size += message_string->value().length(); |
| 283 } |
| 284 // TODO(toyoshim): Support binary data. |
| 285 |
| 286 buffered_amount_after_close_ = |
| 287 SaturateAdd(buffered_amount_after_close_, GetFrameSize(payload_size)); |
| 288 |
| 289 return PP_ERROR_FAILED; |
249 } | 290 } |
250 | 291 |
251 if (message.type != PP_VARTYPE_STRING) { | 292 if (message.type != PP_VARTYPE_STRING) { |
252 // TODO(toyoshim): Support binary data. | 293 // TODO(toyoshim): Support binary data. |
253 return PP_ERROR_NOTSUPPORTED; | 294 return PP_ERROR_NOTSUPPORTED; |
254 } | 295 } |
255 | 296 |
256 // Convert message to WebString. | 297 // Convert message to WebString. |
257 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); | 298 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); |
258 if (!message_string) | 299 if (!message_string) |
259 return PP_ERROR_BADARGUMENT; | 300 return PP_ERROR_BADARGUMENT; |
260 WebString web_message = WebString::fromUTF8(message_string->value()); | 301 WebString web_message = WebString::fromUTF8(message_string->value()); |
261 if (!websocket_->sendText(web_message)) | 302 if (!websocket_->sendText(web_message)) |
262 return PP_ERROR_BADARGUMENT; | 303 return PP_ERROR_BADARGUMENT; |
263 | 304 |
264 return PP_OK; | 305 return PP_OK; |
265 } | 306 } |
266 | 307 |
267 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() { | 308 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() { |
268 // TODO(toyoshim): Implement. | 309 return SaturateAdd(buffered_amount_, buffered_amount_after_close_); |
269 return 0; | |
270 } | 310 } |
271 | 311 |
272 uint16_t PPB_WebSocket_Impl::GetCloseCode() { | 312 uint16_t PPB_WebSocket_Impl::GetCloseCode() { |
273 return close_code_; | 313 return close_code_; |
274 } | 314 } |
275 | 315 |
276 PP_Var PPB_WebSocket_Impl::GetCloseReason() { | 316 PP_Var PPB_WebSocket_Impl::GetCloseReason() { |
277 if (!close_reason_) | 317 if (!close_reason_) |
278 return empty_string_->GetPPVar(); | 318 return empty_string_->GetPPVar(); |
279 return close_reason_->GetPPVar(); | 319 return close_reason_->GetPPVar(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 void PPB_WebSocket_Impl::didReceiveBinaryData(const WebData& binaryData) { | 370 void PPB_WebSocket_Impl::didReceiveBinaryData(const WebData& binaryData) { |
331 DLOG(INFO) << "didReceiveBinaryData is not implemented yet."; | 371 DLOG(INFO) << "didReceiveBinaryData is not implemented yet."; |
332 // TODO(toyoshim): Support to receive binary data. | 372 // TODO(toyoshim): Support to receive binary data. |
333 } | 373 } |
334 | 374 |
335 void PPB_WebSocket_Impl::didReceiveMessageError() { | 375 void PPB_WebSocket_Impl::didReceiveMessageError() { |
336 // TODO(toyoshim): Must implement. | 376 // TODO(toyoshim): Must implement. |
337 DLOG(INFO) << "didReceiveMessageError is not implemented yet."; | 377 DLOG(INFO) << "didReceiveMessageError is not implemented yet."; |
338 } | 378 } |
339 | 379 |
340 void PPB_WebSocket_Impl::didUpdateBufferedAmount(unsigned long bufferedAmount) { | 380 void PPB_WebSocket_Impl::didUpdateBufferedAmount( |
341 // TODO(toyoshim): Must implement. | 381 unsigned long buffered_amount) { |
342 DLOG(INFO) << "didUpdateBufferedAmount is not implemented yet."; | 382 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) |
| 383 return; |
| 384 buffered_amount_ = buffered_amount; |
343 } | 385 } |
344 | 386 |
345 void PPB_WebSocket_Impl::didStartClosingHandshake() { | 387 void PPB_WebSocket_Impl::didStartClosingHandshake() { |
346 // TODO(toyoshim): Must implement. | 388 // TODO(toyoshim): Must implement. |
347 DLOG(INFO) << "didStartClosingHandshake is not implemented yet."; | 389 DLOG(INFO) << "didStartClosingHandshake is not implemented yet."; |
348 } | 390 } |
349 | 391 |
350 void PPB_WebSocket_Impl::didClose(unsigned long bufferedAmount, | 392 void PPB_WebSocket_Impl::didClose(unsigned long buffered_amount, |
351 ClosingHandshakeCompletionStatus status, | 393 ClosingHandshakeCompletionStatus status, |
352 unsigned short code, | 394 unsigned short code, |
353 const WebString& reason) { | 395 const WebString& reason) { |
354 // Store code and reason. | 396 // Store code and reason. |
355 close_code_ = code; | 397 close_code_ = code; |
356 std::string reason_string = reason.utf8(); | 398 std::string reason_string = reason.utf8(); |
357 close_reason_ = new StringVar( | 399 close_reason_ = new StringVar( |
358 PpapiGlobals::Get()->GetModuleForInstance(pp_instance()), reason_string); | 400 PpapiGlobals::Get()->GetModuleForInstance(pp_instance()), reason_string); |
359 | 401 |
360 // TODO(toyoshim): Set close_was_clean_. | 402 // TODO(toyoshim): Set close_was_clean_. |
361 | 403 |
362 // Handle state transition and invoking callback. | 404 // Handle state transition and invoking callback. |
363 DCHECK_NE(PP_WEBSOCKETREADYSTATE_CLOSED_DEV, state_); | 405 DCHECK_NE(PP_WEBSOCKETREADYSTATE_CLOSED_DEV, state_); |
364 PP_WebSocketReadyState_Dev state = state_; | 406 PP_WebSocketReadyState_Dev state = state_; |
365 state_ = PP_WEBSOCKETREADYSTATE_CLOSED_DEV; | 407 state_ = PP_WEBSOCKETREADYSTATE_CLOSED_DEV; |
366 | 408 |
| 409 // Update buffered_amount_. |
| 410 buffered_amount_ = buffered_amount; |
| 411 |
367 if (state == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) | 412 if (state == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) |
368 PP_RunAndClearCompletionCallback(&connect_callback_, PP_OK); | 413 PP_RunAndClearCompletionCallback(&connect_callback_, PP_OK); |
369 | 414 |
370 if (state == PP_WEBSOCKETREADYSTATE_CLOSING_DEV) | 415 if (state == PP_WEBSOCKETREADYSTATE_CLOSING_DEV) |
371 PP_RunAndClearCompletionCallback(&close_callback_, PP_OK); | 416 PP_RunAndClearCompletionCallback(&close_callback_, PP_OK); |
372 } | 417 } |
373 | 418 |
374 int32_t PPB_WebSocket_Impl::DoReceive() { | 419 int32_t PPB_WebSocket_Impl::DoReceive() { |
375 // TODO(toyoshim): Check state. | 420 // TODO(toyoshim): Check state. |
376 | 421 |
377 if (!receive_callback_var_) | 422 if (!receive_callback_var_) |
378 return PP_OK; | 423 return PP_OK; |
379 | 424 |
380 *receive_callback_var_ = received_messages_.front(); | 425 *receive_callback_var_ = received_messages_.front(); |
381 received_messages_.pop(); | 426 received_messages_.pop(); |
382 receive_callback_var_ = NULL; | 427 receive_callback_var_ = NULL; |
383 wait_for_receive_ = false; | 428 wait_for_receive_ = false; |
384 return PP_OK; | 429 return PP_OK; |
385 } | 430 } |
386 | 431 |
387 } // namespace ppapi | 432 } // namespace ppapi |
388 } // namespace webkit | 433 } // namespace webkit |
OLD | NEW |