1 // Copyright 2013 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 "net/websockets/websocket_channel.h" 6 7 #include <string.h> 8 9 #include <iostream> 10 #include <string> 11 #include <vector> 12 13 #include "base/bind.h" 14 #include "base/bind_helpers.h" 15 #include "base/callback.h" 16 #include "base/location.h" 17 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/scoped_vector.h" 19 #include "base/message_loop/message_loop.h" 20 #include "base/safe_numerics.h" 21 #include "base/strings/string_piece.h" 22 #include "net/base/net_errors.h" 23 #include "net/url_request/url_request_context.h" 24 #include "net/websockets/websocket_errors.h" 25 #include "net/websockets/websocket_event_interface.h" 26 #include "net/websockets/websocket_mux.h" 27 #include "testing/gmock/include/gmock/gmock.h" 28 #include "testing/gtest/include/gtest/gtest.h" 29 #include "url/gurl.h" 30 31 // Hacky macros to construct the body of a Close message from a code and a 32 // string, while ensuring the result is a compile-time constant string. 33 // Use like CLOSE_DATA(NORMAL_CLOSURE, "Explanation String") 34 #define CLOSE_DATA(code, string) WEBSOCKET_CLOSE_CODE_AS_STRING_##code string 35 #define WEBSOCKET_CLOSE_CODE_AS_STRING_NORMAL_CLOSURE "\x03\xe8" 36 #define WEBSOCKET_CLOSE_CODE_AS_STRING_GOING_AWAY "\x03\xe9" 37 #define WEBSOCKET_CLOSE_CODE_AS_STRING_SERVER_ERROR "\x03\xf3" 38 39 namespace net { 40 41 // Printing helpers to allow GoogleMock to print frame chunks. These are 42 // explicitly designed to look like the static initialisation format we use in 43 // these tests. They have to live in the net namespace in order to be found by 44 // GoogleMock; a nested anonymous namespace will not work. 45 46 std::ostream& operator<<(std::ostream& os, const WebSocketFrameHeader& header) { 47 return os << "{" << (header.final ? "FINAL_FRAME" : "NOT_FINAL_FRAME") << ", " 48 << header.opcode << ", " 49 << (header.masked ? "MASKED" : "NOT_MASKED") << ", " 50 << header.payload_length << "}"; 51 } 52 53 std::ostream& operator<<(std::ostream& os, const WebSocketFrameChunk& chunk) { 54 os << "{"; 55 if (chunk.header) { 56 os << *chunk.header; 57 } else { 58 os << "{NO_HEADER}"; 59 } 60 return os << ", " << (chunk.final_chunk ? "FINAL_CHUNK" : "NOT_FINAL_CHUNK") 61 << ", \"" 62 << base::StringPiece(chunk.data->data(), chunk.data->size()) 63 << "\"}"; 64 } 65 66 std::ostream& operator<<(std::ostream& os, 67 const ScopedVector<WebSocketFrameChunk>& vector) { 68 os << "{"; 69 bool first = true; 70 for (ScopedVector<WebSocketFrameChunk>::const_iterator it = vector.begin(); 71 it != vector.end(); 72 ++it) { 73 if (!first) { 74 os << ",\n"; 75 } else { 76 first = false; 77 } 78 os << **it; 79 } 80 return os << "}"; 81 } 82 83 std::ostream& operator<<(std::ostream& os, 84 const ScopedVector<WebSocketFrameChunk>* vector) { 85 return os << '&' << *vector; 86 } 87 88 namespace { 89 90 using ::testing::AnyNumber; 91 using ::testing::InSequence; 92 using ::testing::MockFunction; 93 using ::testing::Return; 94 using ::testing::SaveArg; 95 using ::testing::StrictMock; 96 using ::testing::_; 97 98 // A selection of characters that have traditionally been mangled in some 99 // environment or other, for testing 8-bit cleanliness. 100 const char kBinaryBlob[] = {'\n', '\r', // BACKWARDS CRNL 101 '\0', // nul 102 '\x7F', // DEL 103 '\x80', '\xFF', // NOT VALID UTF-8 104 '\x1A', // Control-Z, EOF on DOS 105 '\x03', // Control-C 106 '\x04', // EOT, special for Unix terms 107 '\x1B', // ESC, often special 108 '\b', // backspace 109 '\'', // single-quote, special in PHP 110 }; 111 const size_t kBinaryBlobSize = arraysize(kBinaryBlob); 112 113 // The amount of quota a new connection gets by default. 114 // TODO(ricea): If kDefaultSendQuotaHighWaterMark changes, then this value will 115 // need to be updated. 116 const size_t kDefaultInitialQuota = 1 << 17; 117 // The amount of bytes we need to send after the initial connection to trigger a 118 // quota refresh. TODO(ricea): Change this if kDefaultSendQuotaHighWaterMark or 119 // kDefaultSendQuotaLowWaterMark change. 120 const size_t kDefaultQuotaRefreshTrigger = (1 << 16) + 1; 121 122 // This mock is for testing expectations about how the EventInterface is used. 123 class MockWebSocketEventInterface : public WebSocketEventInterface { 124 public: 125 MOCK_METHOD2(OnAddChannelResponse, void(bool, const std::string&)); 126 MOCK_METHOD3(OnDataFrame, 127 void(bool, WebSocketMessageType, const std::vector<char>&)); 128 MOCK_METHOD1(OnFlowControl, void(int64)); 129 MOCK_METHOD0(OnClosingHandshake, void(void)); 130 MOCK_METHOD2(OnDropChannel, void(uint16, const std::string&)); 131 }; 132 133 // This fake EventInterface is for tests which need a WebSocketEventInterface 134 // implementation but are not verifying how it is used. 135 class FakeWebSocketEventInterface : public WebSocketEventInterface { 136 virtual void OnAddChannelResponse( 137 bool fail, 138 const std::string& selected_protocol) OVERRIDE {} 139 virtual void OnDataFrame(bool fin, 140 WebSocketMessageType type, 141 const std::vector<char>& data) OVERRIDE {} 142 virtual void OnFlowControl(int64 quota) OVERRIDE {} 143 virtual void OnClosingHandshake() OVERRIDE {} 144 virtual void OnDropChannel(uint16 code, const std::string& reason) OVERRIDE {} 145 }; 146 147 // This fake WebSocketStream is for tests that require a WebSocketStream but are 148 // not testing the way it is used. It has minimal functionality to return 149 // the |protocol| and |extensions| that it was constructed with. 150 class FakeWebSocketStream : public WebSocketStream { 151 public: 152 // Constructs with empty protocol and extensions. 153 FakeWebSocketStream() {} 154 155 // Constructs with specified protocol and extensions. 156 FakeWebSocketStream(const std::string& protocol, 157 const std::string& extensions) 158 : protocol_(protocol), extensions_(extensions) {} 159 160 virtual int SendHandshakeRequest( 161 const GURL& url, 162 const HttpRequestHeaders& headers, 163 HttpResponseInfo* response_info, 164 const CompletionCallback& callback) OVERRIDE { 165 return ERR_IO_PENDING; 166 } 167 168 virtual int ReadHandshakeResponse( 169 const CompletionCallback& callback) OVERRIDE { 170 return ERR_IO_PENDING; 171 } 172 173 virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, 174 const CompletionCallback& callback) OVERRIDE { 175 return ERR_IO_PENDING; 176 } 177 178 virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, 179 const CompletionCallback& callback) OVERRIDE { 180 return ERR_IO_PENDING; 181 } 182 183 virtual void Close() OVERRIDE {} 184 185 // Returns the string passed to the constructor. 186 virtual std::string GetSubProtocol() const OVERRIDE { return protocol_; } 187 188 // Returns the string passed to the constructor. 189 virtual std::string GetExtensions() const OVERRIDE { return extensions_; } 190 191 private: 192 // The string to return from GetSubProtocol(). 193 std::string protocol_; 194 195 // The string to return from GetExtensions(). 196 std::string extensions_; 197 }; 198 199 // To make the static initialisers easier to read, we use enums rather than 200 // bools. 201 202 // NO_HEADER means there shouldn't be a header included in the generated 203 // WebSocketFrameChunk. The static initialiser always has a header, but we can 204 // avoid specifying the rest of the fields. 205 enum IsFinal { 206 NO_HEADER, 207 NOT_FINAL_FRAME, 208 FINAL_FRAME 209 }; 210 211 enum IsMasked { 212 NOT_MASKED, 213 MASKED 214 }; 215 216 enum IsFinalChunk { 217 NOT_FINAL_CHUNK, 218 FINAL_CHUNK 219 }; 220 221 // This is used to initialise a WebSocketFrameChunk but is statically 222 // initialisable. 223 struct InitFrameChunk { 224 struct FrameHeader { 225 IsFinal final; 226 // Reserved fields omitted for now. Add them if you need them. 227 WebSocketFrameHeader::OpCode opcode; 228 IsMasked masked; 229 // payload_length is the length of the whole frame. The length of the data 230 // members from every chunk in the frame must add up to the payload_length. 231 uint64 payload_length; 232 }; 233 FrameHeader header; 234 235 // Directly equivalent to WebSocketFrameChunk::final_chunk 236 IsFinalChunk final_chunk; 237 238 // Will be used to create the IOBuffer member. Can be NULL for NULL data. Is a 239 // nul-terminated string for ease-of-use. This means it is not 8-bit clean, 240 // but this is not an issue for test data. 241 const char* const data; 242 }; 243 244 // For GoogleMock 245 std::ostream& operator<<(std::ostream& os, const InitFrameChunk& chunk) { 246 os << "{"; 247 if (chunk.header.final != NO_HEADER) { 248 os << "{" << (chunk.header.final == FINAL_FRAME ? "FINAL_FRAME" 249 : "NOT_FINAL_FRAME") << ", " 250 << chunk.header.opcode << ", " 251 << (chunk.header.masked == MASKED ? "MASKED" : "NOT_MASKED") << ", " 252 << chunk.header.payload_length << "}"; 253 254 } else { 255 os << "{NO_HEADER}"; 256 } 257 return os << ", " << (chunk.final_chunk == FINAL_CHUNK ? "FINAL_CHUNK" 258 : "NOT_FINAL_CHUNK") 259 << ", \"" << chunk.data << "\"}"; 260 } 261 262 template <size_t N> 263 std::ostream& operator<<(std::ostream& os, const InitFrameChunk (&chunks)[N]) { 264 os << "{"; 265 bool first = true; 266 for (size_t i = 0; i < N; ++i) { 267 if (!first) { 268 os << ",\n"; 269 } else { 270 first = false; 271 } 272 os << chunks[i]; 273 } 274 return os << "}"; 275 } 276 277 // Convert a const array of InitFrameChunks to the format used at 278 // runtime. Templated on the size of the array to save typing. 279 template <size_t N> 280 ScopedVector<WebSocketFrameChunk> CreateFrameChunkVector( 281 const InitFrameChunk (&source_chunks)[N]) { 282 ScopedVector<WebSocketFrameChunk> result_chunks; 283 result_chunks.reserve(N); 284 for (size_t i = 0; i < N; ++i) { 285 scoped_ptr<WebSocketFrameChunk> result_chunk(new WebSocketFrameChunk); 286 size_t chunk_length = 287 source_chunks[i].data ? strlen(source_chunks[i].data) : 0; 288 if (source_chunks[i].header.final != NO_HEADER) { 289 const InitFrameChunk::FrameHeader& source_header = 290 source_chunks[i].header; 291 scoped_ptr<WebSocketFrameHeader> result_header( 292 new WebSocketFrameHeader(source_header.opcode)); 293 result_header->final = (source_header.final == FINAL_FRAME); 294 result_header->masked = (source_header.masked == MASKED); 295 result_header->payload_length = source_header.payload_length; 296 DCHECK(chunk_length <= source_header.payload_length); 297 result_chunk->header.swap(result_header); 298 } 299 result_chunk->final_chunk = (source_chunks[i].final_chunk == FINAL_CHUNK); 300 if (source_chunks[i].data) { 301 result_chunk->data = new IOBufferWithSize(chunk_length); 302 memcpy(result_chunk->data->data(), source_chunks[i].data, chunk_length); 303 } 304 result_chunks.push_back(result_chunk.release()); 305 } 306 return result_chunks.Pass(); 307 } 308 309 // A GoogleMock action which can be used to respond to call to ReadFrames with 310 // some frames. Use like ReadFrames(_, _).WillOnce(ReturnChunks(&chunks)); 311 // |chunks| is an array of InitFrameChunks needs to be passed by pointer because 312 // otherwise it will be reduced to a pointer and lose the array size 313 // information. 314 ACTION_P(ReturnChunks, source_chunks) { 315 *arg0 = CreateFrameChunkVector(*source_chunks); 316 return OK; 317 } 318 319 // The implementation of a GoogleMock matcher which can be used to compare a 320 // ScopedVector<WebSocketFrameChunk>* against an expectation defined as an array 321 // of InitFrameChunks. Although it is possible to compose built-in GoogleMock 322 // matchers to check the contents of a WebSocketFrameChunk, the results are so 323 // unreadable that it is better to use this matcher. 324 template <size_t N> 325 class EqualsChunksMatcher 326 : public ::testing::MatcherInterface<ScopedVector<WebSocketFrameChunk>*> { 327 public: 328 EqualsChunksMatcher(const InitFrameChunk (*expect_chunks)[N]) 329 : expect_chunks_(expect_chunks) {} 330 331 virtual bool MatchAndExplain(ScopedVector<WebSocketFrameChunk>* actual_chunks, 332 ::testing::MatchResultListener* listener) const { 333 if (actual_chunks->size() != N) { 334 *listener << "the vector size is " << actual_chunks->size(); 335 return false; 336 } 337 for (size_t i = 0; i < N; ++i) { 338 const WebSocketFrameChunk& actual_chunk = *(*actual_chunks)[i]; 339 const InitFrameChunk& expected_chunk = (*expect_chunks_)[i]; 340 // Testing that the absence or presence of a header is the same for both. 341 if ((!actual_chunk.header) != 342 (expected_chunk.header.final == NO_HEADER)) { 343 *listener << "the header is " 344 << (actual_chunk.header ? "present" : "absent"); 345 return false; 346 } 347 if (actual_chunk.header) { 348 if (actual_chunk.header->final != 349 (expected_chunk.header.final == FINAL_FRAME)) { 350 *listener << "the frame is marked as " 351 << (actual_chunk.header->final ? "" : "not ") << "final"; 352 return false; 353 } 354 if (actual_chunk.header->opcode != expected_chunk.header.opcode) { 355 *listener << "the opcode is " << actual_chunk.header->opcode; 356 return false; 357 } 358 if (actual_chunk.header->masked != 359 (expected_chunk.header.masked == MASKED)) { 360 *listener << "the frame is " 361 << (actual_chunk.header->masked ? "masked" : "not masked"); 362 return false; 363 } 364 if (actual_chunk.header->payload_length != 365 expected_chunk.header.payload_length) { 366 *listener << "the payload length is " 367 << actual_chunk.header->payload_length; 368 return false; 369 } 370 } 371 if (actual_chunk.final_chunk != 372 (expected_chunk.final_chunk == FINAL_CHUNK)) { 373 *listener << "the chunk is marked as " 374 << (actual_chunk.final_chunk ? "" : "not ") << "final"; 375 return false; 376 } 377 if (actual_chunk.data->size() != 378 base::checked_numeric_cast<int>(strlen(expected_chunk.data))) { 379 *listener << "the data size is " << actual_chunk.data->size(); 380 return false; 381 } 382 if (memcmp(actual_chunk.data->data(), 383 expected_chunk.data, 384 actual_chunk.data->size()) != 0) { 385 *listener << "the data content differs"; 386 return false; 387 } 388 } 389 return true; 390 } 391 392 virtual void DescribeTo(std::ostream* os) const { 393 *os << "matches " << *expect_chunks_; 394 } 395 396 virtual void DescribeNegationTo(std::ostream* os) const { 397 *os << "does not match " << *expect_chunks_; 398 } 399 400 private: 401 const InitFrameChunk (*expect_chunks_)[N]; 402 }; 403 404 // The definition of EqualsChunks GoogleMock matcher. Unlike the ReturnChunks 405 // action, this can take the array by reference. 406 template <size_t N> 407 ::testing::Matcher<ScopedVector<WebSocketFrameChunk>*> EqualsChunks( 408 const InitFrameChunk (&chunks)[N]) { 409 return ::testing::MakeMatcher(new EqualsChunksMatcher<N>(&chunks)); 410 } 411 412 // A FakeWebSocketStream whose ReadFrames() function returns data. 413 class ReadableFakeWebSocketStream : public FakeWebSocketStream { 414 public: 415 enum IsSync { 416 SYNC, 417 ASYNC 418 }; 419 420 // After constructing the object, call PrepareReadFrames() once for each 421 // time you wish it to return from the test. 422 ReadableFakeWebSocketStream() : index_(0), read_frames_pending_(false) {} 423 424 // Check that all the prepared responses have been consumed. 425 virtual ~ReadableFakeWebSocketStream() { 426 CHECK(index_ >= responses_.size()); 427 CHECK(!read_frames_pending_); 428 } 429 430 // Prepares a fake responses. Fake responses will be returned from 431 // ReadFrames() in the same order they were prepared with PrepareReadFrames() 432 // and PrepareReadFramesError(). If |async| is ASYNC, then ReadFrames() will 433 // return ERR_IO_PENDING and the callback will be scheduled to run on the 434 // message loop. This requires the test case to run the message loop. If 435 // |async| is SYNC, the response will be returned synchronously. |error| is 436 // returned directly from ReadFrames() in the synchronous case, or passed to 437 // the callback in the asynchronous case. |chunks| will be converted to a 438 // ScopedVector<WebSocketFrameChunks> and copied to the pointer that was 439 // passed to ReadFrames(). 440 template <size_t N> 441 void PrepareReadFrames(IsSync async, 442 int error, 443 const InitFrameChunk (&chunks)[N]) { 444 responses_.push_back( 445 new Response(async, error, CreateFrameChunkVector(chunks))); 446 } 447 448 // An alternate version of PrepareReadFrames for when we need to construct 449 // the frames manually. 450 void PrepareRawReadFrames(IsSync async, 451 int error, 452 ScopedVector<WebSocketFrameChunk> chunks) { 453 responses_.push_back(new Response(async, error, chunks.Pass())); 454 } 455 456 // Prepares a fake error response (ie. there is no data). 457 void PrepareReadFramesError(IsSync async, int error) { 458 responses_.push_back( 459 new Response(async, error, ScopedVector<WebSocketFrameChunk>())); 460 } 461 462 virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, 463 const CompletionCallback& callback) OVERRIDE { 464 CHECK(!read_frames_pending_); 465 if (index_ >= responses_.size()) 466 return ERR_IO_PENDING; 467 if (responses_[index_]->async == ASYNC) { 468 read_frames_pending_ = true; 469 base::MessageLoop::current()->PostTask( 470 FROM_HERE, 471 base::Bind(&ReadableFakeWebSocketStream::DoCallback, 472 base::Unretained(this), 473 frame_chunks, 474 callback)); 475 return ERR_IO_PENDING; 476 } else { 477 frame_chunks->swap(responses_[index_]->chunks); 478 return responses_[index_++]->error; 479 } 480 } 481 482 private: 483 void DoCallback(ScopedVector<WebSocketFrameChunk>* frame_chunks, 484 const CompletionCallback& callback) { 485 read_frames_pending_ = false; 486 frame_chunks->swap(responses_[index_]->chunks); 487 callback.Run(responses_[index_++]->error); 488 return; 489 } 490 491 struct Response { 492 Response(IsSync async, int error, ScopedVector<WebSocketFrameChunk> chunks) 493 : async(async), error(error), chunks(chunks.Pass()) {} 494 495 IsSync async; 496 int error; 497 ScopedVector<WebSocketFrameChunk> chunks; 498 499 private: 500 // Bad things will happen if we attempt to copy or assign "chunks". 501 DISALLOW_COPY_AND_ASSIGN(Response); 502 }; 503 ScopedVector<Response> responses_; 504 505 // The index into the responses_ array of the next response to be returned. 506 size_t index_; 507 508 // True when an async response from ReadFrames() is pending. This only applies 509 // to "real" async responses. Once all the prepared responses have been 510 // returned, ReadFrames() returns ERR_IO_PENDING but read_frames_pending_ is 511 // not set to true. 512 bool read_frames_pending_; 513 }; 514 515 // A FakeWebSocketStream where writes always complete successfully and 516 // synchronously. 517 class WriteableFakeWebSocketStream : public FakeWebSocketStream { 518 public: 519 virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, 520 const CompletionCallback& callback) OVERRIDE { 521 return OK; 522 } 523 }; 524 525 // A FakeWebSocketStream where writes always fail. 526 class UnWriteableFakeWebSocketStream : public FakeWebSocketStream { 527 public: 528 virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, 529 const CompletionCallback& callback) OVERRIDE { 530 return ERR_CONNECTION_RESET; 531 } 532 }; 533 534 // A FakeWebSocketStream which echoes any frames written back. Clears the 535 // "masked" header bit, but makes no other checks for validity. Tests using this 536 // must run the MessageLoop to receive the callback(s). If a message with opcode 537 // Close is echoed, then an ERR_CONNECTION_CLOSED is returned in the next 538 // callback. The test must do something to cause WriteFrames() to be called, 539 // otherwise the ReadFrames() callback will never be called. 540 class EchoeyFakeWebSocketStream : public FakeWebSocketStream { 541 public: 542 EchoeyFakeWebSocketStream() : read_frame_chunks_(NULL), done_(false) {} 543 544 virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, 545 const CompletionCallback& callback) OVERRIDE { 546 // Users of WebSocketStream will not expect the ReadFrames() callback to be 547 // called from within WriteFrames(), so post it to the message loop instead. 548 stored_frame_chunks_.insert( 549 stored_frame_chunks_.end(), frame_chunks->begin(), frame_chunks->end()); 550 frame_chunks->weak_clear(); 551 PostCallback(); 552 return OK; 553 } 554 555 virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, 556 const CompletionCallback& callback) OVERRIDE { 557 read_callback_ = callback; 558 read_frame_chunks_ = frame_chunks; 559 if (done_) 560 PostCallback(); 561 return ERR_IO_PENDING; 562 } 563 564 private: 565 void PostCallback() { 566 base::MessageLoop::current()->PostTask( 567 FROM_HERE, 568 base::Bind(&EchoeyFakeWebSocketStream::DoCallback, 569 base::Unretained(this))); 570 } 571 572 void DoCallback() { 573 if (done_) { 574 read_callback_.Run(ERR_CONNECTION_CLOSED); 575 } else if (!stored_frame_chunks_.empty()) { 576 done_ = MoveFrameChunks(read_frame_chunks_); 577 read_frame_chunks_ = NULL; 578 read_callback_.Run(OK); 579 } 580 } 581 582 // Copy the chunks stored in stored_frame_chunks_ to |out|, while clearing the 583 // "masked" header bit. Returns true if a Close Frame was seen, false 584 // otherwise. 585 bool MoveFrameChunks(ScopedVector<WebSocketFrameChunk>* out) { 586 bool seen_close = false; 587 *out = stored_frame_chunks_.Pass(); 588 for (ScopedVector<WebSocketFrameChunk>::iterator it = out->begin(); 589 it != out->end(); 590 ++it) { 591 WebSocketFrameHeader* header = (*it)->header.get(); 592 if (header) { 593 header->masked = false; 594 if (header->opcode == WebSocketFrameHeader::kOpCodeClose) 595 seen_close = true; 596 } 597 } 598 return seen_close; 599 } 600 601 ScopedVector<WebSocketFrameChunk> stored_frame_chunks_; 602 CompletionCallback read_callback_; 603 // Owned by the caller of ReadFrames(). 604 ScopedVector<WebSocketFrameChunk>* read_frame_chunks_; 605 // True if we should close the connection. 606 bool done_; 607 }; 608 609 // A FakeWebSocketStream where writes trigger a connection reset. 610 // This differs from UnWriteableFakeWebSocketStream in that it is asynchronous 611 // and triggers ReadFrames to return a reset as well. Tests using this need to 612 // run the message loop. 613 class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream { 614 public: 615 virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, 616 const CompletionCallback& callback) OVERRIDE { 617 base::MessageLoop::current()->PostTask( 618 FROM_HERE, base::Bind(callback, ERR_CONNECTION_RESET)); 619 base::MessageLoop::current()->PostTask( 620 FROM_HERE, base::Bind(read_callback_, ERR_CONNECTION_RESET)); 621 return ERR_IO_PENDING; 622 } 623 624 virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, 625 const CompletionCallback& callback) OVERRIDE { 626 read_callback_ = callback; 627 return ERR_IO_PENDING; 628 } 629 630 private: 631 CompletionCallback read_callback_; 632 }; 633 634 // This mock is for verifying that WebSocket protocol semantics are obeyed (to 635 // the extent that they are implemented in WebSocketCommon). 636 class MockWebSocketStream : public WebSocketStream { 637 public: 638 MOCK_METHOD2(ReadFrames, 639 int(ScopedVector<WebSocketFrameChunk>* frame_chunks, 640 const CompletionCallback& callback)); 641 MOCK_METHOD2(WriteFrames, 642 int(ScopedVector<WebSocketFrameChunk>* frame_chunks, 643 const CompletionCallback& callback)); 644 MOCK_METHOD0(Close, void()); 645 MOCK_CONST_METHOD0(GetSubProtocol, std::string()); 646 MOCK_CONST_METHOD0(GetExtensions, std::string()); 647 MOCK_METHOD0(AsWebSocketStream, WebSocketStream*()); 648 MOCK_METHOD4(SendHandshakeRequest, 649 int(const GURL& url, 650 const HttpRequestHeaders& headers, 651 HttpResponseInfo* response_info, 652 const CompletionCallback& callback)); 653 MOCK_METHOD1(ReadHandshakeResponse, int(const CompletionCallback& callback)); 654 }; 655 656 struct ArgumentCopyingWebSocketFactory { 657 scoped_ptr<WebSocketStreamRequest> Factory( 658 const GURL& socket_url, 659 const std::vector<std::string>& requested_subprotocols, 660 const GURL& origin, 661 URLRequestContext* url_request_context, 662 const BoundNetLog& net_log, 663 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) { 664 this->socket_url = socket_url; 665 this->requested_subprotocols = requested_subprotocols; 666 this->origin = origin; 667 this->url_request_context = url_request_context; 668 this->net_log = net_log; 669 this->connect_delegate = connect_delegate.Pass(); 670 return make_scoped_ptr(new WebSocketStreamRequest); 671 } 672 673 GURL socket_url; 674 GURL origin; 675 std::vector<std::string> requested_subprotocols; 676 URLRequestContext* url_request_context; 677 BoundNetLog net_log; 678 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate; 679 }; 680 681 // Converts a std::string to a std::vector<char>. For test purposes, it is 682 // convenient to be able to specify data as a string, but the 683 // WebSocketEventInterface requires the vector<char> type. 684 std::vector<char> AsVector(const std::string& s) { 685 return std::vector<char>(s.begin(), s.end()); 686 } 687 688 // Base class for all test fixtures. 689 class WebSocketChannelTest : public ::testing::Test { 690 protected: 691 WebSocketChannelTest() : stream_(new FakeWebSocketStream) {} 692 693 // Creates a new WebSocketChannel and connects it, using the settings stored 694 // in |connect_data_|. 695 void CreateChannelAndConnect() { 696 channel_.reset( 697 new WebSocketChannel(connect_data_.url, CreateEventInterface())); 698 channel_->SendAddChannelRequestForTesting( 699 connect_data_.requested_subprotocols, 700 connect_data_.origin, 701 &connect_data_.url_request_context, 702 base::Bind(&ArgumentCopyingWebSocketFactory::Factory, 703 base::Unretained(&connect_data_.factory))); 704 } 705 706 // Same as CreateChannelAndConnect(), but calls the on_success callback as 707 // well. This method is virtual so that subclasses can also set the stream. 708 virtual void CreateChannelAndConnectSuccessfully() { 709 CreateChannelAndConnect(); 710 connect_data_.factory.connect_delegate->OnSuccess(stream_.Pass()); 711 } 712 713 // Returns a WebSocketEventInterface to be passed to the WebSocketChannel. 714 // This implementation returns a newly-created fake. Subclasses may return a 715 // mock instead. 716 virtual scoped_ptr<WebSocketEventInterface> CreateEventInterface() { 717 return scoped_ptr<WebSocketEventInterface>(new FakeWebSocketEventInterface); 718 } 719 720 // This method serves no other purpose than to provide a nice syntax for 721 // assigning to stream_. class T must be a subclass of WebSocketStream or you 722 // will have unpleasant compile errors. 723 template <class T> 724 void set_stream(scoped_ptr<T> stream) { 725 // Since the definition of "PassAs" depends on the type T, the C++ standard 726 // requires the "template" keyword to indicate that "PassAs" should be 727 // parsed as a template method. 728 stream_ = stream.template PassAs<WebSocketStream>(); 729 } 730 731 // A struct containing the data that will be used to connect the channel. 732 struct ConnectData { 733 // URL to (pretend to) connect to. 734 GURL url; 735 // Origin of the request 736 GURL origin; 737 // Requested protocols for the request. 738 std::vector<std::string> requested_subprotocols; 739 // URLRequestContext object. 740 URLRequestContext url_request_context; 741 // A fake WebSocketFactory that just records its arguments. 742 ArgumentCopyingWebSocketFactory factory; 743 }; 744 ConnectData connect_data_; 745 746 // The channel we are testing. Not initialised until SetChannel() is called. 747 scoped_ptr<WebSocketChannel> channel_; 748 749 // A mock or fake stream for tests that need one. 750 scoped_ptr<WebSocketStream> stream_; 751 }; 752 753 class WebSocketChannelDeletingTest : public WebSocketChannelTest { 754 public: 755 void ResetChannel() { channel_.reset(); } 756 757 protected: 758 // Create a ChannelDeletingFakeWebSocketEventInterface. Defined out-of-line to 759 // avoid circular dependency. 760 virtual scoped_ptr<WebSocketEventInterface> CreateEventInterface() OVERRIDE; 761 }; 762 763 // A FakeWebSocketEventInterface that deletes the WebSocketChannel on failure to 764 // connect. 765 class ChannelDeletingFakeWebSocketEventInterface 766 : public FakeWebSocketEventInterface { 767 public: 768 ChannelDeletingFakeWebSocketEventInterface( 769 WebSocketChannelDeletingTest* fixture) 770 : fixture_(fixture) {} 771 772 virtual void OnAddChannelResponse( 773 bool fail, 774 const std::string& selected_protocol) OVERRIDE { 775 if (fail) { 776 fixture_->ResetChannel(); 777 } 778 } 779 780 private: 781 // A pointer to the test fixture. Owned by the test harness; this object will 782 // be deleted before it is. 783 WebSocketChannelDeletingTest* fixture_; 784 }; 785 786 scoped_ptr<WebSocketEventInterface> 787 WebSocketChannelDeletingTest::CreateEventInterface() { 788 return scoped_ptr<WebSocketEventInterface>( 789 new ChannelDeletingFakeWebSocketEventInterface(this)); 790 } 791 792 // Base class for tests which verify that EventInterface methods are called 793 // appropriately. 794 class WebSocketChannelEventInterfaceTest : public WebSocketChannelTest { 795 protected: 796 WebSocketChannelEventInterfaceTest() 797 : event_interface_(new StrictMock<MockWebSocketEventInterface>) {} 798 799 // Tests using this fixture must set expectations on the event_interface_ mock 800 // object before calling CreateChannelAndConnect() or 801 // CreateChannelAndConnectSuccessfully(). This will only work once per test 802 // case, but once should be enough. 803 virtual scoped_ptr<WebSocketEventInterface> CreateEventInterface() OVERRIDE { 804 return scoped_ptr<WebSocketEventInterface>(event_interface_.release()); 805 } 806 807 scoped_ptr<MockWebSocketEventInterface> event_interface_; 808 }; 809 810 // Base class for tests which verify that WebSocketStream methods are called 811 // appropriately by using a MockWebSocketStream. 812 class WebSocketChannelStreamTest : public WebSocketChannelTest { 813 protected: 814 WebSocketChannelStreamTest() 815 : mock_stream_(new StrictMock<MockWebSocketStream>) {} 816 817 virtual void CreateChannelAndConnectSuccessfully() OVERRIDE { 818 set_stream(mock_stream_.Pass()); 819 WebSocketChannelTest::CreateChannelAndConnectSuccessfully(); 820 } 821 822 scoped_ptr<MockWebSocketStream> mock_stream_; 823 }; 824 825 // Simple test that everything that should be passed to the factory function is 826 // passed to the factory function. 827 TEST_F(WebSocketChannelTest, EverythingIsPassedToTheFactoryFunction) { 828 connect_data_.url = GURL("ws://example.com/test"); 829 connect_data_.origin = GURL("http://example.com/test"); 830 connect_data_.requested_subprotocols.push_back("Sinbad"); 831 832 CreateChannelAndConnect(); 833 834 EXPECT_EQ(connect_data_.url, connect_data_.factory.socket_url); 835 EXPECT_EQ(connect_data_.origin, connect_data_.factory.origin); 836 EXPECT_EQ(connect_data_.requested_subprotocols, 837 connect_data_.factory.requested_subprotocols); 838 EXPECT_EQ(&connect_data_.url_request_context, 839 connect_data_.factory.url_request_context); 840 } 841 842 // The documentation for WebSocketEventInterface::OnAddChannelResponse() says 843 // that if the first argument is true, ie. the connection failed, then we can 844 // safely synchronously delete the WebSocketChannel. This test will only 845 // reliably find problems if run with a memory debugger such as 846 // AddressSanitizer. 847 TEST_F(WebSocketChannelDeletingTest, DeletingFromOnAddChannelResponseWorks) { 848 CreateChannelAndConnect(); 849 connect_data_.factory.connect_delegate 850 ->OnFailure(kWebSocketErrorNoStatusReceived); 851 EXPECT_EQ(NULL, channel_.get()); 852 } 853 854 TEST_F(WebSocketChannelEventInterfaceTest, ConnectSuccessReported) { 855 // false means success. 856 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, "")); 857 // OnFlowControl is always called immediately after connect to provide initial 858 // quota to the renderer. 859 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 860 861 CreateChannelAndConnect(); 862 863 connect_data_.factory.connect_delegate->OnSuccess(stream_.Pass()); 864 } 865 866 TEST_F(WebSocketChannelEventInterfaceTest, ConnectFailureReported) { 867 // true means failure. 868 EXPECT_CALL(*event_interface_, OnAddChannelResponse(true, "")); 869 870 CreateChannelAndConnect(); 871 872 connect_data_.factory.connect_delegate 873 ->OnFailure(kWebSocketErrorNoStatusReceived); 874 } 875 876 TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) { 877 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, "Bob")); 878 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 879 880 CreateChannelAndConnect(); 881 882 connect_data_.factory.connect_delegate->OnSuccess( 883 scoped_ptr<WebSocketStream>(new FakeWebSocketStream("Bob", ""))); 884 } 885 886 // The first frames from the server can arrive together with the handshake, in 887 // which case they will be available as soon as ReadFrames() is called the first 888 // time. 889 TEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) { 890 scoped_ptr<ReadableFakeWebSocketStream> stream( 891 new ReadableFakeWebSocketStream); 892 static const InitFrameChunk chunks[] = { 893 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5}, 894 FINAL_CHUNK, "HELLO"}}; 895 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks); 896 set_stream(stream.Pass()); 897 { 898 InSequence s; 899 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 900 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 901 EXPECT_CALL( 902 *event_interface_, 903 OnDataFrame( 904 true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO"))); 905 } 906 907 CreateChannelAndConnectSuccessfully(); 908 } 909 910 // A remote server could accept the handshake, but then immediately send a 911 // Close frame. 912 TEST_F(WebSocketChannelEventInterfaceTest, CloseAfterHandshake) { 913 scoped_ptr<ReadableFakeWebSocketStream> stream( 914 new ReadableFakeWebSocketStream); 915 static const InitFrameChunk chunks[] = { 916 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 23}, 917 FINAL_CHUNK, CLOSE_DATA(SERVER_ERROR, "Internal Server Error")}}; 918 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks); 919 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, 920 ERR_CONNECTION_CLOSED); 921 set_stream(stream.Pass()); 922 { 923 InSequence s; 924 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 925 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 926 EXPECT_CALL(*event_interface_, OnClosingHandshake()); 927 EXPECT_CALL(*event_interface_, 928 OnDropChannel(kWebSocketErrorInternalServerError, 929 "Internal Server Error")); 930 } 931 932 CreateChannelAndConnectSuccessfully(); 933 } 934 935 // A remote server could close the connection immediately after sending the 936 // handshake response (most likely a bug in the server). 937 TEST_F(WebSocketChannelEventInterfaceTest, ConnectionCloseAfterHandshake) { 938 scoped_ptr<ReadableFakeWebSocketStream> stream( 939 new ReadableFakeWebSocketStream); 940 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, 941 ERR_CONNECTION_CLOSED); 942 set_stream(stream.Pass()); 943 { 944 InSequence s; 945 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 946 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 947 EXPECT_CALL(*event_interface_, 948 OnDropChannel(kWebSocketErrorAbnormalClosure, _)); 949 } 950 951 CreateChannelAndConnectSuccessfully(); 952 } 953 954 TEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) { 955 scoped_ptr<ReadableFakeWebSocketStream> stream( 956 new ReadableFakeWebSocketStream); 957 static const InitFrameChunk chunks[] = { 958 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5}, 959 FINAL_CHUNK, "HELLO"}}; 960 // We use this checkpoint object to verify that the callback isn't called 961 // until we expect it to be. 962 MockFunction<void(int)> checkpoint; 963 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks); 964 set_stream(stream.Pass()); 965 { 966 InSequence s; 967 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 968 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 969 EXPECT_CALL(checkpoint, Call(1)); 970 EXPECT_CALL( 971 *event_interface_, 972 OnDataFrame( 973 true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO"))); 974 EXPECT_CALL(checkpoint, Call(2)); 975 } 976 977 CreateChannelAndConnectSuccessfully(); 978 checkpoint.Call(1); 979 base::MessageLoop::current()->RunUntilIdle(); 980 checkpoint.Call(2); 981 } 982 983 // Extra data can arrive while a read is being processed, resulting in the next 984 // read completing synchronously. 985 TEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) { 986 scoped_ptr<ReadableFakeWebSocketStream> stream( 987 new ReadableFakeWebSocketStream); 988 static const InitFrameChunk chunks1[] = { 989 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5}, 990 FINAL_CHUNK, "HELLO"}}; 991 static const InitFrameChunk chunks2[] = { 992 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5}, 993 FINAL_CHUNK, "WORLD"}}; 994 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1); 995 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks2); 996 set_stream(stream.Pass()); 997 { 998 InSequence s; 999 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1000 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1001 EXPECT_CALL( 1002 *event_interface_, 1003 OnDataFrame( 1004 true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO"))); 1005 EXPECT_CALL( 1006 *event_interface_, 1007 OnDataFrame( 1008 true, WebSocketFrameHeader::kOpCodeText, AsVector("WORLD"))); 1009 } 1010 1011 CreateChannelAndConnectSuccessfully(); 1012 base::MessageLoop::current()->RunUntilIdle(); 1013 } 1014 1015 // Data frames that arrive in fragments are turned into individual frames 1016 TEST_F(WebSocketChannelEventInterfaceTest, FragmentedFrames) { 1017 scoped_ptr<ReadableFakeWebSocketStream> stream( 1018 new ReadableFakeWebSocketStream); 1019 // Here we have one message split into 3 frames which arrive in 3 chunks. The 1020 // first frame is entirely in the first chunk, the second frame is split 1021 // across all the chunks, and the final frame is entirely in the final 1022 // chunk. The frame fragments are converted to separate frames so that they 1023 // can be delivered immediatedly. So the EventInterface should see a Text 1024 // message with 5 frames. 1025 static const InitFrameChunk chunks1[] = { 1026 {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5}, 1027 FINAL_CHUNK, "THREE"}, 1028 {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, 1029 7}, 1030 NOT_FINAL_CHUNK, " "}}; 1031 static const InitFrameChunk chunks2[] = { 1032 {{NO_HEADER}, NOT_FINAL_CHUNK, "SMALL"}}; 1033 static const InitFrameChunk chunks3[] = { 1034 {{NO_HEADER}, FINAL_CHUNK, " "}, 1035 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, 6}, 1036 FINAL_CHUNK, "FRAMES"}}; 1037 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1); 1038 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2); 1039 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3); 1040 set_stream(stream.Pass()); 1041 { 1042 InSequence s; 1043 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1044 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1045 EXPECT_CALL( 1046 *event_interface_, 1047 OnDataFrame( 1048 false, WebSocketFrameHeader::kOpCodeText, AsVector("THREE"))); 1049 EXPECT_CALL( 1050 *event_interface_, 1051 OnDataFrame( 1052 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector(" "))); 1053 EXPECT_CALL(*event_interface_, 1054 OnDataFrame(false, 1055 WebSocketFrameHeader::kOpCodeContinuation, 1056 AsVector("SMALL"))); 1057 EXPECT_CALL( 1058 *event_interface_, 1059 OnDataFrame( 1060 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector(" "))); 1061 EXPECT_CALL(*event_interface_, 1062 OnDataFrame(true, 1063 WebSocketFrameHeader::kOpCodeContinuation, 1064 AsVector("FRAMES"))); 1065 } 1066 1067 CreateChannelAndConnectSuccessfully(); 1068 base::MessageLoop::current()->RunUntilIdle(); 1069 } 1070 1071 // In the case when a single-frame message because fragmented, it must be 1072 // correctly transformed to multiple frames. 1073 TEST_F(WebSocketChannelEventInterfaceTest, MessageFragmentation) { 1074 scoped_ptr<ReadableFakeWebSocketStream> stream( 1075 new ReadableFakeWebSocketStream); 1076 // A single-frame Text message arrives in three chunks. This should be 1077 // delivered as three frames. 1078 static const InitFrameChunk chunks1[] = { 1079 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 12}, 1080 NOT_FINAL_CHUNK, "TIME"}}; 1081 static const InitFrameChunk chunks2[] = { 1082 {{NO_HEADER}, NOT_FINAL_CHUNK, " FOR "}}; 1083 static const InitFrameChunk chunks3[] = {{{NO_HEADER}, FINAL_CHUNK, "TEA"}}; 1084 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1); 1085 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2); 1086 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3); 1087 set_stream(stream.Pass()); 1088 { 1089 InSequence s; 1090 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1091 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1092 EXPECT_CALL( 1093 *event_interface_, 1094 OnDataFrame( 1095 false, WebSocketFrameHeader::kOpCodeText, AsVector("TIME"))); 1096 EXPECT_CALL(*event_interface_, 1097 OnDataFrame(false, 1098 WebSocketFrameHeader::kOpCodeContinuation, 1099 AsVector(" FOR "))); 1100 EXPECT_CALL( 1101 *event_interface_, 1102 OnDataFrame( 1103 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("TEA"))); 1104 } 1105 1106 CreateChannelAndConnectSuccessfully(); 1107 base::MessageLoop::current()->RunUntilIdle(); 1108 } 1109 1110 // If a control message is fragmented, it must be re-assembled before being 1111 // delivered. A control message can only be fragmented at the network level; it 1112 // is not permitted to be split into multiple frames. 1113 TEST_F(WebSocketChannelEventInterfaceTest, FragmentedControlMessage) { 1114 scoped_ptr<ReadableFakeWebSocketStream> stream( 1115 new ReadableFakeWebSocketStream); 1116 static const InitFrameChunk chunks1[] = { 1117 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7}, 1118 NOT_FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "")}}; 1119 static const InitFrameChunk chunks2[] = { 1120 {{NO_HEADER}, NOT_FINAL_CHUNK, "Clo"}}; 1121 static const InitFrameChunk chunks3[] = {{{NO_HEADER}, FINAL_CHUNK, "se"}}; 1122 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1); 1123 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2); 1124 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3); 1125 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC, 1126 ERR_CONNECTION_CLOSED); 1127 set_stream(stream.Pass()); 1128 { 1129 InSequence s; 1130 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1131 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1132 EXPECT_CALL(*event_interface_, OnClosingHandshake()); 1133 EXPECT_CALL(*event_interface_, 1134 OnDropChannel(kWebSocketNormalClosure, "Close")); 1135 } 1136 1137 CreateChannelAndConnectSuccessfully(); 1138 base::MessageLoop::current()->RunUntilIdle(); 1139 } 1140 1141 // The payload of a control frame is not permitted to exceed 125 bytes. RFC6455 1142 // 5.5 "All control frames MUST have a payload length of 125 bytes or less" 1143 TEST_F(WebSocketChannelEventInterfaceTest, OversizeControlMessageIsRejected) { 1144 scoped_ptr<ReadableFakeWebSocketStream> stream( 1145 new ReadableFakeWebSocketStream); 1146 static const size_t kPayloadLen = 126; 1147 char payload[kPayloadLen + 1]; // allow space for trailing NUL 1148 std::fill(payload, payload + kPayloadLen, 'A'); 1149 payload[kPayloadLen] = '\0'; 1150 // Not static because "payload" is constructed at runtime. 1151 const InitFrameChunk chunks[] = { 1152 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 1153 kPayloadLen}, 1154 FINAL_CHUNK, payload}}; 1155 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks); 1156 set_stream(stream.Pass()); 1157 1158 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1159 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1160 EXPECT_CALL(*event_interface_, 1161 OnDropChannel(kWebSocketErrorProtocolError, _)); 1162 1163 CreateChannelAndConnectSuccessfully(); 1164 } 1165 1166 // A control frame is not permitted to be split into multiple frames. RFC6455 1167 // 5.5 "All control frames ... MUST NOT be fragmented." 1168 TEST_F(WebSocketChannelEventInterfaceTest, MultiFrameControlMessageIsRejected) { 1169 scoped_ptr<ReadableFakeWebSocketStream> stream( 1170 new ReadableFakeWebSocketStream); 1171 static const InitFrameChunk chunks[] = { 1172 {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 2}, 1173 FINAL_CHUNK, "Pi"}, 1174 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, 2}, 1175 FINAL_CHUNK, "ng"}}; 1176 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks); 1177 set_stream(stream.Pass()); 1178 { 1179 InSequence s; 1180 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1181 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1182 EXPECT_CALL(*event_interface_, 1183 OnDropChannel(kWebSocketErrorProtocolError, _)); 1184 } 1185 1186 CreateChannelAndConnectSuccessfully(); 1187 base::MessageLoop::current()->RunUntilIdle(); 1188 } 1189 1190 // Connection closed by the remote host without a closing handshake. 1191 TEST_F(WebSocketChannelEventInterfaceTest, AsyncAbnormalClosure) { 1192 scoped_ptr<ReadableFakeWebSocketStream> stream( 1193 new ReadableFakeWebSocketStream); 1194 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC, 1195 ERR_CONNECTION_CLOSED); 1196 set_stream(stream.Pass()); 1197 { 1198 InSequence s; 1199 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1200 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1201 EXPECT_CALL(*event_interface_, 1202 OnDropChannel(kWebSocketErrorAbnormalClosure, _)); 1203 } 1204 1205 CreateChannelAndConnectSuccessfully(); 1206 base::MessageLoop::current()->RunUntilIdle(); 1207 } 1208 1209 // A connection reset should produce the same event as an unexpected closure. 1210 TEST_F(WebSocketChannelEventInterfaceTest, ConnectionReset) { 1211 scoped_ptr<ReadableFakeWebSocketStream> stream( 1212 new ReadableFakeWebSocketStream); 1213 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC, 1214 ERR_CONNECTION_RESET); 1215 set_stream(stream.Pass()); 1216 { 1217 InSequence s; 1218 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1219 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1220 EXPECT_CALL(*event_interface_, 1221 OnDropChannel(kWebSocketErrorAbnormalClosure, _)); 1222 } 1223 1224 CreateChannelAndConnectSuccessfully(); 1225 base::MessageLoop::current()->RunUntilIdle(); 1226 } 1227 1228 // Connection closed in the middle of a Close message (server bug, etc.) 1229 TEST_F(WebSocketChannelEventInterfaceTest, ConnectionClosedInMessage) { 1230 scoped_ptr<ReadableFakeWebSocketStream> stream( 1231 new ReadableFakeWebSocketStream); 1232 static const InitFrameChunk chunks[] = { 1233 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7}, 1234 NOT_FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "")}}; 1235 1236 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks); 1237 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC, 1238 ERR_CONNECTION_CLOSED); 1239 set_stream(stream.Pass()); 1240 { 1241 InSequence s; 1242 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1243 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1244 EXPECT_CALL(*event_interface_, 1245 OnDropChannel(kWebSocketErrorAbnormalClosure, _)); 1246 } 1247 1248 CreateChannelAndConnectSuccessfully(); 1249 base::MessageLoop::current()->RunUntilIdle(); 1250 } 1251 1252 // RFC6455 5.1 "A client MUST close a connection if it detects a masked frame." 1253 TEST_F(WebSocketChannelEventInterfaceTest, MaskedFramesAreRejected) { 1254 scoped_ptr<ReadableFakeWebSocketStream> stream( 1255 new ReadableFakeWebSocketStream); 1256 static const InitFrameChunk chunks[] = { 1257 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 5}, FINAL_CHUNK, 1258 "HELLO"}}; 1259 1260 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks); 1261 set_stream(stream.Pass()); 1262 { 1263 InSequence s; 1264 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1265 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1266 EXPECT_CALL(*event_interface_, 1267 OnDropChannel(kWebSocketErrorProtocolError, _)); 1268 } 1269 1270 CreateChannelAndConnectSuccessfully(); 1271 base::MessageLoop::current()->RunUntilIdle(); 1272 } 1273 1274 // RFC6455 5.2 "If an unknown opcode is received, the receiving endpoint MUST 1275 // _Fail the WebSocket Connection_." 1276 TEST_F(WebSocketChannelEventInterfaceTest, UnknownOpCodeIsRejected) { 1277 scoped_ptr<ReadableFakeWebSocketStream> stream( 1278 new ReadableFakeWebSocketStream); 1279 static const InitFrameChunk chunks[] = { 1280 {{FINAL_FRAME, 4, NOT_MASKED, 5}, FINAL_CHUNK, "HELLO"}}; 1281 1282 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks); 1283 set_stream(stream.Pass()); 1284 { 1285 InSequence s; 1286 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1287 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1288 EXPECT_CALL(*event_interface_, 1289 OnDropChannel(kWebSocketErrorProtocolError, _)); 1290 } 1291 1292 CreateChannelAndConnectSuccessfully(); 1293 base::MessageLoop::current()->RunUntilIdle(); 1294 } 1295 1296 // RFC6455 5.4 "Control frames ... MAY be injected in the middle of a 1297 // fragmented message." 1298 TEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) { 1299 scoped_ptr<ReadableFakeWebSocketStream> stream( 1300 new ReadableFakeWebSocketStream); 1301 // We have one message of type Text split into two frames. In the middle is a 1302 // control message of type Pong. 1303 static const InitFrameChunk chunks1[] = { 1304 {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 6}, 1305 FINAL_CHUNK, "SPLIT "}}; 1306 static const InitFrameChunk chunks2[] = { 1307 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, 0}, 1308 FINAL_CHUNK, ""}}; 1309 static const InitFrameChunk chunks3[] = { 1310 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, 7}, 1311 FINAL_CHUNK, "MESSAGE"}}; 1312 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1); 1313 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2); 1314 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3); 1315 set_stream(stream.Pass()); 1316 { 1317 InSequence s; 1318 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1319 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1320 EXPECT_CALL( 1321 *event_interface_, 1322 OnDataFrame( 1323 false, WebSocketFrameHeader::kOpCodeText, AsVector("SPLIT "))); 1324 EXPECT_CALL(*event_interface_, 1325 OnDataFrame(true, 1326 WebSocketFrameHeader::kOpCodeContinuation, 1327 AsVector("MESSAGE"))); 1328 } 1329 1330 CreateChannelAndConnectSuccessfully(); 1331 base::MessageLoop::current()->RunUntilIdle(); 1332 } 1333 1334 // If a chunk has an invalid header, then the connection is closed and 1335 // subsequent chunks must not trigger events. 1336 TEST_F(WebSocketChannelEventInterfaceTest, HeaderlessChunkAfterInvalidChunk) { 1337 scoped_ptr<ReadableFakeWebSocketStream> stream( 1338 new ReadableFakeWebSocketStream); 1339 static const InitFrameChunk chunks[] = { 1340 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 11}, 1341 NOT_FINAL_CHUNK, "HELLO"}, 1342 {{NO_HEADER}, FINAL_CHUNK, " WORLD"}}; 1343 1344 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks); 1345 set_stream(stream.Pass()); 1346 { 1347 InSequence s; 1348 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1349 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1350 EXPECT_CALL(*event_interface_, 1351 OnDropChannel(kWebSocketErrorProtocolError, _)); 1352 } 1353 1354 CreateChannelAndConnectSuccessfully(); 1355 base::MessageLoop::current()->RunUntilIdle(); 1356 } 1357 1358 // If the renderer sends lots of small writes, we don't want to update the quota 1359 // for each one. 1360 TEST_F(WebSocketChannelEventInterfaceTest, SmallWriteDoesntUpdateQuota) { 1361 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream)); 1362 { 1363 InSequence s; 1364 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1365 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1366 } 1367 1368 CreateChannelAndConnectSuccessfully(); 1369 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("B")); 1370 } 1371 1372 // If we send enough to go below send_quota_low_water_mask_ we should get our 1373 // quota refreshed. 1374 TEST_F(WebSocketChannelEventInterfaceTest, LargeWriteUpdatesQuota) { 1375 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream)); 1376 // We use this checkpoint object to verify that the quota update comes after 1377 // the write. 1378 MockFunction<void(int)> checkpoint; 1379 { 1380 InSequence s; 1381 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1382 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1383 EXPECT_CALL(checkpoint, Call(1)); 1384 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1385 EXPECT_CALL(checkpoint, Call(2)); 1386 } 1387 1388 CreateChannelAndConnectSuccessfully(); 1389 checkpoint.Call(1); 1390 channel_->SendFrame(true, 1391 WebSocketFrameHeader::kOpCodeText, 1392 std::vector<char>(kDefaultInitialQuota, 'B')); 1393 checkpoint.Call(2); 1394 } 1395 1396 // Verify that our quota actually is refreshed when we are told it is. 1397 TEST_F(WebSocketChannelEventInterfaceTest, QuotaReallyIsRefreshed) { 1398 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream)); 1399 MockFunction<void(int)> checkpoint; 1400 { 1401 InSequence s; 1402 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1403 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1404 EXPECT_CALL(checkpoint, Call(1)); 1405 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1406 EXPECT_CALL(checkpoint, Call(2)); 1407 // If quota was not really refreshed, we would get an OnDropChannel() 1408 // message. 1409 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1410 EXPECT_CALL(checkpoint, Call(3)); 1411 } 1412 1413 CreateChannelAndConnectSuccessfully(); 1414 checkpoint.Call(1); 1415 channel_->SendFrame(true, 1416 WebSocketFrameHeader::kOpCodeText, 1417 std::vector<char>(kDefaultQuotaRefreshTrigger, 'D')); 1418 checkpoint.Call(2); 1419 // We should have received more quota at this point. 1420 channel_->SendFrame(true, 1421 WebSocketFrameHeader::kOpCodeText, 1422 std::vector<char>(kDefaultQuotaRefreshTrigger, 'E')); 1423 checkpoint.Call(3); 1424 } 1425 1426 // If we send more than the available quota then the connection will be closed 1427 // with an error. 1428 TEST_F(WebSocketChannelEventInterfaceTest, WriteOverQuotaIsRejected) { 1429 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream)); 1430 { 1431 InSequence s; 1432 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1433 EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota)); 1434 EXPECT_CALL(*event_interface_, 1435 OnDropChannel(kWebSocketMuxErrorSendQuotaViolation, _)); 1436 } 1437 1438 CreateChannelAndConnectSuccessfully(); 1439 channel_->SendFrame(true, 1440 WebSocketFrameHeader::kOpCodeText, 1441 std::vector<char>(kDefaultInitialQuota + 1, 'C')); 1442 } 1443 1444 // If a write fails, the channel is dropped. 1445 TEST_F(WebSocketChannelEventInterfaceTest, FailedWrite) { 1446 set_stream(make_scoped_ptr(new UnWriteableFakeWebSocketStream)); 1447 MockFunction<void(int)> checkpoint; 1448 { 1449 InSequence s; 1450 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1451 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1452 EXPECT_CALL(checkpoint, Call(1)); 1453 EXPECT_CALL(*event_interface_, 1454 OnDropChannel(kWebSocketErrorAbnormalClosure, _)); 1455 EXPECT_CALL(checkpoint, Call(2)); 1456 } 1457 1458 CreateChannelAndConnectSuccessfully(); 1459 checkpoint.Call(1); 1460 1461 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("H")); 1462 checkpoint.Call(2); 1463 } 1464 1465 // OnDropChannel() is called exactly once when StartClosingHandshake() is used. 1466 TEST_F(WebSocketChannelEventInterfaceTest, SendCloseDropsChannel) { 1467 set_stream(make_scoped_ptr(new EchoeyFakeWebSocketStream)); 1468 { 1469 InSequence s; 1470 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1471 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1472 EXPECT_CALL(*event_interface_, 1473 OnDropChannel(kWebSocketNormalClosure, "Fred")); 1474 } 1475 1476 CreateChannelAndConnectSuccessfully(); 1477 1478 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Fred"); 1479 base::MessageLoop::current()->RunUntilIdle(); 1480 } 1481 1482 // OnDropChannel() is only called once when a write() on the socket triggers a 1483 // connection reset. 1484 TEST_F(WebSocketChannelEventInterfaceTest, OnDropChannelCalledOnce) { 1485 set_stream(make_scoped_ptr(new ResetOnWriteFakeWebSocketStream)); 1486 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1487 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1488 1489 EXPECT_CALL(*event_interface_, 1490 OnDropChannel(kWebSocketErrorAbnormalClosure, "Abnormal Closure")) 1491 .Times(1); 1492 1493 CreateChannelAndConnectSuccessfully(); 1494 1495 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("yt?")); 1496 base::MessageLoop::current()->RunUntilIdle(); 1497 } 1498 1499 // When the remote server sends a Close frame with an empty payload, 1500 // WebSocketChannel should report code 1005, kWebSocketErrorNoStatusReceived. 1501 TEST_F(WebSocketChannelEventInterfaceTest, CloseWithNoPayloadGivesStatus1005) { 1502 scoped_ptr<ReadableFakeWebSocketStream> stream( 1503 new ReadableFakeWebSocketStream); 1504 static const InitFrameChunk chunks[] = { 1505 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 0}, 1506 FINAL_CHUNK, ""}}; 1507 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks); 1508 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, 1509 ERR_CONNECTION_CLOSED); 1510 set_stream(stream.Pass()); 1511 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1512 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1513 EXPECT_CALL(*event_interface_, OnClosingHandshake()); 1514 EXPECT_CALL(*event_interface_, 1515 OnDropChannel(kWebSocketErrorNoStatusReceived, _)); 1516 1517 CreateChannelAndConnectSuccessfully(); 1518 } 1519 1520 // RFC6455 5.1 "a client MUST mask all frames that it sends to the server". 1521 // WebSocketChannel actually only sets the mask bit in the header, it doesn't 1522 // perform masking itself (not all transports actually use masking). 1523 TEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) { 1524 static const InitFrameChunk expected[] = { 1525 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 13}, 1526 FINAL_CHUNK, "NEEDS MASKING"}}; 1527 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1528 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 1529 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _)) 1530 .WillOnce(Return(OK)); 1531 1532 CreateChannelAndConnectSuccessfully(); 1533 channel_->SendFrame( 1534 true, WebSocketFrameHeader::kOpCodeText, AsVector("NEEDS MASKING")); 1535 } 1536 1537 // RFC6455 5.5.1 "The application MUST NOT send any more data frames after 1538 // sending a Close frame." 1539 TEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) { 1540 static const InitFrameChunk expected[] = { 1541 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 9}, 1542 FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Success")}}; 1543 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1544 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 1545 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _)) 1546 .WillOnce(Return(OK)); 1547 1548 CreateChannelAndConnectSuccessfully(); 1549 channel_->StartClosingHandshake(1000, "Success"); 1550 channel_->SendFrame( 1551 true, WebSocketFrameHeader::kOpCodeText, AsVector("SHOULD BE IGNORED")); 1552 } 1553 1554 // RFC6455 5.5.1 "If an endpoint receives a Close frame and did not previously 1555 // send a Close frame, the endpoint MUST send a Close frame in response." 1556 TEST_F(WebSocketChannelStreamTest, CloseIsEchoedBack) { 1557 static const InitFrameChunk chunks[] = { 1558 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7}, 1559 FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}}; 1560 static const InitFrameChunk expected[] = { 1561 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 7}, 1562 FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}}; 1563 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1564 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 1565 .WillOnce(ReturnChunks(&chunks)) 1566 .WillRepeatedly(Return(ERR_IO_PENDING)); 1567 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _)) 1568 .WillOnce(Return(OK)); 1569 1570 CreateChannelAndConnectSuccessfully(); 1571 } 1572 1573 // The converse of the above case; after sending a Close frame, we should not 1574 // send another one. 1575 TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) { 1576 static const InitFrameChunk expected[] = { 1577 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 7}, 1578 FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}}; 1579 static const InitFrameChunk chunks[] = { 1580 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7}, 1581 FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}}; 1582 1583 // We store the parameters that were passed to ReadFrames() so that we can 1584 // call them explicitly later. 1585 CompletionCallback read_callback; 1586 ScopedVector<WebSocketFrameChunk>* frame_chunks = NULL; 1587 1588 // Use a checkpoint to make the ordering of events clearer. 1589 MockFunction<void(int)> checkpoint; 1590 { 1591 InSequence s; 1592 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1593 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 1594 .WillOnce(DoAll(SaveArg<0>(&frame_chunks), 1595 SaveArg<1>(&read_callback), 1596 Return(ERR_IO_PENDING))); 1597 EXPECT_CALL(checkpoint, Call(1)); 1598 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _)) 1599 .WillOnce(Return(OK)); 1600 EXPECT_CALL(checkpoint, Call(2)); 1601 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 1602 .WillOnce(Return(ERR_IO_PENDING)); 1603 EXPECT_CALL(checkpoint, Call(3)); 1604 // WriteFrames() must not be called again. GoogleMock will ensure that the 1605 // test fails if it is. 1606 } 1607 1608 CreateChannelAndConnectSuccessfully(); 1609 checkpoint.Call(1); 1610 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Close"); 1611 checkpoint.Call(2); 1612 1613 *frame_chunks = CreateFrameChunkVector(chunks); 1614 read_callback.Run(OK); 1615 checkpoint.Call(3); 1616 } 1617 1618 // We generate code 1005, kWebSocketErrorNoStatusReceived, when there is no 1619 // status in the Close message from the other side. Code 1005 is not allowed to 1620 // appear on the wire, so we should not echo it back. See test 1621 // CloseWithNoPayloadGivesStatus1005, above, for confirmation that code 1005 is 1622 // correctly generated internally. 1623 TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoed) { 1624 static const InitFrameChunk chunks[] = { 1625 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 0}, 1626 FINAL_CHUNK, ""}}; 1627 static const InitFrameChunk expected[] = { 1628 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 0}, 1629 FINAL_CHUNK, ""}}; 1630 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1631 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 1632 .WillOnce(ReturnChunks(&chunks)) 1633 .WillRepeatedly(Return(ERR_IO_PENDING)); 1634 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _)) 1635 .WillOnce(Return(OK)); 1636 1637 CreateChannelAndConnectSuccessfully(); 1638 } 1639 1640 // RFC6455 5.5.2 "Upon receipt of a Ping frame, an endpoint MUST send a Pong 1641 // frame in response" 1642 // 5.5.3 "A Pong frame sent in response to a Ping frame must have identical 1643 // "Application data" as found in the message body of the Ping frame being 1644 // replied to." 1645 TEST_F(WebSocketChannelStreamTest, PingRepliedWithPong) { 1646 static const InitFrameChunk chunks[] = { 1647 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 16}, 1648 FINAL_CHUNK, "Application data"}}; 1649 static const InitFrameChunk expected[] = { 1650 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, 16}, 1651 FINAL_CHUNK, "Application data"}}; 1652 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1653 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 1654 .WillOnce(ReturnChunks(&chunks)) 1655 .WillRepeatedly(Return(ERR_IO_PENDING)); 1656 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _)) 1657 .WillOnce(Return(OK)); 1658 1659 CreateChannelAndConnectSuccessfully(); 1660 } 1661 1662 TEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) { 1663 static const InitFrameChunk chunks[] = { 1664 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 16}, 1665 FINAL_CHUNK, "Application data"}}; 1666 static const InitFrameChunk expected1[] = { 1667 {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 6}, 1668 FINAL_CHUNK, "Hello "}}; 1669 static const InitFrameChunk expected2[] = { 1670 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, 16}, 1671 FINAL_CHUNK, "Application data"}}; 1672 static const InitFrameChunk expected3[] = { 1673 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, MASKED, 5}, 1674 FINAL_CHUNK, "World"}}; 1675 ScopedVector<WebSocketFrameChunk>* read_chunks; 1676 CompletionCallback read_callback; 1677 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1678 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 1679 .WillOnce(DoAll(SaveArg<0>(&read_chunks), 1680 SaveArg<1>(&read_callback), 1681 Return(ERR_IO_PENDING))) 1682 .WillRepeatedly(Return(ERR_IO_PENDING)); 1683 { 1684 InSequence s; 1685 1686 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected1), _)) 1687 .WillOnce(Return(OK)); 1688 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected2), _)) 1689 .WillOnce(Return(OK)); 1690 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected3), _)) 1691 .WillOnce(Return(OK)); 1692 } 1693 1694 CreateChannelAndConnectSuccessfully(); 1695 channel_->SendFrame( 1696 false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello ")); 1697 *read_chunks = CreateFrameChunkVector(chunks); 1698 read_callback.Run(OK); 1699 channel_->SendFrame( 1700 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("World")); 1701 } 1702 1703 // WriteFrames() may not be called until the previous write has completed. 1704 // WebSocketChannel must buffer writes that happen in the meantime. 1705 TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) { 1706 static const InitFrameChunk expected1[] = { 1707 {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 6}, 1708 FINAL_CHUNK, "Hello "}}; 1709 static const InitFrameChunk expected2[] = { 1710 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 5}, FINAL_CHUNK, 1711 "World"}}; 1712 CompletionCallback write_callback; 1713 MockFunction<void(int)> checkpoint; 1714 1715 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1716 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 1717 { 1718 InSequence s; 1719 EXPECT_CALL(checkpoint, Call(1)); 1720 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected1), _)) 1721 .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING))); 1722 EXPECT_CALL(checkpoint, Call(2)); 1723 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected2), _)) 1724 .WillOnce(Return(ERR_IO_PENDING)); 1725 EXPECT_CALL(checkpoint, Call(3)); 1726 } 1727 1728 CreateChannelAndConnectSuccessfully(); 1729 checkpoint.Call(1); 1730 channel_->SendFrame( 1731 false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello ")); 1732 channel_->SendFrame( 1733 true, WebSocketFrameHeader::kOpCodeText, AsVector("World")); 1734 checkpoint.Call(2); 1735 write_callback.Run(OK); 1736 checkpoint.Call(3); 1737 } 1738 1739 // WebSocketChannel must buffer frames while it is waiting for a write to 1740 // complete, and then send them in a single batch. The batching behaviour is 1741 // important to get good throughput in the "many small messages" case. 1742 TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) { 1743 static const char input_letters[] = "Hello"; 1744 static const InitFrameChunk expected1[] = { 1745 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK, 1746 "H"}}; 1747 static const InitFrameChunk expected2[] = { 1748 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK, 1749 "e"}, 1750 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK, 1751 "l"}, 1752 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK, 1753 "l"}, 1754 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK, 1755 "o"}}; 1756 CompletionCallback write_callback; 1757 1758 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1759 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 1760 { 1761 InSequence s; 1762 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected1), _)) 1763 .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING))); 1764 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected2), _)) 1765 .WillOnce(Return(ERR_IO_PENDING)); 1766 } 1767 1768 CreateChannelAndConnectSuccessfully(); 1769 for (size_t i = 0; i < strlen(input_letters); ++i) { 1770 channel_->SendFrame(true, 1771 WebSocketFrameHeader::kOpCodeText, 1772 std::vector<char>(1, input_letters[i])); 1773 } 1774 write_callback.Run(OK); 1775 } 1776 1777 // When the renderer sends more on a channel than it has quota for, then we send 1778 // a kWebSocketMuxErrorSendQuotaViolation status code (from the draft websocket 1779 // mux specification) back to the renderer. This should not be sent to the 1780 // remote server, which may not even implement the mux specification, and could 1781 // even be using a different extension which uses that code to mean something 1782 // else. 1783 TEST_F(WebSocketChannelStreamTest, MuxErrorIsNotSentToStream) { 1784 static const InitFrameChunk expected[] = { 1785 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 16}, 1786 FINAL_CHUNK, CLOSE_DATA(GOING_AWAY, "Internal Error")}}; 1787 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1788 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 1789 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _)) 1790 .WillOnce(Return(OK)); 1791 EXPECT_CALL(*mock_stream_, Close()); 1792 1793 CreateChannelAndConnectSuccessfully(); 1794 channel_->SendFrame(true, 1795 WebSocketFrameHeader::kOpCodeText, 1796 std::vector<char>(kDefaultInitialQuota + 1, 'C')); 1797 } 1798 1799 // For convenience, most of these tests use Text frames. However, the WebSocket 1800 // protocol also has Binary frames and those need to be 8-bit clean. For the 1801 // sake of completeness, this test verifies that they are. 1802 TEST_F(WebSocketChannelStreamTest, WrittenBinaryFramesAre8BitClean) { 1803 ScopedVector<WebSocketFrameChunk>* frame_chunks = NULL; 1804 1805 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1806 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 1807 EXPECT_CALL(*mock_stream_, WriteFrames(_, _)) 1808 .WillOnce(DoAll(SaveArg<0>(&frame_chunks), Return(ERR_IO_PENDING))); 1809 1810 CreateChannelAndConnectSuccessfully(); 1811 channel_->SendFrame( 1812 true, 1813 WebSocketFrameHeader::kOpCodeBinary, 1814 std::vector<char>(kBinaryBlob, kBinaryBlob + kBinaryBlobSize)); 1815 ASSERT_TRUE(frame_chunks != NULL); 1816 ASSERT_EQ(1U, frame_chunks->size()); 1817 const WebSocketFrameChunk* out_chunk = (*frame_chunks)[0]; 1818 ASSERT_TRUE(out_chunk->header); 1819 EXPECT_EQ(kBinaryBlobSize, out_chunk->header->payload_length); 1820 ASSERT_TRUE(out_chunk->data); 1821 EXPECT_EQ(kBinaryBlobSize, static_cast<size_t>(out_chunk->data->size())); 1822 EXPECT_EQ(0, memcmp(kBinaryBlob, out_chunk->data->data(), kBinaryBlobSize)); 1823 } 1824 1825 // Test the read path for 8-bit cleanliness as well. 1826 TEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) { 1827 scoped_ptr<WebSocketFrameHeader> frame_header( 1828 new WebSocketFrameHeader(WebSocketFrameHeader::kOpCodeBinary)); 1829 frame_header->final = true; 1830 frame_header->payload_length = kBinaryBlobSize; 1831 scoped_ptr<WebSocketFrameChunk> frame_chunk(new WebSocketFrameChunk); 1832 frame_chunk->header = frame_header.Pass(); 1833 frame_chunk->final_chunk = true; 1834 frame_chunk->data = new IOBufferWithSize(kBinaryBlobSize); 1835 memcpy(frame_chunk->data->data(), kBinaryBlob, kBinaryBlobSize); 1836 ScopedVector<WebSocketFrameChunk> chunks; 1837 chunks.push_back(frame_chunk.release()); 1838 scoped_ptr<ReadableFakeWebSocketStream> stream( 1839 new ReadableFakeWebSocketStream); 1840 stream->PrepareRawReadFrames( 1841 ReadableFakeWebSocketStream::SYNC, OK, chunks.Pass()); 1842 set_stream(stream.Pass()); 1843 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _)); 1844 EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1845 EXPECT_CALL(*event_interface_, 1846 OnDataFrame(true, 1847 WebSocketFrameHeader::kOpCodeBinary, 1848 std::vector<char>(kBinaryBlob, 1849 kBinaryBlob + kBinaryBlobSize))); 1850 1851 CreateChannelAndConnectSuccessfully(); 1852 } 1853 1854 // If we receive another frame after Close, it is not valid. It is not 1855 // completely clear what behaviour is required from the standard in this case, 1856 // but the current implementation fails the connection. Since a Close has 1857 // already been sent, this just means closing the connection. 1858 TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) { 1859 static const InitFrameChunk chunks[] = { 1860 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 4}, 1861 FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "OK")}, 1862 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 9}, 1863 FINAL_CHUNK, "Ping body"}}; 1864 static const InitFrameChunk expected[] = { 1865 {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 4}, 1866 FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "OK")}}; 1867 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 1868 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 1869 .WillOnce(ReturnChunks(&chunks)) 1870 .WillRepeatedly(Return(ERR_IO_PENDING)); 1871 { 1872 // We only need to verify the relative order of WriteFrames() and 1873 // Close(). The current implementation calls WriteFrames() for the Close 1874 // frame before calling ReadFrames() again, but that is an implementation 1875 // detail and better not to consider required behaviour. 1876 InSequence s; 1877 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _)) 1878 .WillOnce(Return(OK)); 1879 EXPECT_CALL(*mock_stream_, Close()).Times(1); 1880 } 1881 1882 CreateChannelAndConnectSuccessfully(); 1883 } 1884 1885 } // namespace 1886 } // namespace net 1887