Chromium Code Reviews| 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 12 matching lines...) Expand all Loading... | |
| 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 static const uint32_t kMaxReasonSizeInBytes = 123; |
| 42 static const size_t kHybiBaseFramingOverhead = 2; | |
| 43 static const size_t kHybiMaskingKeyLength = 4; | |
| 44 static const size_t kMinimumPayloadSizeWithTwoByteExtendedPayloadLength = 126; | |
| 45 static const size_t kMinimumPayloadSizeWithEightByteExtendedPayloadLength = | |
| 46 0x10000; | |
| 41 | 47 |
| 42 namespace webkit { | 48 namespace webkit { |
| 43 namespace ppapi { | 49 namespace ppapi { |
| 44 | 50 |
| 45 PPB_WebSocket_Impl::PPB_WebSocket_Impl(PP_Instance instance) | 51 PPB_WebSocket_Impl::PPB_WebSocket_Impl(PP_Instance instance) |
| 46 : Resource(instance), | 52 : Resource(instance), |
| 47 state_(PP_WEBSOCKETREADYSTATE_INVALID_DEV), | 53 state_(PP_WEBSOCKETREADYSTATE_INVALID_DEV), |
| 48 receive_callback_var_(NULL), | 54 receive_callback_var_(NULL), |
| 49 wait_for_receive_(false), | 55 wait_for_receive_(false), |
| 50 close_code_(0), | 56 close_code_(0), |
| 51 close_was_clean_(PP_FALSE) { | 57 close_was_clean_(PP_FALSE), |
| 58 buffered_amount_(0), | |
| 59 buffered_amount_after_close_(0) { | |
| 52 empty_string_ = new StringVar( | 60 empty_string_ = new StringVar( |
| 53 PpapiGlobals::Get()->GetModuleForInstance(instance), "", 0); | 61 PpapiGlobals::Get()->GetModuleForInstance(instance), "", 0); |
| 54 } | 62 } |
| 55 | 63 |
| 56 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() { | 64 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() { |
| 57 if (websocket_.get()) | 65 if (websocket_.get()) |
| 58 websocket_->disconnect(); | 66 websocket_->disconnect(); |
| 59 | 67 |
| 60 // Clean up received and unread messages | 68 // Clean up received and unread messages |
| 61 VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker(); | 69 VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker(); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 if (!websocket_.get()) | 246 if (!websocket_.get()) |
| 239 return PP_ERROR_FAILED; | 247 return PP_ERROR_FAILED; |
| 240 | 248 |
| 241 // Check state. | 249 // Check state. |
| 242 if (state_ == PP_WEBSOCKETREADYSTATE_INVALID_DEV || | 250 if (state_ == PP_WEBSOCKETREADYSTATE_INVALID_DEV || |
| 243 state_ == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) | 251 state_ == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) |
| 244 return PP_ERROR_BADARGUMENT; | 252 return PP_ERROR_BADARGUMENT; |
| 245 | 253 |
| 246 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV || | 254 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV || |
| 247 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) { | 255 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) { |
| 248 // TODO(toyoshim): Handle bufferedAmount here. | 256 // Handle buffered_amount_after_close_. |
| 257 uint64_t payload_size = 0; | |
| 258 if (message.type == PP_VARTYPE_STRING) { | |
| 259 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); | |
| 260 if (message_string) | |
| 261 payload_size += message_string->value().length(); | |
|
Yuta Kitamura
2011/11/30 11:40:48
Is this byte length in UTF-8?
Takashi Toyoshima
2011/11/30 12:29:12
Yes.
StringVar::value() returns std::string& direc
| |
| 262 } | |
| 263 // TODO(toyoshim): Support binary data. | |
| 264 | |
| 265 buffered_amount_after_close_ = | |
| 266 SaturateAdd(buffered_amount_after_close_, GetFrameSize(payload_size)); | |
| 267 | |
| 268 return PP_ERROR_FAILED; | |
| 249 } | 269 } |
| 250 | 270 |
| 251 if (message.type != PP_VARTYPE_STRING) { | 271 if (message.type != PP_VARTYPE_STRING) { |
| 252 // TODO(toyoshim): Support binary data. | 272 // TODO(toyoshim): Support binary data. |
| 253 return PP_ERROR_NOTSUPPORTED; | 273 return PP_ERROR_NOTSUPPORTED; |
| 254 } | 274 } |
| 255 | 275 |
| 256 // Convert message to WebString. | 276 // Convert message to WebString. |
| 257 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); | 277 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); |
| 258 if (!message_string) | 278 if (!message_string) |
| 259 return PP_ERROR_BADARGUMENT; | 279 return PP_ERROR_BADARGUMENT; |
| 260 WebString web_message = WebString::fromUTF8(message_string->value()); | 280 WebString web_message = WebString::fromUTF8(message_string->value()); |
| 261 if (!websocket_->sendText(web_message)) | 281 if (!websocket_->sendText(web_message)) |
| 262 return PP_ERROR_BADARGUMENT; | 282 return PP_ERROR_BADARGUMENT; |
| 263 | 283 |
| 264 return PP_OK; | 284 return PP_OK; |
| 265 } | 285 } |
| 266 | 286 |
| 267 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() { | 287 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() { |
| 268 // TODO(toyoshim): Implement. | 288 return SaturateAdd(buffered_amount_, buffered_amount_after_close_); |
| 269 return 0; | |
| 270 } | 289 } |
| 271 | 290 |
| 272 uint16_t PPB_WebSocket_Impl::GetCloseCode() { | 291 uint16_t PPB_WebSocket_Impl::GetCloseCode() { |
| 273 return close_code_; | 292 return close_code_; |
| 274 } | 293 } |
| 275 | 294 |
| 276 PP_Var PPB_WebSocket_Impl::GetCloseReason() { | 295 PP_Var PPB_WebSocket_Impl::GetCloseReason() { |
| 277 if (!close_reason_) | 296 if (!close_reason_) |
| 278 return empty_string_->GetPPVar(); | 297 return empty_string_->GetPPVar(); |
| 279 return close_reason_->GetPPVar(); | 298 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) { | 349 void PPB_WebSocket_Impl::didReceiveBinaryData(const WebData& binaryData) { |
| 331 DLOG(INFO) << "didReceiveBinaryData is not implemented yet."; | 350 DLOG(INFO) << "didReceiveBinaryData is not implemented yet."; |
| 332 // TODO(toyoshim): Support to receive binary data. | 351 // TODO(toyoshim): Support to receive binary data. |
| 333 } | 352 } |
| 334 | 353 |
| 335 void PPB_WebSocket_Impl::didReceiveMessageError() { | 354 void PPB_WebSocket_Impl::didReceiveMessageError() { |
| 336 // TODO(toyoshim): Must implement. | 355 // TODO(toyoshim): Must implement. |
| 337 DLOG(INFO) << "didReceiveMessageError is not implemented yet."; | 356 DLOG(INFO) << "didReceiveMessageError is not implemented yet."; |
| 338 } | 357 } |
| 339 | 358 |
| 340 void PPB_WebSocket_Impl::didUpdateBufferedAmount(unsigned long bufferedAmount) { | 359 void PPB_WebSocket_Impl::didUpdateBufferedAmount( |
| 341 // TODO(toyoshim): Must implement. | 360 unsigned long buffered_amount) { |
| 342 DLOG(INFO) << "didUpdateBufferedAmount is not implemented yet."; | 361 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) |
| 362 return; | |
| 363 buffered_amount_ = buffered_amount; | |
| 343 } | 364 } |
| 344 | 365 |
| 345 void PPB_WebSocket_Impl::didStartClosingHandshake() { | 366 void PPB_WebSocket_Impl::didStartClosingHandshake() { |
| 346 // TODO(toyoshim): Must implement. | 367 // TODO(toyoshim): Must implement. |
| 347 DLOG(INFO) << "didStartClosingHandshake is not implemented yet."; | 368 DLOG(INFO) << "didStartClosingHandshake is not implemented yet."; |
| 348 } | 369 } |
| 349 | 370 |
| 350 void PPB_WebSocket_Impl::didClose(unsigned long bufferedAmount, | 371 void PPB_WebSocket_Impl::didClose(unsigned long buffered_amount, |
| 351 ClosingHandshakeCompletionStatus status, | 372 ClosingHandshakeCompletionStatus status, |
| 352 unsigned short code, | 373 unsigned short code, |
| 353 const WebString& reason) { | 374 const WebString& reason) { |
| 354 // Store code and reason. | 375 // Store code and reason. |
| 355 close_code_ = code; | 376 close_code_ = code; |
| 356 std::string reason_string = reason.utf8(); | 377 std::string reason_string = reason.utf8(); |
| 357 close_reason_ = new StringVar( | 378 close_reason_ = new StringVar( |
| 358 PpapiGlobals::Get()->GetModuleForInstance(pp_instance()), reason_string); | 379 PpapiGlobals::Get()->GetModuleForInstance(pp_instance()), reason_string); |
| 359 | 380 |
| 360 // TODO(toyoshim): Set close_was_clean_. | 381 // TODO(toyoshim): Set close_was_clean_. |
| 361 | 382 |
| 362 // Handle state transition and invoking callback. | 383 // Handle state transition and invoking callback. |
| 363 DCHECK_NE(PP_WEBSOCKETREADYSTATE_CLOSED_DEV, state_); | 384 DCHECK_NE(PP_WEBSOCKETREADYSTATE_CLOSED_DEV, state_); |
| 364 PP_WebSocketReadyState_Dev state = state_; | 385 PP_WebSocketReadyState_Dev state = state_; |
| 365 state_ = PP_WEBSOCKETREADYSTATE_CLOSED_DEV; | 386 state_ = PP_WEBSOCKETREADYSTATE_CLOSED_DEV; |
| 366 | 387 |
| 388 // Update buffered_amount_. | |
| 389 buffered_amount_ = buffered_amount; | |
| 390 | |
| 367 if (state == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) | 391 if (state == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) |
| 368 PP_RunAndClearCompletionCallback(&connect_callback_, PP_OK); | 392 PP_RunAndClearCompletionCallback(&connect_callback_, PP_OK); |
| 369 | 393 |
| 370 if (state == PP_WEBSOCKETREADYSTATE_CLOSING_DEV) | 394 if (state == PP_WEBSOCKETREADYSTATE_CLOSING_DEV) |
| 371 PP_RunAndClearCompletionCallback(&close_callback_, PP_OK); | 395 PP_RunAndClearCompletionCallback(&close_callback_, PP_OK); |
| 372 } | 396 } |
| 373 | 397 |
| 374 int32_t PPB_WebSocket_Impl::DoReceive() { | 398 int32_t PPB_WebSocket_Impl::DoReceive() { |
| 375 // TODO(toyoshim): Check state. | 399 // TODO(toyoshim): Check state. |
| 376 | 400 |
| 377 if (!receive_callback_var_) | 401 if (!receive_callback_var_) |
| 378 return PP_OK; | 402 return PP_OK; |
| 379 | 403 |
| 380 *receive_callback_var_ = received_messages_.front(); | 404 *receive_callback_var_ = received_messages_.front(); |
| 381 received_messages_.pop(); | 405 received_messages_.pop(); |
| 382 receive_callback_var_ = NULL; | 406 receive_callback_var_ = NULL; |
| 383 wait_for_receive_ = false; | 407 wait_for_receive_ = false; |
| 384 return PP_OK; | 408 return PP_OK; |
| 385 } | 409 } |
| 386 | 410 |
| 411 uint64_t PPB_WebSocket_Impl::GetFrameSize(uint64_t payload_size) { | |
|
Yuta Kitamura
2011/11/30 11:40:48
See comments below.
| |
| 412 if (!payload_size) | |
| 413 return 0; | |
| 414 | |
| 415 uint64_t overhead = kHybiBaseFramingOverhead + kHybiMaskingKeyLength; | |
| 416 if (payload_size > kMinimumPayloadSizeWithEightByteExtendedPayloadLength) | |
| 417 overhead += 8; | |
| 418 else if (payload_size > kMinimumPayloadSizeWithTwoByteExtendedPayloadLength) | |
| 419 overhead += 2; | |
| 420 return SaturateAdd(payload_size, overhead); | |
| 421 } | |
| 422 | |
| 423 uint64_t PPB_WebSocket_Impl::SaturateAdd(uint64_t a, uint64_t b) { | |
|
Yuta Kitamura
2011/11/30 11:40:48
I prefer this function to belong unnamed namespace
Takashi Toyoshima
2011/11/30 12:29:12
OK.
I move them to top of this file as static func
| |
| 424 if (kuint64max - a < b) | |
| 425 return kuint64max; | |
| 426 return a + b; | |
| 427 } | |
| 428 | |
| 387 } // namespace ppapi | 429 } // namespace ppapi |
| 388 } // namespace webkit | 430 } // namespace webkit |
| OLD | NEW |