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 <limits.h>
8 #include <string.h>
9
10 #include <iostream>
11 #include <string>
12 #include <vector>
13
14 #include "base/bind.h"
15 #include "base/bind_helpers.h"
16 #include "base/callback.h"
17 #include "base/location.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/scoped_vector.h"
20 #include "base/memory/weak_ptr.h"
21 #include "base/message_loop/message_loop.h"
22 #include "base/strings/string_piece.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/test_completion_callback.h"
25 #include "net/http/http_response_headers.h"
26 #include "net/url_request/url_request_context.h"
27 #include "net/websockets/websocket_errors.h"
28 #include "net/websockets/websocket_event_interface.h"
29 #include "net/websockets/websocket_handshake_request_info.h"
30 #include "net/websockets/websocket_handshake_response_info.h"
31 #include "net/websockets/websocket_mux.h"
32 #include "testing/gmock/include/gmock/gmock.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34 #include "url/gurl.h"
35 #include "url/origin.h"
36
37 // Hacky macros to construct the body of a Close message from a code and a
38 // string, while ensuring the result is a compile-time constant string.
39 // Use like CLOSE_DATA(NORMAL_CLOSURE, "Explanation String")
40 #define CLOSE_DATA(code, string) WEBSOCKET_CLOSE_CODE_AS_STRING_##code string
41 #define WEBSOCKET_CLOSE_CODE_AS_STRING_NORMAL_CLOSURE "\x03\xe8"
42 #define WEBSOCKET_CLOSE_CODE_AS_STRING_GOING_AWAY "\x03\xe9"
43 #define WEBSOCKET_CLOSE_CODE_AS_STRING_PROTOCOL_ERROR "\x03\xea"
44 #define WEBSOCKET_CLOSE_CODE_AS_STRING_ABNORMAL_CLOSURE "\x03\xee"
45 #define WEBSOCKET_CLOSE_CODE_AS_STRING_SERVER_ERROR "\x03\xf3"
46
47 namespace net {
48
49 // Printing helpers to allow GoogleMock to print frames. These are explicitly
50 // designed to look like the static initialisation format we use in these
51 // tests. They have to live in the net namespace in order to be found by
52 // GoogleMock; a nested anonymous namespace will not work.
53
operator <<(std::ostream & os,const WebSocketFrameHeader & header)54 std::ostream& operator<<(std::ostream& os, const WebSocketFrameHeader& header) {
55 return os << (header.final ? "FINAL_FRAME" : "NOT_FINAL_FRAME") << ", "
56 << header.opcode << ", "
57 << (header.masked ? "MASKED" : "NOT_MASKED");
58 }
59
operator <<(std::ostream & os,const WebSocketFrame & frame)60 std::ostream& operator<<(std::ostream& os, const WebSocketFrame& frame) {
61 os << "{" << frame.header << ", ";
62 if (frame.data) {
63 return os << "\"" << base::StringPiece(frame.data->data(),
64 frame.header.payload_length)
65 << "\"}";
66 }
67 return os << "NULL}";
68 }
69
operator <<(std::ostream & os,const ScopedVector<WebSocketFrame> & vector)70 std::ostream& operator<<(std::ostream& os,
71 const ScopedVector<WebSocketFrame>& vector) {
72 os << "{";
73 bool first = true;
74 for (ScopedVector<WebSocketFrame>::const_iterator it = vector.begin();
75 it != vector.end();
76 ++it) {
77 if (!first) {
78 os << ",\n";
79 } else {
80 first = false;
81 }
82 os << **it;
83 }
84 return os << "}";
85 }
86
operator <<(std::ostream & os,const ScopedVector<WebSocketFrame> * vector)87 std::ostream& operator<<(std::ostream& os,
88 const ScopedVector<WebSocketFrame>* vector) {
89 return os << '&' << *vector;
90 }
91
92 namespace {
93
94 using ::base::TimeDelta;
95
96 using ::testing::AnyNumber;
97 using ::testing::DefaultValue;
98 using ::testing::InSequence;
99 using ::testing::MockFunction;
100 using ::testing::NotNull;
101 using ::testing::Return;
102 using ::testing::SaveArg;
103 using ::testing::StrictMock;
104 using ::testing::_;
105
106 // A selection of characters that have traditionally been mangled in some
107 // environment or other, for testing 8-bit cleanliness.
108 const char kBinaryBlob[] = {'\n', '\r', // BACKWARDS CRNL
109 '\0', // nul
110 '\x7F', // DEL
111 '\x80', '\xFF', // NOT VALID UTF-8
112 '\x1A', // Control-Z, EOF on DOS
113 '\x03', // Control-C
114 '\x04', // EOT, special for Unix terms
115 '\x1B', // ESC, often special
116 '\b', // backspace
117 '\'', // single-quote, special in PHP
118 };
119 const size_t kBinaryBlobSize = arraysize(kBinaryBlob);
120
121 // The amount of quota a new connection gets by default.
122 // TODO(ricea): If kDefaultSendQuotaHighWaterMark changes, then this value will
123 // need to be updated.
124 const size_t kDefaultInitialQuota = 1 << 17;
125 // The amount of bytes we need to send after the initial connection to trigger a
126 // quota refresh. TODO(ricea): Change this if kDefaultSendQuotaHighWaterMark or
127 // kDefaultSendQuotaLowWaterMark change.
128 const size_t kDefaultQuotaRefreshTrigger = (1 << 16) + 1;
129
130 // TestTimeouts::tiny_timeout() is 100ms! I could run halfway around the world
131 // in that time! I would like my tests to run a bit quicker.
132 const int kVeryTinyTimeoutMillis = 1;
133
134 // Enough quota to pass any test.
135 const int64 kPlentyOfQuota = INT_MAX;
136
137 typedef WebSocketEventInterface::ChannelState ChannelState;
138 const ChannelState CHANNEL_ALIVE = WebSocketEventInterface::CHANNEL_ALIVE;
139 const ChannelState CHANNEL_DELETED = WebSocketEventInterface::CHANNEL_DELETED;
140
141 // This typedef mainly exists to avoid having to repeat the "NOLINT" incantation
142 // all over the place.
143 typedef StrictMock< MockFunction<void(int)> > Checkpoint; // NOLINT
144
145 // This mock is for testing expectations about how the EventInterface is used.
146 class MockWebSocketEventInterface : public WebSocketEventInterface {
147 public:
MockWebSocketEventInterface()148 MockWebSocketEventInterface() {}
149
150 MOCK_METHOD3(OnAddChannelResponse,
151 ChannelState(bool,
152 const std::string&,
153 const std::string&)); // NOLINT
154 MOCK_METHOD3(OnDataFrame,
155 ChannelState(bool,
156 WebSocketMessageType,
157 const std::vector<char>&)); // NOLINT
158 MOCK_METHOD1(OnFlowControl, ChannelState(int64)); // NOLINT
159 MOCK_METHOD0(OnClosingHandshake, ChannelState(void)); // NOLINT
160 MOCK_METHOD1(OnFailChannel, ChannelState(const std::string&)); // NOLINT
161 MOCK_METHOD3(OnDropChannel,
162 ChannelState(bool, uint16, const std::string&)); // NOLINT
163
164 // We can't use GMock with scoped_ptr.
OnStartOpeningHandshake(scoped_ptr<WebSocketHandshakeRequestInfo>)165 ChannelState OnStartOpeningHandshake(
166 scoped_ptr<WebSocketHandshakeRequestInfo>) OVERRIDE {
167 OnStartOpeningHandshakeCalled();
168 return CHANNEL_ALIVE;
169 }
OnFinishOpeningHandshake(scoped_ptr<WebSocketHandshakeResponseInfo>)170 ChannelState OnFinishOpeningHandshake(
171 scoped_ptr<WebSocketHandshakeResponseInfo>) OVERRIDE {
172 OnFinishOpeningHandshakeCalled();
173 return CHANNEL_ALIVE;
174 }
OnSSLCertificateError(scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks,const GURL & url,const SSLInfo & ssl_info,bool fatal)175 virtual ChannelState OnSSLCertificateError(
176 scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks,
177 const GURL& url,
178 const SSLInfo& ssl_info,
179 bool fatal) OVERRIDE {
180 OnSSLCertificateErrorCalled(
181 ssl_error_callbacks.get(), url, ssl_info, fatal);
182 return CHANNEL_ALIVE;
183 }
184
185 MOCK_METHOD0(OnStartOpeningHandshakeCalled, void()); // NOLINT
186 MOCK_METHOD0(OnFinishOpeningHandshakeCalled, void()); // NOLINT
187 MOCK_METHOD4(
188 OnSSLCertificateErrorCalled,
189 void(SSLErrorCallbacks*, const GURL&, const SSLInfo&, bool)); // NOLINT
190 };
191
192 // This fake EventInterface is for tests which need a WebSocketEventInterface
193 // implementation but are not verifying how it is used.
194 class FakeWebSocketEventInterface : public WebSocketEventInterface {
OnAddChannelResponse(bool fail,const std::string & selected_protocol,const std::string & extensions)195 virtual ChannelState OnAddChannelResponse(
196 bool fail,
197 const std::string& selected_protocol,
198 const std::string& extensions) OVERRIDE {
199 return fail ? CHANNEL_DELETED : CHANNEL_ALIVE;
200 }
OnDataFrame(bool fin,WebSocketMessageType type,const std::vector<char> & data)201 virtual ChannelState OnDataFrame(bool fin,
202 WebSocketMessageType type,
203 const std::vector<char>& data) OVERRIDE {
204 return CHANNEL_ALIVE;
205 }
OnFlowControl(int64 quota)206 virtual ChannelState OnFlowControl(int64 quota) OVERRIDE {
207 return CHANNEL_ALIVE;
208 }
OnClosingHandshake()209 virtual ChannelState OnClosingHandshake() OVERRIDE { return CHANNEL_ALIVE; }
OnFailChannel(const std::string & message)210 virtual ChannelState OnFailChannel(const std::string& message) OVERRIDE {
211 return CHANNEL_DELETED;
212 }
OnDropChannel(bool was_clean,uint16 code,const std::string & reason)213 virtual ChannelState OnDropChannel(bool was_clean,
214 uint16 code,
215 const std::string& reason) OVERRIDE {
216 return CHANNEL_DELETED;
217 }
OnStartOpeningHandshake(scoped_ptr<WebSocketHandshakeRequestInfo> request)218 virtual ChannelState OnStartOpeningHandshake(
219 scoped_ptr<WebSocketHandshakeRequestInfo> request) OVERRIDE {
220 return CHANNEL_ALIVE;
221 }
OnFinishOpeningHandshake(scoped_ptr<WebSocketHandshakeResponseInfo> response)222 virtual ChannelState OnFinishOpeningHandshake(
223 scoped_ptr<WebSocketHandshakeResponseInfo> response) OVERRIDE {
224 return CHANNEL_ALIVE;
225 }
OnSSLCertificateError(scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks,const GURL & url,const SSLInfo & ssl_info,bool fatal)226 virtual ChannelState OnSSLCertificateError(
227 scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks,
228 const GURL& url,
229 const SSLInfo& ssl_info,
230 bool fatal) OVERRIDE {
231 return CHANNEL_ALIVE;
232 }
233 };
234
235 // This fake WebSocketStream is for tests that require a WebSocketStream but are
236 // not testing the way it is used. It has minimal functionality to return
237 // the |protocol| and |extensions| that it was constructed with.
238 class FakeWebSocketStream : public WebSocketStream {
239 public:
240 // Constructs with empty protocol and extensions.
FakeWebSocketStream()241 FakeWebSocketStream() {}
242
243 // Constructs with specified protocol and extensions.
FakeWebSocketStream(const std::string & protocol,const std::string & extensions)244 FakeWebSocketStream(const std::string& protocol,
245 const std::string& extensions)
246 : protocol_(protocol), extensions_(extensions) {}
247
ReadFrames(ScopedVector<WebSocketFrame> * frames,const CompletionCallback & callback)248 virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
249 const CompletionCallback& callback) OVERRIDE {
250 return ERR_IO_PENDING;
251 }
252
WriteFrames(ScopedVector<WebSocketFrame> * frames,const CompletionCallback & callback)253 virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
254 const CompletionCallback& callback) OVERRIDE {
255 return ERR_IO_PENDING;
256 }
257
Close()258 virtual void Close() OVERRIDE {}
259
260 // Returns the string passed to the constructor.
GetSubProtocol() const261 virtual std::string GetSubProtocol() const OVERRIDE { return protocol_; }
262
263 // Returns the string passed to the constructor.
GetExtensions() const264 virtual std::string GetExtensions() const OVERRIDE { return extensions_; }
265
266 private:
267 // The string to return from GetSubProtocol().
268 std::string protocol_;
269
270 // The string to return from GetExtensions().
271 std::string extensions_;
272 };
273
274 // To make the static initialisers easier to read, we use enums rather than
275 // bools.
276 enum IsFinal { NOT_FINAL_FRAME, FINAL_FRAME };
277
278 enum IsMasked { NOT_MASKED, MASKED };
279
280 // This is used to initialise a WebSocketFrame but is statically initialisable.
281 struct InitFrame {
282 IsFinal final;
283 // Reserved fields omitted for now. Add them if you need them.
284 WebSocketFrameHeader::OpCode opcode;
285 IsMasked masked;
286
287 // Will be used to create the IOBuffer member. Can be NULL for NULL data. Is a
288 // nul-terminated string for ease-of-use. |header.payload_length| is
289 // initialised from |strlen(data)|. This means it is not 8-bit clean, but this
290 // is not an issue for test data.
291 const char* const data;
292 };
293
294 // For GoogleMock
operator <<(std::ostream & os,const InitFrame & frame)295 std::ostream& operator<<(std::ostream& os, const InitFrame& frame) {
296 os << "{" << (frame.final == FINAL_FRAME ? "FINAL_FRAME" : "NOT_FINAL_FRAME")
297 << ", " << frame.opcode << ", "
298 << (frame.masked == MASKED ? "MASKED" : "NOT_MASKED") << ", ";
299 if (frame.data) {
300 return os << "\"" << frame.data << "\"}";
301 }
302 return os << "NULL}";
303 }
304
305 template <size_t N>
operator <<(std::ostream & os,const InitFrame (& frames)[N])306 std::ostream& operator<<(std::ostream& os, const InitFrame (&frames)[N]) {
307 os << "{";
308 bool first = true;
309 for (size_t i = 0; i < N; ++i) {
310 if (!first) {
311 os << ",\n";
312 } else {
313 first = false;
314 }
315 os << frames[i];
316 }
317 return os << "}";
318 }
319
320 // Convert a const array of InitFrame structs to the format used at
321 // runtime. Templated on the size of the array to save typing.
322 template <size_t N>
CreateFrameVector(const InitFrame (& source_frames)[N])323 ScopedVector<WebSocketFrame> CreateFrameVector(
324 const InitFrame (&source_frames)[N]) {
325 ScopedVector<WebSocketFrame> result_frames;
326 result_frames.reserve(N);
327 for (size_t i = 0; i < N; ++i) {
328 const InitFrame& source_frame = source_frames[i];
329 scoped_ptr<WebSocketFrame> result_frame(
330 new WebSocketFrame(source_frame.opcode));
331 size_t frame_length = source_frame.data ? strlen(source_frame.data) : 0;
332 WebSocketFrameHeader& result_header = result_frame->header;
333 result_header.final = (source_frame.final == FINAL_FRAME);
334 result_header.masked = (source_frame.masked == MASKED);
335 result_header.payload_length = frame_length;
336 if (source_frame.data) {
337 result_frame->data = new IOBuffer(frame_length);
338 memcpy(result_frame->data->data(), source_frame.data, frame_length);
339 }
340 result_frames.push_back(result_frame.release());
341 }
342 return result_frames.Pass();
343 }
344
345 // A GoogleMock action which can be used to respond to call to ReadFrames with
346 // some frames. Use like ReadFrames(_, _).WillOnce(ReturnFrames(&frames));
347 // |frames| is an array of InitFrame. |frames| needs to be passed by pointer
348 // because otherwise it will be treated as a pointer and the array size
349 // information will be lost.
ACTION_P(ReturnFrames,source_frames)350 ACTION_P(ReturnFrames, source_frames) {
351 *arg0 = CreateFrameVector(*source_frames);
352 return OK;
353 }
354
355 // The implementation of a GoogleMock matcher which can be used to compare a
356 // ScopedVector<WebSocketFrame>* against an expectation defined as an array of
357 // InitFrame objects. Although it is possible to compose built-in GoogleMock
358 // matchers to check the contents of a WebSocketFrame, the results are so
359 // unreadable that it is better to use this matcher.
360 template <size_t N>
361 class EqualsFramesMatcher
362 : public ::testing::MatcherInterface<ScopedVector<WebSocketFrame>*> {
363 public:
EqualsFramesMatcher(const InitFrame (* expect_frames)[N])364 EqualsFramesMatcher(const InitFrame (*expect_frames)[N])
365 : expect_frames_(expect_frames) {}
366
MatchAndExplain(ScopedVector<WebSocketFrame> * actual_frames,::testing::MatchResultListener * listener) const367 virtual bool MatchAndExplain(ScopedVector<WebSocketFrame>* actual_frames,
368 ::testing::MatchResultListener* listener) const {
369 if (actual_frames->size() != N) {
370 *listener << "the vector size is " << actual_frames->size();
371 return false;
372 }
373 for (size_t i = 0; i < N; ++i) {
374 const WebSocketFrame& actual_frame = *(*actual_frames)[i];
375 const InitFrame& expected_frame = (*expect_frames_)[i];
376 if (actual_frame.header.final != (expected_frame.final == FINAL_FRAME)) {
377 *listener << "the frame is marked as "
378 << (actual_frame.header.final ? "" : "not ") << "final";
379 return false;
380 }
381 if (actual_frame.header.opcode != expected_frame.opcode) {
382 *listener << "the opcode is " << actual_frame.header.opcode;
383 return false;
384 }
385 if (actual_frame.header.masked != (expected_frame.masked == MASKED)) {
386 *listener << "the frame is "
387 << (actual_frame.header.masked ? "masked" : "not masked");
388 return false;
389 }
390 const size_t expected_length =
391 expected_frame.data ? strlen(expected_frame.data) : 0;
392 if (actual_frame.header.payload_length != expected_length) {
393 *listener << "the payload length is "
394 << actual_frame.header.payload_length;
395 return false;
396 }
397 if (expected_length != 0 &&
398 memcmp(actual_frame.data->data(),
399 expected_frame.data,
400 actual_frame.header.payload_length) != 0) {
401 *listener << "the data content differs";
402 return false;
403 }
404 }
405 return true;
406 }
407
DescribeTo(std::ostream * os) const408 virtual void DescribeTo(std::ostream* os) const {
409 *os << "matches " << *expect_frames_;
410 }
411
DescribeNegationTo(std::ostream * os) const412 virtual void DescribeNegationTo(std::ostream* os) const {
413 *os << "does not match " << *expect_frames_;
414 }
415
416 private:
417 const InitFrame (*expect_frames_)[N];
418 };
419
420 // The definition of EqualsFrames GoogleMock matcher. Unlike the ReturnFrames
421 // action, this can take the array by reference.
422 template <size_t N>
EqualsFrames(const InitFrame (& frames)[N])423 ::testing::Matcher<ScopedVector<WebSocketFrame>*> EqualsFrames(
424 const InitFrame (&frames)[N]) {
425 return ::testing::MakeMatcher(new EqualsFramesMatcher<N>(&frames));
426 }
427
428 // TestClosure works like TestCompletionCallback, but doesn't take an argument.
429 class TestClosure {
430 public:
closure()431 base::Closure closure() { return base::Bind(callback_.callback(), OK); }
432
WaitForResult()433 void WaitForResult() { callback_.WaitForResult(); }
434
435 private:
436 // Delegate to TestCompletionCallback for the implementation.
437 TestCompletionCallback callback_;
438 };
439
440 // A GoogleMock action to run a Closure.
ACTION_P(InvokeClosure,closure)441 ACTION_P(InvokeClosure, closure) { closure.Run(); }
442
443 // A GoogleMock action to run a Closure and return CHANNEL_DELETED.
ACTION_P(InvokeClosureReturnDeleted,closure)444 ACTION_P(InvokeClosureReturnDeleted, closure) {
445 closure.Run();
446 return WebSocketEventInterface::CHANNEL_DELETED;
447 }
448
449 // A FakeWebSocketStream whose ReadFrames() function returns data.
450 class ReadableFakeWebSocketStream : public FakeWebSocketStream {
451 public:
452 enum IsSync { SYNC, ASYNC };
453
454 // After constructing the object, call PrepareReadFrames() once for each
455 // time you wish it to return from the test.
ReadableFakeWebSocketStream()456 ReadableFakeWebSocketStream() : index_(0), read_frames_pending_(false) {}
457
458 // Check that all the prepared responses have been consumed.
~ReadableFakeWebSocketStream()459 virtual ~ReadableFakeWebSocketStream() {
460 CHECK(index_ >= responses_.size());
461 CHECK(!read_frames_pending_);
462 }
463
464 // Prepares a fake response. Fake responses will be returned from ReadFrames()
465 // in the same order they were prepared with PrepareReadFrames() and
466 // PrepareReadFramesError(). If |async| is ASYNC, then ReadFrames() will
467 // return ERR_IO_PENDING and the callback will be scheduled to run on the
468 // message loop. This requires the test case to run the message loop. If
469 // |async| is SYNC, the response will be returned synchronously. |error| is
470 // returned directly from ReadFrames() in the synchronous case, or passed to
471 // the callback in the asynchronous case. |frames| will be converted to a
472 // ScopedVector<WebSocketFrame> and copied to the pointer that was passed to
473 // ReadFrames().
474 template <size_t N>
PrepareReadFrames(IsSync async,int error,const InitFrame (& frames)[N])475 void PrepareReadFrames(IsSync async,
476 int error,
477 const InitFrame (&frames)[N]) {
478 responses_.push_back(new Response(async, error, CreateFrameVector(frames)));
479 }
480
481 // An alternate version of PrepareReadFrames for when we need to construct
482 // the frames manually.
PrepareRawReadFrames(IsSync async,int error,ScopedVector<WebSocketFrame> frames)483 void PrepareRawReadFrames(IsSync async,
484 int error,
485 ScopedVector<WebSocketFrame> frames) {
486 responses_.push_back(new Response(async, error, frames.Pass()));
487 }
488
489 // Prepares a fake error response (ie. there is no data).
PrepareReadFramesError(IsSync async,int error)490 void PrepareReadFramesError(IsSync async, int error) {
491 responses_.push_back(
492 new Response(async, error, ScopedVector<WebSocketFrame>()));
493 }
494
ReadFrames(ScopedVector<WebSocketFrame> * frames,const CompletionCallback & callback)495 virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
496 const CompletionCallback& callback) OVERRIDE {
497 CHECK(!read_frames_pending_);
498 if (index_ >= responses_.size())
499 return ERR_IO_PENDING;
500 if (responses_[index_]->async == ASYNC) {
501 read_frames_pending_ = true;
502 base::MessageLoop::current()->PostTask(
503 FROM_HERE,
504 base::Bind(&ReadableFakeWebSocketStream::DoCallback,
505 base::Unretained(this),
506 frames,
507 callback));
508 return ERR_IO_PENDING;
509 } else {
510 frames->swap(responses_[index_]->frames);
511 return responses_[index_++]->error;
512 }
513 }
514
515 private:
DoCallback(ScopedVector<WebSocketFrame> * frames,const CompletionCallback & callback)516 void DoCallback(ScopedVector<WebSocketFrame>* frames,
517 const CompletionCallback& callback) {
518 read_frames_pending_ = false;
519 frames->swap(responses_[index_]->frames);
520 callback.Run(responses_[index_++]->error);
521 return;
522 }
523
524 struct Response {
Responsenet::__anon89aaeda00111::ReadableFakeWebSocketStream::Response525 Response(IsSync async, int error, ScopedVector<WebSocketFrame> frames)
526 : async(async), error(error), frames(frames.Pass()) {}
527
528 IsSync async;
529 int error;
530 ScopedVector<WebSocketFrame> frames;
531
532 private:
533 // Bad things will happen if we attempt to copy or assign |frames|.
534 DISALLOW_COPY_AND_ASSIGN(Response);
535 };
536 ScopedVector<Response> responses_;
537
538 // The index into the responses_ array of the next response to be returned.
539 size_t index_;
540
541 // True when an async response from ReadFrames() is pending. This only applies
542 // to "real" async responses. Once all the prepared responses have been
543 // returned, ReadFrames() returns ERR_IO_PENDING but read_frames_pending_ is
544 // not set to true.
545 bool read_frames_pending_;
546 };
547
548 // A FakeWebSocketStream where writes always complete successfully and
549 // synchronously.
550 class WriteableFakeWebSocketStream : public FakeWebSocketStream {
551 public:
WriteFrames(ScopedVector<WebSocketFrame> * frames,const CompletionCallback & callback)552 virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
553 const CompletionCallback& callback) OVERRIDE {
554 return OK;
555 }
556 };
557
558 // A FakeWebSocketStream where writes always fail.
559 class UnWriteableFakeWebSocketStream : public FakeWebSocketStream {
560 public:
WriteFrames(ScopedVector<WebSocketFrame> * frames,const CompletionCallback & callback)561 virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
562 const CompletionCallback& callback) OVERRIDE {
563 return ERR_CONNECTION_RESET;
564 }
565 };
566
567 // A FakeWebSocketStream which echoes any frames written back. Clears the
568 // "masked" header bit, but makes no other checks for validity. Tests using this
569 // must run the MessageLoop to receive the callback(s). If a message with opcode
570 // Close is echoed, then an ERR_CONNECTION_CLOSED is returned in the next
571 // callback. The test must do something to cause WriteFrames() to be called,
572 // otherwise the ReadFrames() callback will never be called.
573 class EchoeyFakeWebSocketStream : public FakeWebSocketStream {
574 public:
EchoeyFakeWebSocketStream()575 EchoeyFakeWebSocketStream() : read_frames_(NULL), done_(false) {}
576
WriteFrames(ScopedVector<WebSocketFrame> * frames,const CompletionCallback & callback)577 virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
578 const CompletionCallback& callback) OVERRIDE {
579 // Users of WebSocketStream will not expect the ReadFrames() callback to be
580 // called from within WriteFrames(), so post it to the message loop instead.
581 stored_frames_.insert(stored_frames_.end(), frames->begin(), frames->end());
582 frames->weak_clear();
583 PostCallback();
584 return OK;
585 }
586
ReadFrames(ScopedVector<WebSocketFrame> * frames,const CompletionCallback & callback)587 virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
588 const CompletionCallback& callback) OVERRIDE {
589 read_callback_ = callback;
590 read_frames_ = frames;
591 if (done_)
592 PostCallback();
593 return ERR_IO_PENDING;
594 }
595
596 private:
PostCallback()597 void PostCallback() {
598 base::MessageLoop::current()->PostTask(
599 FROM_HERE,
600 base::Bind(&EchoeyFakeWebSocketStream::DoCallback,
601 base::Unretained(this)));
602 }
603
DoCallback()604 void DoCallback() {
605 if (done_) {
606 read_callback_.Run(ERR_CONNECTION_CLOSED);
607 } else if (!stored_frames_.empty()) {
608 done_ = MoveFrames(read_frames_);
609 read_frames_ = NULL;
610 read_callback_.Run(OK);
611 }
612 }
613
614 // Copy the frames stored in stored_frames_ to |out|, while clearing the
615 // "masked" header bit. Returns true if a Close Frame was seen, false
616 // otherwise.
MoveFrames(ScopedVector<WebSocketFrame> * out)617 bool MoveFrames(ScopedVector<WebSocketFrame>* out) {
618 bool seen_close = false;
619 *out = stored_frames_.Pass();
620 for (ScopedVector<WebSocketFrame>::iterator it = out->begin();
621 it != out->end();
622 ++it) {
623 WebSocketFrameHeader& header = (*it)->header;
624 header.masked = false;
625 if (header.opcode == WebSocketFrameHeader::kOpCodeClose)
626 seen_close = true;
627 }
628 return seen_close;
629 }
630
631 ScopedVector<WebSocketFrame> stored_frames_;
632 CompletionCallback read_callback_;
633 // Owned by the caller of ReadFrames().
634 ScopedVector<WebSocketFrame>* read_frames_;
635 // True if we should close the connection.
636 bool done_;
637 };
638
639 // A FakeWebSocketStream where writes trigger a connection reset.
640 // This differs from UnWriteableFakeWebSocketStream in that it is asynchronous
641 // and triggers ReadFrames to return a reset as well. Tests using this need to
642 // run the message loop. There are two tricky parts here:
643 // 1. Calling the write callback may call Close(), after which the read callback
644 // should not be called.
645 // 2. Calling either callback may delete the stream altogether.
646 class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream {
647 public:
ResetOnWriteFakeWebSocketStream()648 ResetOnWriteFakeWebSocketStream() : closed_(false), weak_ptr_factory_(this) {}
649
WriteFrames(ScopedVector<WebSocketFrame> * frames,const CompletionCallback & callback)650 virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
651 const CompletionCallback& callback) OVERRIDE {
652 base::MessageLoop::current()->PostTask(
653 FROM_HERE,
654 base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
655 weak_ptr_factory_.GetWeakPtr(),
656 callback,
657 ERR_CONNECTION_RESET));
658 base::MessageLoop::current()->PostTask(
659 FROM_HERE,
660 base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
661 weak_ptr_factory_.GetWeakPtr(),
662 read_callback_,
663 ERR_CONNECTION_RESET));
664 return ERR_IO_PENDING;
665 }
666
ReadFrames(ScopedVector<WebSocketFrame> * frames,const CompletionCallback & callback)667 virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
668 const CompletionCallback& callback) OVERRIDE {
669 read_callback_ = callback;
670 return ERR_IO_PENDING;
671 }
672
Close()673 virtual void Close() OVERRIDE { closed_ = true; }
674
675 private:
CallCallbackUnlessClosed(const CompletionCallback & callback,int value)676 void CallCallbackUnlessClosed(const CompletionCallback& callback, int value) {
677 if (!closed_)
678 callback.Run(value);
679 }
680
681 CompletionCallback read_callback_;
682 bool closed_;
683 // An IO error can result in the socket being deleted, so we use weak pointers
684 // to ensure correct behaviour in that case.
685 base::WeakPtrFactory<ResetOnWriteFakeWebSocketStream> weak_ptr_factory_;
686 };
687
688 // This mock is for verifying that WebSocket protocol semantics are obeyed (to
689 // the extent that they are implemented in WebSocketCommon).
690 class MockWebSocketStream : public WebSocketStream {
691 public:
692 MOCK_METHOD2(ReadFrames,
693 int(ScopedVector<WebSocketFrame>* frames,
694 const CompletionCallback& callback));
695 MOCK_METHOD2(WriteFrames,
696 int(ScopedVector<WebSocketFrame>* frames,
697 const CompletionCallback& callback));
698 MOCK_METHOD0(Close, void());
699 MOCK_CONST_METHOD0(GetSubProtocol, std::string());
700 MOCK_CONST_METHOD0(GetExtensions, std::string());
701 MOCK_METHOD0(AsWebSocketStream, WebSocketStream*());
702 };
703
704 struct ArgumentCopyingWebSocketStreamCreator {
Createnet::__anon89aaeda00111::ArgumentCopyingWebSocketStreamCreator705 scoped_ptr<WebSocketStreamRequest> Create(
706 const GURL& socket_url,
707 const std::vector<std::string>& requested_subprotocols,
708 const url::Origin& origin,
709 URLRequestContext* url_request_context,
710 const BoundNetLog& net_log,
711 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
712 this->socket_url = socket_url;
713 this->requested_subprotocols = requested_subprotocols;
714 this->origin = origin;
715 this->url_request_context = url_request_context;
716 this->net_log = net_log;
717 this->connect_delegate = connect_delegate.Pass();
718 return make_scoped_ptr(new WebSocketStreamRequest);
719 }
720
721 GURL socket_url;
722 url::Origin origin;
723 std::vector<std::string> requested_subprotocols;
724 URLRequestContext* url_request_context;
725 BoundNetLog net_log;
726 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate;
727 };
728
729 // Converts a std::string to a std::vector<char>. For test purposes, it is
730 // convenient to be able to specify data as a string, but the
731 // WebSocketEventInterface requires the vector<char> type.
AsVector(const std::string & s)732 std::vector<char> AsVector(const std::string& s) {
733 return std::vector<char>(s.begin(), s.end());
734 }
735
736 class FakeSSLErrorCallbacks
737 : public WebSocketEventInterface::SSLErrorCallbacks {
738 public:
CancelSSLRequest(int error,const SSLInfo * ssl_info)739 virtual void CancelSSLRequest(int error, const SSLInfo* ssl_info) OVERRIDE {}
ContinueSSLRequest()740 virtual void ContinueSSLRequest() OVERRIDE {}
741 };
742
743 // Base class for all test fixtures.
744 class WebSocketChannelTest : public ::testing::Test {
745 protected:
WebSocketChannelTest()746 WebSocketChannelTest() : stream_(new FakeWebSocketStream) {}
747
748 // Creates a new WebSocketChannel and connects it, using the settings stored
749 // in |connect_data_|.
CreateChannelAndConnect()750 void CreateChannelAndConnect() {
751 channel_.reset(new WebSocketChannel(CreateEventInterface(),
752 &connect_data_.url_request_context));
753 channel_->SendAddChannelRequestForTesting(
754 connect_data_.socket_url,
755 connect_data_.requested_subprotocols,
756 connect_data_.origin,
757 base::Bind(&ArgumentCopyingWebSocketStreamCreator::Create,
758 base::Unretained(&connect_data_.creator)));
759 }
760
761 // Same as CreateChannelAndConnect(), but calls the on_success callback as
762 // well. This method is virtual so that subclasses can also set the stream.
CreateChannelAndConnectSuccessfully()763 virtual void CreateChannelAndConnectSuccessfully() {
764 CreateChannelAndConnect();
765 // Most tests aren't concerned with flow control from the renderer, so allow
766 // MAX_INT quota units.
767 channel_->SendFlowControl(kPlentyOfQuota);
768 connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
769 }
770
771 // Returns a WebSocketEventInterface to be passed to the WebSocketChannel.
772 // This implementation returns a newly-created fake. Subclasses may return a
773 // mock instead.
CreateEventInterface()774 virtual scoped_ptr<WebSocketEventInterface> CreateEventInterface() {
775 return scoped_ptr<WebSocketEventInterface>(new FakeWebSocketEventInterface);
776 }
777
778 // This method serves no other purpose than to provide a nice syntax for
779 // assigning to stream_. class T must be a subclass of WebSocketStream or you
780 // will have unpleasant compile errors.
781 template <class T>
set_stream(scoped_ptr<T> stream)782 void set_stream(scoped_ptr<T> stream) {
783 // Since the definition of "PassAs" depends on the type T, the C++ standard
784 // requires the "template" keyword to indicate that "PassAs" should be
785 // parsed as a template method.
786 stream_ = stream.template PassAs<WebSocketStream>();
787 }
788
789 // A struct containing the data that will be used to connect the channel.
790 // Grouped for readability.
791 struct ConnectData {
ConnectDatanet::__anon89aaeda00111::WebSocketChannelTest::ConnectData792 ConnectData() : socket_url("ws://ws/"), origin("http://ws") {}
793
794 // URLRequestContext object.
795 URLRequestContext url_request_context;
796
797 // URL to (pretend to) connect to.
798 GURL socket_url;
799 // Requested protocols for the request.
800 std::vector<std::string> requested_subprotocols;
801 // Origin of the request
802 url::Origin origin;
803
804 // A fake WebSocketStreamCreator that just records its arguments.
805 ArgumentCopyingWebSocketStreamCreator creator;
806 };
807 ConnectData connect_data_;
808
809 // The channel we are testing. Not initialised until SetChannel() is called.
810 scoped_ptr<WebSocketChannel> channel_;
811
812 // A mock or fake stream for tests that need one.
813 scoped_ptr<WebSocketStream> stream_;
814 };
815
816 // enum of WebSocketEventInterface calls. These are intended to be or'd together
817 // in order to instruct WebSocketChannelDeletingTest when it should fail.
818 enum EventInterfaceCall {
819 EVENT_ON_ADD_CHANNEL_RESPONSE = 0x1,
820 EVENT_ON_DATA_FRAME = 0x2,
821 EVENT_ON_FLOW_CONTROL = 0x4,
822 EVENT_ON_CLOSING_HANDSHAKE = 0x8,
823 EVENT_ON_FAIL_CHANNEL = 0x10,
824 EVENT_ON_DROP_CHANNEL = 0x20,
825 EVENT_ON_START_OPENING_HANDSHAKE = 0x40,
826 EVENT_ON_FINISH_OPENING_HANDSHAKE = 0x80,
827 EVENT_ON_SSL_CERTIFICATE_ERROR = 0x100,
828 };
829
830 class WebSocketChannelDeletingTest : public WebSocketChannelTest {
831 public:
DeleteIfDeleting(EventInterfaceCall call)832 ChannelState DeleteIfDeleting(EventInterfaceCall call) {
833 if (deleting_ & call) {
834 channel_.reset();
835 return CHANNEL_DELETED;
836 } else {
837 return CHANNEL_ALIVE;
838 }
839 }
840
841 protected:
WebSocketChannelDeletingTest()842 WebSocketChannelDeletingTest()
843 : deleting_(EVENT_ON_ADD_CHANNEL_RESPONSE | EVENT_ON_DATA_FRAME |
844 EVENT_ON_FLOW_CONTROL |
845 EVENT_ON_CLOSING_HANDSHAKE |
846 EVENT_ON_FAIL_CHANNEL |
847 EVENT_ON_DROP_CHANNEL |
848 EVENT_ON_START_OPENING_HANDSHAKE |
849 EVENT_ON_FINISH_OPENING_HANDSHAKE |
850 EVENT_ON_SSL_CERTIFICATE_ERROR) {}
851 // Create a ChannelDeletingFakeWebSocketEventInterface. Defined out-of-line to
852 // avoid circular dependency.
853 virtual scoped_ptr<WebSocketEventInterface> CreateEventInterface() OVERRIDE;
854
855 // Tests can set deleting_ to a bitmap of EventInterfaceCall members that they
856 // want to cause Channel deletion. The default is for all calls to cause
857 // deletion.
858 int deleting_;
859 };
860
861 // A FakeWebSocketEventInterface that deletes the WebSocketChannel on failure to
862 // connect.
863 class ChannelDeletingFakeWebSocketEventInterface
864 : public FakeWebSocketEventInterface {
865 public:
ChannelDeletingFakeWebSocketEventInterface(WebSocketChannelDeletingTest * fixture)866 ChannelDeletingFakeWebSocketEventInterface(
867 WebSocketChannelDeletingTest* fixture)
868 : fixture_(fixture) {}
869
OnAddChannelResponse(bool fail,const std::string & selected_protocol,const std::string & extensions)870 virtual ChannelState OnAddChannelResponse(
871 bool fail,
872 const std::string& selected_protocol,
873 const std::string& extensions) OVERRIDE {
874 return fixture_->DeleteIfDeleting(EVENT_ON_ADD_CHANNEL_RESPONSE);
875 }
876
OnDataFrame(bool fin,WebSocketMessageType type,const std::vector<char> & data)877 virtual ChannelState OnDataFrame(bool fin,
878 WebSocketMessageType type,
879 const std::vector<char>& data) OVERRIDE {
880 return fixture_->DeleteIfDeleting(EVENT_ON_DATA_FRAME);
881 }
882
OnFlowControl(int64 quota)883 virtual ChannelState OnFlowControl(int64 quota) OVERRIDE {
884 return fixture_->DeleteIfDeleting(EVENT_ON_FLOW_CONTROL);
885 }
886
OnClosingHandshake()887 virtual ChannelState OnClosingHandshake() OVERRIDE {
888 return fixture_->DeleteIfDeleting(EVENT_ON_CLOSING_HANDSHAKE);
889 }
890
OnFailChannel(const std::string & message)891 virtual ChannelState OnFailChannel(const std::string& message) OVERRIDE {
892 return fixture_->DeleteIfDeleting(EVENT_ON_FAIL_CHANNEL);
893 }
894
OnDropChannel(bool was_clean,uint16 code,const std::string & reason)895 virtual ChannelState OnDropChannel(bool was_clean,
896 uint16 code,
897 const std::string& reason) OVERRIDE {
898 return fixture_->DeleteIfDeleting(EVENT_ON_DROP_CHANNEL);
899 }
900
OnStartOpeningHandshake(scoped_ptr<WebSocketHandshakeRequestInfo> request)901 virtual ChannelState OnStartOpeningHandshake(
902 scoped_ptr<WebSocketHandshakeRequestInfo> request) OVERRIDE {
903 return fixture_->DeleteIfDeleting(EVENT_ON_START_OPENING_HANDSHAKE);
904 }
OnFinishOpeningHandshake(scoped_ptr<WebSocketHandshakeResponseInfo> response)905 virtual ChannelState OnFinishOpeningHandshake(
906 scoped_ptr<WebSocketHandshakeResponseInfo> response) OVERRIDE {
907 return fixture_->DeleteIfDeleting(EVENT_ON_FINISH_OPENING_HANDSHAKE);
908 }
OnSSLCertificateError(scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks,const GURL & url,const SSLInfo & ssl_info,bool fatal)909 virtual ChannelState OnSSLCertificateError(
910 scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks,
911 const GURL& url,
912 const SSLInfo& ssl_info,
913 bool fatal) OVERRIDE {
914 return fixture_->DeleteIfDeleting(EVENT_ON_SSL_CERTIFICATE_ERROR);
915 }
916
917 private:
918 // A pointer to the test fixture. Owned by the test harness; this object will
919 // be deleted before it is.
920 WebSocketChannelDeletingTest* fixture_;
921 };
922
923 scoped_ptr<WebSocketEventInterface>
CreateEventInterface()924 WebSocketChannelDeletingTest::CreateEventInterface() {
925 return scoped_ptr<WebSocketEventInterface>(
926 new ChannelDeletingFakeWebSocketEventInterface(this));
927 }
928
929 // Base class for tests which verify that EventInterface methods are called
930 // appropriately.
931 class WebSocketChannelEventInterfaceTest : public WebSocketChannelTest {
932 protected:
WebSocketChannelEventInterfaceTest()933 WebSocketChannelEventInterfaceTest()
934 : event_interface_(new StrictMock<MockWebSocketEventInterface>) {
935 DefaultValue<ChannelState>::Set(CHANNEL_ALIVE);
936 ON_CALL(*event_interface_, OnAddChannelResponse(true, _, _))
937 .WillByDefault(Return(CHANNEL_DELETED));
938 ON_CALL(*event_interface_, OnDropChannel(_, _, _))
939 .WillByDefault(Return(CHANNEL_DELETED));
940 ON_CALL(*event_interface_, OnFailChannel(_))
941 .WillByDefault(Return(CHANNEL_DELETED));
942 }
943
~WebSocketChannelEventInterfaceTest()944 virtual ~WebSocketChannelEventInterfaceTest() {
945 DefaultValue<ChannelState>::Clear();
946 }
947
948 // Tests using this fixture must set expectations on the event_interface_ mock
949 // object before calling CreateChannelAndConnect() or
950 // CreateChannelAndConnectSuccessfully(). This will only work once per test
951 // case, but once should be enough.
CreateEventInterface()952 virtual scoped_ptr<WebSocketEventInterface> CreateEventInterface() OVERRIDE {
953 return scoped_ptr<WebSocketEventInterface>(event_interface_.release());
954 }
955
956 scoped_ptr<MockWebSocketEventInterface> event_interface_;
957 };
958
959 // Base class for tests which verify that WebSocketStream methods are called
960 // appropriately by using a MockWebSocketStream.
961 class WebSocketChannelStreamTest : public WebSocketChannelTest {
962 protected:
WebSocketChannelStreamTest()963 WebSocketChannelStreamTest()
964 : mock_stream_(new StrictMock<MockWebSocketStream>) {}
965
CreateChannelAndConnectSuccessfully()966 virtual void CreateChannelAndConnectSuccessfully() OVERRIDE {
967 set_stream(mock_stream_.Pass());
968 WebSocketChannelTest::CreateChannelAndConnectSuccessfully();
969 }
970
971 scoped_ptr<MockWebSocketStream> mock_stream_;
972 };
973
974 // Fixture for tests which test UTF-8 validation of sent Text frames via the
975 // EventInterface.
976 class WebSocketChannelSendUtf8Test
977 : public WebSocketChannelEventInterfaceTest {
978 public:
SetUp()979 virtual void SetUp() {
980 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream));
981 // For the purpose of the tests using this fixture, it doesn't matter
982 // whether these methods are called or not.
983 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _))
984 .Times(AnyNumber());
985 EXPECT_CALL(*event_interface_, OnFlowControl(_))
986 .Times(AnyNumber());
987 }
988 };
989
990 // Fixture for tests which test use of receive quota from the renderer.
991 class WebSocketChannelFlowControlTest
992 : public WebSocketChannelEventInterfaceTest {
993 protected:
994 // Tests using this fixture should use CreateChannelAndConnectWithQuota()
995 // instead of CreateChannelAndConnectSuccessfully().
CreateChannelAndConnectWithQuota(int64 quota)996 void CreateChannelAndConnectWithQuota(int64 quota) {
997 CreateChannelAndConnect();
998 channel_->SendFlowControl(quota);
999 connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
1000 }
1001
CreateChannelAndConnectSuccesfully()1002 virtual void CreateChannelAndConnectSuccesfully() { NOTREACHED(); }
1003 };
1004
1005 // Fixture for tests which test UTF-8 validation of received Text frames using a
1006 // mock WebSocketStream.
1007 class WebSocketChannelReceiveUtf8Test : public WebSocketChannelStreamTest {
1008 public:
SetUp()1009 virtual void SetUp() {
1010 // For the purpose of the tests using this fixture, it doesn't matter
1011 // whether these methods are called or not.
1012 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
1013 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
1014 }
1015 };
1016
1017 // Simple test that everything that should be passed to the creator function is
1018 // passed to the creator function.
TEST_F(WebSocketChannelTest,EverythingIsPassedToTheCreatorFunction)1019 TEST_F(WebSocketChannelTest, EverythingIsPassedToTheCreatorFunction) {
1020 connect_data_.socket_url = GURL("ws://example.com/test");
1021 connect_data_.origin = url::Origin("http://example.com");
1022 connect_data_.requested_subprotocols.push_back("Sinbad");
1023
1024 CreateChannelAndConnect();
1025
1026 const ArgumentCopyingWebSocketStreamCreator& actual = connect_data_.creator;
1027
1028 EXPECT_EQ(&connect_data_.url_request_context, actual.url_request_context);
1029
1030 EXPECT_EQ(connect_data_.socket_url, actual.socket_url);
1031 EXPECT_EQ(connect_data_.requested_subprotocols,
1032 actual.requested_subprotocols);
1033 EXPECT_EQ(connect_data_.origin.string(), actual.origin.string());
1034 }
1035
1036 // Verify that calling SendFlowControl before the connection is established does
1037 // not cause a crash.
TEST_F(WebSocketChannelTest,SendFlowControlDuringHandshakeOkay)1038 TEST_F(WebSocketChannelTest, SendFlowControlDuringHandshakeOkay) {
1039 CreateChannelAndConnect();
1040 ASSERT_TRUE(channel_);
1041 channel_->SendFlowControl(65536);
1042 }
1043
1044 // Any WebSocketEventInterface methods can delete the WebSocketChannel and
1045 // return CHANNEL_DELETED. The WebSocketChannelDeletingTests are intended to
1046 // verify that there are no use-after-free bugs when this happens. Problems will
1047 // probably only be found when running under Address Sanitizer or a similar
1048 // tool.
TEST_F(WebSocketChannelDeletingTest,OnAddChannelResponseFail)1049 TEST_F(WebSocketChannelDeletingTest, OnAddChannelResponseFail) {
1050 CreateChannelAndConnect();
1051 EXPECT_TRUE(channel_);
1052 connect_data_.creator.connect_delegate->OnFailure("bye");
1053 EXPECT_EQ(NULL, channel_.get());
1054 }
1055
1056 // Deletion is possible (due to IPC failure) even if the connect succeeds.
TEST_F(WebSocketChannelDeletingTest,OnAddChannelResponseSuccess)1057 TEST_F(WebSocketChannelDeletingTest, OnAddChannelResponseSuccess) {
1058 CreateChannelAndConnectSuccessfully();
1059 EXPECT_EQ(NULL, channel_.get());
1060 }
1061
TEST_F(WebSocketChannelDeletingTest,OnDataFrameSync)1062 TEST_F(WebSocketChannelDeletingTest, OnDataFrameSync) {
1063 scoped_ptr<ReadableFakeWebSocketStream> stream(
1064 new ReadableFakeWebSocketStream);
1065 static const InitFrame frames[] = {
1066 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1067 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1068 set_stream(stream.Pass());
1069 deleting_ = EVENT_ON_DATA_FRAME;
1070
1071 CreateChannelAndConnectSuccessfully();
1072 EXPECT_EQ(NULL, channel_.get());
1073 }
1074
TEST_F(WebSocketChannelDeletingTest,OnDataFrameAsync)1075 TEST_F(WebSocketChannelDeletingTest, OnDataFrameAsync) {
1076 scoped_ptr<ReadableFakeWebSocketStream> stream(
1077 new ReadableFakeWebSocketStream);
1078 static const InitFrame frames[] = {
1079 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1080 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1081 set_stream(stream.Pass());
1082 deleting_ = EVENT_ON_DATA_FRAME;
1083
1084 CreateChannelAndConnectSuccessfully();
1085 EXPECT_TRUE(channel_);
1086 base::MessageLoop::current()->RunUntilIdle();
1087 EXPECT_EQ(NULL, channel_.get());
1088 }
1089
TEST_F(WebSocketChannelDeletingTest,OnFlowControlAfterConnect)1090 TEST_F(WebSocketChannelDeletingTest, OnFlowControlAfterConnect) {
1091 deleting_ = EVENT_ON_FLOW_CONTROL;
1092
1093 CreateChannelAndConnectSuccessfully();
1094 EXPECT_EQ(NULL, channel_.get());
1095 }
1096
TEST_F(WebSocketChannelDeletingTest,OnFlowControlAfterSend)1097 TEST_F(WebSocketChannelDeletingTest, OnFlowControlAfterSend) {
1098 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream));
1099 // Avoid deleting the channel yet.
1100 deleting_ = EVENT_ON_FAIL_CHANNEL | EVENT_ON_DROP_CHANNEL;
1101 CreateChannelAndConnectSuccessfully();
1102 ASSERT_TRUE(channel_);
1103 deleting_ = EVENT_ON_FLOW_CONTROL;
1104 channel_->SendFrame(true,
1105 WebSocketFrameHeader::kOpCodeText,
1106 std::vector<char>(kDefaultInitialQuota, 'B'));
1107 EXPECT_EQ(NULL, channel_.get());
1108 }
1109
TEST_F(WebSocketChannelDeletingTest,OnClosingHandshakeSync)1110 TEST_F(WebSocketChannelDeletingTest, OnClosingHandshakeSync) {
1111 scoped_ptr<ReadableFakeWebSocketStream> stream(
1112 new ReadableFakeWebSocketStream);
1113 static const InitFrame frames[] = {
1114 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1115 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
1116 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1117 set_stream(stream.Pass());
1118 deleting_ = EVENT_ON_CLOSING_HANDSHAKE;
1119 CreateChannelAndConnectSuccessfully();
1120 EXPECT_EQ(NULL, channel_.get());
1121 }
1122
TEST_F(WebSocketChannelDeletingTest,OnClosingHandshakeAsync)1123 TEST_F(WebSocketChannelDeletingTest, OnClosingHandshakeAsync) {
1124 scoped_ptr<ReadableFakeWebSocketStream> stream(
1125 new ReadableFakeWebSocketStream);
1126 static const InitFrame frames[] = {
1127 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1128 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
1129 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1130 set_stream(stream.Pass());
1131 deleting_ = EVENT_ON_CLOSING_HANDSHAKE;
1132 CreateChannelAndConnectSuccessfully();
1133 ASSERT_TRUE(channel_);
1134 base::MessageLoop::current()->RunUntilIdle();
1135 EXPECT_EQ(NULL, channel_.get());
1136 }
1137
TEST_F(WebSocketChannelDeletingTest,OnDropChannelWriteError)1138 TEST_F(WebSocketChannelDeletingTest, OnDropChannelWriteError) {
1139 set_stream(make_scoped_ptr(new UnWriteableFakeWebSocketStream));
1140 deleting_ = EVENT_ON_DROP_CHANNEL;
1141 CreateChannelAndConnectSuccessfully();
1142 ASSERT_TRUE(channel_);
1143 channel_->SendFrame(
1144 true, WebSocketFrameHeader::kOpCodeText, AsVector("this will fail"));
1145 EXPECT_EQ(NULL, channel_.get());
1146 }
1147
TEST_F(WebSocketChannelDeletingTest,OnDropChannelReadError)1148 TEST_F(WebSocketChannelDeletingTest, OnDropChannelReadError) {
1149 scoped_ptr<ReadableFakeWebSocketStream> stream(
1150 new ReadableFakeWebSocketStream);
1151 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1152 ERR_FAILED);
1153 set_stream(stream.Pass());
1154 deleting_ = EVENT_ON_DROP_CHANNEL;
1155 CreateChannelAndConnectSuccessfully();
1156 ASSERT_TRUE(channel_);
1157 base::MessageLoop::current()->RunUntilIdle();
1158 EXPECT_EQ(NULL, channel_.get());
1159 }
1160
TEST_F(WebSocketChannelDeletingTest,OnNotifyStartOpeningHandshakeError)1161 TEST_F(WebSocketChannelDeletingTest, OnNotifyStartOpeningHandshakeError) {
1162 scoped_ptr<ReadableFakeWebSocketStream> stream(
1163 new ReadableFakeWebSocketStream);
1164 static const InitFrame frames[] = {
1165 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1166 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1167 set_stream(stream.Pass());
1168 deleting_ = EVENT_ON_START_OPENING_HANDSHAKE;
1169
1170 CreateChannelAndConnectSuccessfully();
1171 ASSERT_TRUE(channel_);
1172 channel_->OnStartOpeningHandshake(scoped_ptr<WebSocketHandshakeRequestInfo>(
1173 new WebSocketHandshakeRequestInfo(GURL("http://www.example.com/"),
1174 base::Time())));
1175 base::MessageLoop::current()->RunUntilIdle();
1176 EXPECT_EQ(NULL, channel_.get());
1177 }
1178
TEST_F(WebSocketChannelDeletingTest,OnNotifyFinishOpeningHandshakeError)1179 TEST_F(WebSocketChannelDeletingTest, OnNotifyFinishOpeningHandshakeError) {
1180 scoped_ptr<ReadableFakeWebSocketStream> stream(
1181 new ReadableFakeWebSocketStream);
1182 static const InitFrame frames[] = {
1183 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1184 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1185 set_stream(stream.Pass());
1186 deleting_ = EVENT_ON_FINISH_OPENING_HANDSHAKE;
1187
1188 CreateChannelAndConnectSuccessfully();
1189 ASSERT_TRUE(channel_);
1190 scoped_refptr<HttpResponseHeaders> response_headers(
1191 new HttpResponseHeaders(""));
1192 channel_->OnFinishOpeningHandshake(scoped_ptr<WebSocketHandshakeResponseInfo>(
1193 new WebSocketHandshakeResponseInfo(GURL("http://www.example.com/"),
1194 200,
1195 "OK",
1196 response_headers,
1197 base::Time())));
1198 base::MessageLoop::current()->RunUntilIdle();
1199 EXPECT_EQ(NULL, channel_.get());
1200 }
1201
TEST_F(WebSocketChannelDeletingTest,FailChannelInSendFrame)1202 TEST_F(WebSocketChannelDeletingTest, FailChannelInSendFrame) {
1203 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream));
1204 deleting_ = EVENT_ON_FAIL_CHANNEL;
1205 CreateChannelAndConnectSuccessfully();
1206 ASSERT_TRUE(channel_);
1207 channel_->SendFrame(true,
1208 WebSocketFrameHeader::kOpCodeText,
1209 std::vector<char>(kDefaultInitialQuota * 2, 'T'));
1210 EXPECT_EQ(NULL, channel_.get());
1211 }
1212
TEST_F(WebSocketChannelDeletingTest,FailChannelInOnReadDone)1213 TEST_F(WebSocketChannelDeletingTest, FailChannelInOnReadDone) {
1214 scoped_ptr<ReadableFakeWebSocketStream> stream(
1215 new ReadableFakeWebSocketStream);
1216 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1217 ERR_WS_PROTOCOL_ERROR);
1218 set_stream(stream.Pass());
1219 deleting_ = EVENT_ON_FAIL_CHANNEL;
1220 CreateChannelAndConnectSuccessfully();
1221 ASSERT_TRUE(channel_);
1222 base::MessageLoop::current()->RunUntilIdle();
1223 EXPECT_EQ(NULL, channel_.get());
1224 }
1225
TEST_F(WebSocketChannelDeletingTest,FailChannelDueToMaskedFrame)1226 TEST_F(WebSocketChannelDeletingTest, FailChannelDueToMaskedFrame) {
1227 scoped_ptr<ReadableFakeWebSocketStream> stream(
1228 new ReadableFakeWebSocketStream);
1229 static const InitFrame frames[] = {
1230 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}};
1231 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1232 set_stream(stream.Pass());
1233 deleting_ = EVENT_ON_FAIL_CHANNEL;
1234
1235 CreateChannelAndConnectSuccessfully();
1236 EXPECT_EQ(NULL, channel_.get());
1237 }
1238
TEST_F(WebSocketChannelDeletingTest,FailChannelDueToBadControlFrame)1239 TEST_F(WebSocketChannelDeletingTest, FailChannelDueToBadControlFrame) {
1240 scoped_ptr<ReadableFakeWebSocketStream> stream(
1241 new ReadableFakeWebSocketStream);
1242 static const InitFrame frames[] = {
1243 {FINAL_FRAME, 0xF, NOT_MASKED, ""}};
1244 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1245 set_stream(stream.Pass());
1246 deleting_ = EVENT_ON_FAIL_CHANNEL;
1247
1248 CreateChannelAndConnectSuccessfully();
1249 EXPECT_EQ(NULL, channel_.get());
1250 }
1251
1252 // Version of above test with NULL data.
TEST_F(WebSocketChannelDeletingTest,FailChannelDueToBadControlFrameNull)1253 TEST_F(WebSocketChannelDeletingTest, FailChannelDueToBadControlFrameNull) {
1254 scoped_ptr<ReadableFakeWebSocketStream> stream(
1255 new ReadableFakeWebSocketStream);
1256 static const InitFrame frames[] = {
1257 {FINAL_FRAME, 0xF, NOT_MASKED, NULL}};
1258 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1259 set_stream(stream.Pass());
1260 deleting_ = EVENT_ON_FAIL_CHANNEL;
1261
1262 CreateChannelAndConnectSuccessfully();
1263 EXPECT_EQ(NULL, channel_.get());
1264 }
1265
TEST_F(WebSocketChannelDeletingTest,FailChannelDueToPongAfterClose)1266 TEST_F(WebSocketChannelDeletingTest, FailChannelDueToPongAfterClose) {
1267 scoped_ptr<ReadableFakeWebSocketStream> stream(
1268 new ReadableFakeWebSocketStream);
1269 static const InitFrame frames[] = {
1270 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
1271 CLOSE_DATA(NORMAL_CLOSURE, "Success")},
1272 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}};
1273 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1274 set_stream(stream.Pass());
1275 deleting_ = EVENT_ON_FAIL_CHANNEL;
1276
1277 CreateChannelAndConnectSuccessfully();
1278 EXPECT_EQ(NULL, channel_.get());
1279 }
1280
TEST_F(WebSocketChannelDeletingTest,FailChannelDueToPongAfterCloseNull)1281 TEST_F(WebSocketChannelDeletingTest, FailChannelDueToPongAfterCloseNull) {
1282 scoped_ptr<ReadableFakeWebSocketStream> stream(
1283 new ReadableFakeWebSocketStream);
1284 static const InitFrame frames[] = {
1285 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
1286 CLOSE_DATA(NORMAL_CLOSURE, "Success")},
1287 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, NULL}};
1288 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1289 set_stream(stream.Pass());
1290 deleting_ = EVENT_ON_FAIL_CHANNEL;
1291
1292 CreateChannelAndConnectSuccessfully();
1293 EXPECT_EQ(NULL, channel_.get());
1294 }
1295
TEST_F(WebSocketChannelDeletingTest,FailChannelDueToUnknownOpCode)1296 TEST_F(WebSocketChannelDeletingTest, FailChannelDueToUnknownOpCode) {
1297 scoped_ptr<ReadableFakeWebSocketStream> stream(
1298 new ReadableFakeWebSocketStream);
1299 static const InitFrame frames[] = {{FINAL_FRAME, 0x7, NOT_MASKED, ""}};
1300 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1301 set_stream(stream.Pass());
1302 deleting_ = EVENT_ON_FAIL_CHANNEL;
1303
1304 CreateChannelAndConnectSuccessfully();
1305 EXPECT_EQ(NULL, channel_.get());
1306 }
1307
TEST_F(WebSocketChannelDeletingTest,FailChannelDueToUnknownOpCodeNull)1308 TEST_F(WebSocketChannelDeletingTest, FailChannelDueToUnknownOpCodeNull) {
1309 scoped_ptr<ReadableFakeWebSocketStream> stream(
1310 new ReadableFakeWebSocketStream);
1311 static const InitFrame frames[] = {{FINAL_FRAME, 0x7, NOT_MASKED, NULL}};
1312 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1313 set_stream(stream.Pass());
1314 deleting_ = EVENT_ON_FAIL_CHANNEL;
1315
1316 CreateChannelAndConnectSuccessfully();
1317 EXPECT_EQ(NULL, channel_.get());
1318 }
1319
TEST_F(WebSocketChannelDeletingTest,FailChannelDueInvalidCloseReason)1320 TEST_F(WebSocketChannelDeletingTest, FailChannelDueInvalidCloseReason) {
1321 scoped_ptr<ReadableFakeWebSocketStream> stream(
1322 new ReadableFakeWebSocketStream);
1323 static const InitFrame frames[] = {
1324 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1325 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}};
1326 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1327 set_stream(stream.Pass());
1328 deleting_ = EVENT_ON_FAIL_CHANNEL;
1329
1330 CreateChannelAndConnectSuccessfully();
1331 EXPECT_EQ(NULL, channel_.get());
1332 }
1333
TEST_F(WebSocketChannelEventInterfaceTest,ConnectSuccessReported)1334 TEST_F(WebSocketChannelEventInterfaceTest, ConnectSuccessReported) {
1335 // false means success.
1336 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, "", ""));
1337 // OnFlowControl is always called immediately after connect to provide initial
1338 // quota to the renderer.
1339 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1340
1341 CreateChannelAndConnect();
1342
1343 connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
1344 }
1345
TEST_F(WebSocketChannelEventInterfaceTest,ConnectFailureReported)1346 TEST_F(WebSocketChannelEventInterfaceTest, ConnectFailureReported) {
1347 EXPECT_CALL(*event_interface_, OnFailChannel("hello"));
1348
1349 CreateChannelAndConnect();
1350
1351 connect_data_.creator.connect_delegate->OnFailure("hello");
1352 }
1353
TEST_F(WebSocketChannelEventInterfaceTest,NonWebSocketSchemeRejected)1354 TEST_F(WebSocketChannelEventInterfaceTest, NonWebSocketSchemeRejected) {
1355 EXPECT_CALL(*event_interface_, OnAddChannelResponse(true, "", ""));
1356 connect_data_.socket_url = GURL("http://www.google.com/");
1357 CreateChannelAndConnect();
1358 }
1359
TEST_F(WebSocketChannelEventInterfaceTest,ProtocolPassed)1360 TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) {
1361 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, "Bob", ""));
1362 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1363
1364 CreateChannelAndConnect();
1365
1366 connect_data_.creator.connect_delegate->OnSuccess(
1367 scoped_ptr<WebSocketStream>(new FakeWebSocketStream("Bob", "")));
1368 }
1369
TEST_F(WebSocketChannelEventInterfaceTest,ExtensionsPassed)1370 TEST_F(WebSocketChannelEventInterfaceTest, ExtensionsPassed) {
1371 EXPECT_CALL(*event_interface_,
1372 OnAddChannelResponse(false, "", "extension1, extension2"));
1373 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1374
1375 CreateChannelAndConnect();
1376
1377 connect_data_.creator.connect_delegate->OnSuccess(scoped_ptr<WebSocketStream>(
1378 new FakeWebSocketStream("", "extension1, extension2")));
1379 }
1380
1381 // The first frames from the server can arrive together with the handshake, in
1382 // which case they will be available as soon as ReadFrames() is called the first
1383 // time.
TEST_F(WebSocketChannelEventInterfaceTest,DataLeftFromHandshake)1384 TEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) {
1385 scoped_ptr<ReadableFakeWebSocketStream> stream(
1386 new ReadableFakeWebSocketStream);
1387 static const InitFrame frames[] = {
1388 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1389 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1390 set_stream(stream.Pass());
1391 {
1392 InSequence s;
1393 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1394 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1395 EXPECT_CALL(
1396 *event_interface_,
1397 OnDataFrame(
1398 true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO")));
1399 }
1400
1401 CreateChannelAndConnectSuccessfully();
1402 }
1403
1404 // A remote server could accept the handshake, but then immediately send a
1405 // Close frame.
TEST_F(WebSocketChannelEventInterfaceTest,CloseAfterHandshake)1406 TEST_F(WebSocketChannelEventInterfaceTest, CloseAfterHandshake) {
1407 scoped_ptr<ReadableFakeWebSocketStream> stream(
1408 new ReadableFakeWebSocketStream);
1409 static const InitFrame frames[] = {
1410 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1411 NOT_MASKED, CLOSE_DATA(SERVER_ERROR, "Internal Server Error")}};
1412 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1413 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1414 ERR_CONNECTION_CLOSED);
1415 set_stream(stream.Pass());
1416 {
1417 InSequence s;
1418 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1419 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1420 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1421 EXPECT_CALL(
1422 *event_interface_,
1423 OnDropChannel(
1424 true, kWebSocketErrorInternalServerError, "Internal Server Error"));
1425 }
1426
1427 CreateChannelAndConnectSuccessfully();
1428 }
1429
1430 // A remote server could close the connection immediately after sending the
1431 // handshake response (most likely a bug in the server).
TEST_F(WebSocketChannelEventInterfaceTest,ConnectionCloseAfterHandshake)1432 TEST_F(WebSocketChannelEventInterfaceTest, ConnectionCloseAfterHandshake) {
1433 scoped_ptr<ReadableFakeWebSocketStream> stream(
1434 new ReadableFakeWebSocketStream);
1435 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1436 ERR_CONNECTION_CLOSED);
1437 set_stream(stream.Pass());
1438 {
1439 InSequence s;
1440 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1441 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1442 EXPECT_CALL(*event_interface_,
1443 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
1444 }
1445
1446 CreateChannelAndConnectSuccessfully();
1447 }
1448
TEST_F(WebSocketChannelEventInterfaceTest,NormalAsyncRead)1449 TEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) {
1450 scoped_ptr<ReadableFakeWebSocketStream> stream(
1451 new ReadableFakeWebSocketStream);
1452 static const InitFrame frames[] = {
1453 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1454 // We use this checkpoint object to verify that the callback isn't called
1455 // until we expect it to be.
1456 Checkpoint checkpoint;
1457 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1458 set_stream(stream.Pass());
1459 {
1460 InSequence s;
1461 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1462 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1463 EXPECT_CALL(checkpoint, Call(1));
1464 EXPECT_CALL(
1465 *event_interface_,
1466 OnDataFrame(
1467 true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO")));
1468 EXPECT_CALL(checkpoint, Call(2));
1469 }
1470
1471 CreateChannelAndConnectSuccessfully();
1472 checkpoint.Call(1);
1473 base::MessageLoop::current()->RunUntilIdle();
1474 checkpoint.Call(2);
1475 }
1476
1477 // Extra data can arrive while a read is being processed, resulting in the next
1478 // read completing synchronously.
TEST_F(WebSocketChannelEventInterfaceTest,AsyncThenSyncRead)1479 TEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) {
1480 scoped_ptr<ReadableFakeWebSocketStream> stream(
1481 new ReadableFakeWebSocketStream);
1482 static const InitFrame frames1[] = {
1483 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1484 static const InitFrame frames2[] = {
1485 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "WORLD"}};
1486 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1487 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames2);
1488 set_stream(stream.Pass());
1489 {
1490 InSequence s;
1491 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1492 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1493 EXPECT_CALL(
1494 *event_interface_,
1495 OnDataFrame(
1496 true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO")));
1497 EXPECT_CALL(
1498 *event_interface_,
1499 OnDataFrame(
1500 true, WebSocketFrameHeader::kOpCodeText, AsVector("WORLD")));
1501 }
1502
1503 CreateChannelAndConnectSuccessfully();
1504 base::MessageLoop::current()->RunUntilIdle();
1505 }
1506
1507 // Data frames are delivered the same regardless of how many reads they arrive
1508 // as.
TEST_F(WebSocketChannelEventInterfaceTest,FragmentedMessage)1509 TEST_F(WebSocketChannelEventInterfaceTest, FragmentedMessage) {
1510 scoped_ptr<ReadableFakeWebSocketStream> stream(
1511 new ReadableFakeWebSocketStream);
1512 // Here we have one message which arrived in five frames split across three
1513 // reads. It may have been reframed on arrival, but this class doesn't care
1514 // about that.
1515 static const InitFrame frames1[] = {
1516 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "THREE"},
1517 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1518 NOT_MASKED, " "}};
1519 static const InitFrame frames2[] = {
1520 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1521 NOT_MASKED, "SMALL"}};
1522 static const InitFrame frames3[] = {
1523 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1524 NOT_MASKED, " "},
1525 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1526 NOT_MASKED, "FRAMES"}};
1527 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1528 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
1529 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
1530 set_stream(stream.Pass());
1531 {
1532 InSequence s;
1533 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1534 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1535 EXPECT_CALL(
1536 *event_interface_,
1537 OnDataFrame(
1538 false, WebSocketFrameHeader::kOpCodeText, AsVector("THREE")));
1539 EXPECT_CALL(
1540 *event_interface_,
1541 OnDataFrame(
1542 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector(" ")));
1543 EXPECT_CALL(*event_interface_,
1544 OnDataFrame(false,
1545 WebSocketFrameHeader::kOpCodeContinuation,
1546 AsVector("SMALL")));
1547 EXPECT_CALL(
1548 *event_interface_,
1549 OnDataFrame(
1550 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector(" ")));
1551 EXPECT_CALL(*event_interface_,
1552 OnDataFrame(true,
1553 WebSocketFrameHeader::kOpCodeContinuation,
1554 AsVector("FRAMES")));
1555 }
1556
1557 CreateChannelAndConnectSuccessfully();
1558 base::MessageLoop::current()->RunUntilIdle();
1559 }
1560
1561 // A message can consist of one frame with NULL payload.
TEST_F(WebSocketChannelEventInterfaceTest,NullMessage)1562 TEST_F(WebSocketChannelEventInterfaceTest, NullMessage) {
1563 scoped_ptr<ReadableFakeWebSocketStream> stream(
1564 new ReadableFakeWebSocketStream);
1565 static const InitFrame frames[] = {
1566 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, NULL}};
1567 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1568 set_stream(stream.Pass());
1569 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1570 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1571 EXPECT_CALL(
1572 *event_interface_,
1573 OnDataFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
1574 CreateChannelAndConnectSuccessfully();
1575 }
1576
1577 // Connection closed by the remote host without a closing handshake.
TEST_F(WebSocketChannelEventInterfaceTest,AsyncAbnormalClosure)1578 TEST_F(WebSocketChannelEventInterfaceTest, AsyncAbnormalClosure) {
1579 scoped_ptr<ReadableFakeWebSocketStream> stream(
1580 new ReadableFakeWebSocketStream);
1581 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1582 ERR_CONNECTION_CLOSED);
1583 set_stream(stream.Pass());
1584 {
1585 InSequence s;
1586 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1587 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1588 EXPECT_CALL(*event_interface_,
1589 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
1590 }
1591
1592 CreateChannelAndConnectSuccessfully();
1593 base::MessageLoop::current()->RunUntilIdle();
1594 }
1595
1596 // A connection reset should produce the same event as an unexpected closure.
TEST_F(WebSocketChannelEventInterfaceTest,ConnectionReset)1597 TEST_F(WebSocketChannelEventInterfaceTest, ConnectionReset) {
1598 scoped_ptr<ReadableFakeWebSocketStream> stream(
1599 new ReadableFakeWebSocketStream);
1600 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1601 ERR_CONNECTION_RESET);
1602 set_stream(stream.Pass());
1603 {
1604 InSequence s;
1605 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1606 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1607 EXPECT_CALL(*event_interface_,
1608 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
1609 }
1610
1611 CreateChannelAndConnectSuccessfully();
1612 base::MessageLoop::current()->RunUntilIdle();
1613 }
1614
1615 // RFC6455 5.1 "A client MUST close a connection if it detects a masked frame."
TEST_F(WebSocketChannelEventInterfaceTest,MaskedFramesAreRejected)1616 TEST_F(WebSocketChannelEventInterfaceTest, MaskedFramesAreRejected) {
1617 scoped_ptr<ReadableFakeWebSocketStream> stream(
1618 new ReadableFakeWebSocketStream);
1619 static const InitFrame frames[] = {
1620 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}};
1621
1622 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1623 set_stream(stream.Pass());
1624 {
1625 InSequence s;
1626 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1627 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1628 EXPECT_CALL(
1629 *event_interface_,
1630 OnFailChannel(
1631 "A server must not mask any frames that it sends to the client."));
1632 }
1633
1634 CreateChannelAndConnectSuccessfully();
1635 base::MessageLoop::current()->RunUntilIdle();
1636 }
1637
1638 // RFC6455 5.2 "If an unknown opcode is received, the receiving endpoint MUST
1639 // _Fail the WebSocket Connection_."
TEST_F(WebSocketChannelEventInterfaceTest,UnknownOpCodeIsRejected)1640 TEST_F(WebSocketChannelEventInterfaceTest, UnknownOpCodeIsRejected) {
1641 scoped_ptr<ReadableFakeWebSocketStream> stream(
1642 new ReadableFakeWebSocketStream);
1643 static const InitFrame frames[] = {{FINAL_FRAME, 4, NOT_MASKED, "HELLO"}};
1644
1645 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1646 set_stream(stream.Pass());
1647 {
1648 InSequence s;
1649 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1650 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1651 EXPECT_CALL(*event_interface_,
1652 OnFailChannel("Unrecognized frame opcode: 4"));
1653 }
1654
1655 CreateChannelAndConnectSuccessfully();
1656 base::MessageLoop::current()->RunUntilIdle();
1657 }
1658
1659 // RFC6455 5.4 "Control frames ... MAY be injected in the middle of a
1660 // fragmented message."
TEST_F(WebSocketChannelEventInterfaceTest,ControlFrameInDataMessage)1661 TEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) {
1662 scoped_ptr<ReadableFakeWebSocketStream> stream(
1663 new ReadableFakeWebSocketStream);
1664 // We have one message of type Text split into two frames. In the middle is a
1665 // control message of type Pong.
1666 static const InitFrame frames1[] = {
1667 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
1668 NOT_MASKED, "SPLIT "}};
1669 static const InitFrame frames2[] = {
1670 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}};
1671 static const InitFrame frames3[] = {
1672 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1673 NOT_MASKED, "MESSAGE"}};
1674 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1675 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
1676 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
1677 set_stream(stream.Pass());
1678 {
1679 InSequence s;
1680 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1681 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1682 EXPECT_CALL(
1683 *event_interface_,
1684 OnDataFrame(
1685 false, WebSocketFrameHeader::kOpCodeText, AsVector("SPLIT ")));
1686 EXPECT_CALL(*event_interface_,
1687 OnDataFrame(true,
1688 WebSocketFrameHeader::kOpCodeContinuation,
1689 AsVector("MESSAGE")));
1690 }
1691
1692 CreateChannelAndConnectSuccessfully();
1693 base::MessageLoop::current()->RunUntilIdle();
1694 }
1695
1696 // It seems redundant to repeat the entirety of the above test, so just test a
1697 // Pong with NULL data.
TEST_F(WebSocketChannelEventInterfaceTest,PongWithNullData)1698 TEST_F(WebSocketChannelEventInterfaceTest, PongWithNullData) {
1699 scoped_ptr<ReadableFakeWebSocketStream> stream(
1700 new ReadableFakeWebSocketStream);
1701 static const InitFrame frames[] = {
1702 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, NULL}};
1703 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1704 set_stream(stream.Pass());
1705 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1706 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1707
1708 CreateChannelAndConnectSuccessfully();
1709 base::MessageLoop::current()->RunUntilIdle();
1710 }
1711
1712 // If a frame has an invalid header, then the connection is closed and
1713 // subsequent frames must not trigger events.
TEST_F(WebSocketChannelEventInterfaceTest,FrameAfterInvalidFrame)1714 TEST_F(WebSocketChannelEventInterfaceTest, FrameAfterInvalidFrame) {
1715 scoped_ptr<ReadableFakeWebSocketStream> stream(
1716 new ReadableFakeWebSocketStream);
1717 static const InitFrame frames[] = {
1718 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"},
1719 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, " WORLD"}};
1720
1721 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1722 set_stream(stream.Pass());
1723 {
1724 InSequence s;
1725 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1726 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1727 EXPECT_CALL(
1728 *event_interface_,
1729 OnFailChannel(
1730 "A server must not mask any frames that it sends to the client."));
1731 }
1732
1733 CreateChannelAndConnectSuccessfully();
1734 base::MessageLoop::current()->RunUntilIdle();
1735 }
1736
1737 // If the renderer sends lots of small writes, we don't want to update the quota
1738 // for each one.
TEST_F(WebSocketChannelEventInterfaceTest,SmallWriteDoesntUpdateQuota)1739 TEST_F(WebSocketChannelEventInterfaceTest, SmallWriteDoesntUpdateQuota) {
1740 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream));
1741 {
1742 InSequence s;
1743 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1744 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1745 }
1746
1747 CreateChannelAndConnectSuccessfully();
1748 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("B"));
1749 }
1750
1751 // If we send enough to go below send_quota_low_water_mask_ we should get our
1752 // quota refreshed.
TEST_F(WebSocketChannelEventInterfaceTest,LargeWriteUpdatesQuota)1753 TEST_F(WebSocketChannelEventInterfaceTest, LargeWriteUpdatesQuota) {
1754 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream));
1755 // We use this checkpoint object to verify that the quota update comes after
1756 // the write.
1757 Checkpoint checkpoint;
1758 {
1759 InSequence s;
1760 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1761 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1762 EXPECT_CALL(checkpoint, Call(1));
1763 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1764 EXPECT_CALL(checkpoint, Call(2));
1765 }
1766
1767 CreateChannelAndConnectSuccessfully();
1768 checkpoint.Call(1);
1769 channel_->SendFrame(true,
1770 WebSocketFrameHeader::kOpCodeText,
1771 std::vector<char>(kDefaultInitialQuota, 'B'));
1772 checkpoint.Call(2);
1773 }
1774
1775 // Verify that our quota actually is refreshed when we are told it is.
TEST_F(WebSocketChannelEventInterfaceTest,QuotaReallyIsRefreshed)1776 TEST_F(WebSocketChannelEventInterfaceTest, QuotaReallyIsRefreshed) {
1777 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream));
1778 Checkpoint checkpoint;
1779 {
1780 InSequence s;
1781 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1782 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1783 EXPECT_CALL(checkpoint, Call(1));
1784 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1785 EXPECT_CALL(checkpoint, Call(2));
1786 // If quota was not really refreshed, we would get an OnDropChannel()
1787 // message.
1788 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1789 EXPECT_CALL(checkpoint, Call(3));
1790 }
1791
1792 CreateChannelAndConnectSuccessfully();
1793 checkpoint.Call(1);
1794 channel_->SendFrame(true,
1795 WebSocketFrameHeader::kOpCodeText,
1796 std::vector<char>(kDefaultQuotaRefreshTrigger, 'D'));
1797 checkpoint.Call(2);
1798 // We should have received more quota at this point.
1799 channel_->SendFrame(true,
1800 WebSocketFrameHeader::kOpCodeText,
1801 std::vector<char>(kDefaultQuotaRefreshTrigger, 'E'));
1802 checkpoint.Call(3);
1803 }
1804
1805 // If we send more than the available quota then the connection will be closed
1806 // with an error.
TEST_F(WebSocketChannelEventInterfaceTest,WriteOverQuotaIsRejected)1807 TEST_F(WebSocketChannelEventInterfaceTest, WriteOverQuotaIsRejected) {
1808 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream));
1809 {
1810 InSequence s;
1811 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1812 EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
1813 EXPECT_CALL(*event_interface_, OnFailChannel("Send quota exceeded"));
1814 }
1815
1816 CreateChannelAndConnectSuccessfully();
1817 channel_->SendFrame(true,
1818 WebSocketFrameHeader::kOpCodeText,
1819 std::vector<char>(kDefaultInitialQuota + 1, 'C'));
1820 }
1821
1822 // If a write fails, the channel is dropped.
TEST_F(WebSocketChannelEventInterfaceTest,FailedWrite)1823 TEST_F(WebSocketChannelEventInterfaceTest, FailedWrite) {
1824 set_stream(make_scoped_ptr(new UnWriteableFakeWebSocketStream));
1825 Checkpoint checkpoint;
1826 {
1827 InSequence s;
1828 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1829 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1830 EXPECT_CALL(checkpoint, Call(1));
1831 EXPECT_CALL(*event_interface_,
1832 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
1833 EXPECT_CALL(checkpoint, Call(2));
1834 }
1835
1836 CreateChannelAndConnectSuccessfully();
1837 checkpoint.Call(1);
1838
1839 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("H"));
1840 checkpoint.Call(2);
1841 }
1842
1843 // OnDropChannel() is called exactly once when StartClosingHandshake() is used.
TEST_F(WebSocketChannelEventInterfaceTest,SendCloseDropsChannel)1844 TEST_F(WebSocketChannelEventInterfaceTest, SendCloseDropsChannel) {
1845 set_stream(make_scoped_ptr(new EchoeyFakeWebSocketStream));
1846 {
1847 InSequence s;
1848 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1849 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1850 EXPECT_CALL(*event_interface_,
1851 OnDropChannel(true, kWebSocketNormalClosure, "Fred"));
1852 }
1853
1854 CreateChannelAndConnectSuccessfully();
1855
1856 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Fred");
1857 base::MessageLoop::current()->RunUntilIdle();
1858 }
1859
1860 // StartClosingHandshake() also works before connection completes, and calls
1861 // OnDropChannel.
TEST_F(WebSocketChannelEventInterfaceTest,CloseDuringConnection)1862 TEST_F(WebSocketChannelEventInterfaceTest, CloseDuringConnection) {
1863 EXPECT_CALL(*event_interface_,
1864 OnDropChannel(false, kWebSocketErrorAbnormalClosure, ""));
1865
1866 CreateChannelAndConnect();
1867 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Joe");
1868 }
1869
1870 // OnDropChannel() is only called once when a write() on the socket triggers a
1871 // connection reset.
TEST_F(WebSocketChannelEventInterfaceTest,OnDropChannelCalledOnce)1872 TEST_F(WebSocketChannelEventInterfaceTest, OnDropChannelCalledOnce) {
1873 set_stream(make_scoped_ptr(new ResetOnWriteFakeWebSocketStream));
1874 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1875 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1876
1877 EXPECT_CALL(*event_interface_,
1878 OnDropChannel(false, kWebSocketErrorAbnormalClosure, ""))
1879 .Times(1);
1880
1881 CreateChannelAndConnectSuccessfully();
1882
1883 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("yt?"));
1884 base::MessageLoop::current()->RunUntilIdle();
1885 }
1886
1887 // When the remote server sends a Close frame with an empty payload,
1888 // WebSocketChannel should report code 1005, kWebSocketErrorNoStatusReceived.
TEST_F(WebSocketChannelEventInterfaceTest,CloseWithNoPayloadGivesStatus1005)1889 TEST_F(WebSocketChannelEventInterfaceTest, CloseWithNoPayloadGivesStatus1005) {
1890 scoped_ptr<ReadableFakeWebSocketStream> stream(
1891 new ReadableFakeWebSocketStream);
1892 static const InitFrame frames[] = {
1893 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
1894 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1895 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1896 ERR_CONNECTION_CLOSED);
1897 set_stream(stream.Pass());
1898 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1899 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1900 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1901 EXPECT_CALL(*event_interface_,
1902 OnDropChannel(true, kWebSocketErrorNoStatusReceived, _));
1903
1904 CreateChannelAndConnectSuccessfully();
1905 }
1906
1907 // A version of the above test with NULL payload.
TEST_F(WebSocketChannelEventInterfaceTest,CloseWithNullPayloadGivesStatus1005)1908 TEST_F(WebSocketChannelEventInterfaceTest,
1909 CloseWithNullPayloadGivesStatus1005) {
1910 scoped_ptr<ReadableFakeWebSocketStream> stream(
1911 new ReadableFakeWebSocketStream);
1912 static const InitFrame frames[] = {
1913 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, NULL}};
1914 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1915 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1916 ERR_CONNECTION_CLOSED);
1917 set_stream(stream.Pass());
1918 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1919 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1920 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1921 EXPECT_CALL(*event_interface_,
1922 OnDropChannel(true, kWebSocketErrorNoStatusReceived, _));
1923
1924 CreateChannelAndConnectSuccessfully();
1925 }
1926
1927 // If ReadFrames() returns ERR_WS_PROTOCOL_ERROR, then the connection must be
1928 // failed.
TEST_F(WebSocketChannelEventInterfaceTest,SyncProtocolErrorGivesStatus1002)1929 TEST_F(WebSocketChannelEventInterfaceTest, SyncProtocolErrorGivesStatus1002) {
1930 scoped_ptr<ReadableFakeWebSocketStream> stream(
1931 new ReadableFakeWebSocketStream);
1932 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1933 ERR_WS_PROTOCOL_ERROR);
1934 set_stream(stream.Pass());
1935 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1936 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1937
1938 EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header"));
1939
1940 CreateChannelAndConnectSuccessfully();
1941 }
1942
1943 // Async version of above test.
TEST_F(WebSocketChannelEventInterfaceTest,AsyncProtocolErrorGivesStatus1002)1944 TEST_F(WebSocketChannelEventInterfaceTest, AsyncProtocolErrorGivesStatus1002) {
1945 scoped_ptr<ReadableFakeWebSocketStream> stream(
1946 new ReadableFakeWebSocketStream);
1947 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1948 ERR_WS_PROTOCOL_ERROR);
1949 set_stream(stream.Pass());
1950 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1951 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1952
1953 EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header"));
1954
1955 CreateChannelAndConnectSuccessfully();
1956 base::MessageLoop::current()->RunUntilIdle();
1957 }
1958
TEST_F(WebSocketChannelEventInterfaceTest,StartHandshakeRequest)1959 TEST_F(WebSocketChannelEventInterfaceTest, StartHandshakeRequest) {
1960 {
1961 InSequence s;
1962 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1963 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1964 EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled());
1965 }
1966
1967 CreateChannelAndConnectSuccessfully();
1968
1969 scoped_ptr<WebSocketHandshakeRequestInfo> request_info(
1970 new WebSocketHandshakeRequestInfo(GURL("ws://www.example.com/"),
1971 base::Time()));
1972 connect_data_.creator.connect_delegate->OnStartOpeningHandshake(
1973 request_info.Pass());
1974
1975 base::MessageLoop::current()->RunUntilIdle();
1976 }
1977
TEST_F(WebSocketChannelEventInterfaceTest,FinishHandshakeRequest)1978 TEST_F(WebSocketChannelEventInterfaceTest, FinishHandshakeRequest) {
1979 {
1980 InSequence s;
1981 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
1982 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1983 EXPECT_CALL(*event_interface_, OnFinishOpeningHandshakeCalled());
1984 }
1985
1986 CreateChannelAndConnectSuccessfully();
1987
1988 scoped_refptr<HttpResponseHeaders> response_headers(
1989 new HttpResponseHeaders(""));
1990 scoped_ptr<WebSocketHandshakeResponseInfo> response_info(
1991 new WebSocketHandshakeResponseInfo(GURL("ws://www.example.com/"),
1992 200,
1993 "OK",
1994 response_headers,
1995 base::Time()));
1996 connect_data_.creator.connect_delegate->OnFinishOpeningHandshake(
1997 response_info.Pass());
1998 base::MessageLoop::current()->RunUntilIdle();
1999 }
2000
TEST_F(WebSocketChannelEventInterfaceTest,FailJustAfterHandshake)2001 TEST_F(WebSocketChannelEventInterfaceTest, FailJustAfterHandshake) {
2002 {
2003 InSequence s;
2004 EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled());
2005 EXPECT_CALL(*event_interface_, OnFinishOpeningHandshakeCalled());
2006 EXPECT_CALL(*event_interface_, OnFailChannel("bye"));
2007 }
2008
2009 CreateChannelAndConnect();
2010
2011 WebSocketStream::ConnectDelegate* connect_delegate =
2012 connect_data_.creator.connect_delegate.get();
2013 GURL url("ws://www.example.com/");
2014 scoped_ptr<WebSocketHandshakeRequestInfo> request_info(
2015 new WebSocketHandshakeRequestInfo(url, base::Time()));
2016 scoped_refptr<HttpResponseHeaders> response_headers(
2017 new HttpResponseHeaders(""));
2018 scoped_ptr<WebSocketHandshakeResponseInfo> response_info(
2019 new WebSocketHandshakeResponseInfo(url,
2020 200,
2021 "OK",
2022 response_headers,
2023 base::Time()));
2024 connect_delegate->OnStartOpeningHandshake(request_info.Pass());
2025 connect_delegate->OnFinishOpeningHandshake(response_info.Pass());
2026
2027 connect_delegate->OnFailure("bye");
2028 base::MessageLoop::current()->RunUntilIdle();
2029 }
2030
2031 // Any frame after close is invalid. This test uses a Text frame. See also
2032 // test "PingAfterCloseIfRejected".
TEST_F(WebSocketChannelEventInterfaceTest,DataAfterCloseIsRejected)2033 TEST_F(WebSocketChannelEventInterfaceTest, DataAfterCloseIsRejected) {
2034 scoped_ptr<ReadableFakeWebSocketStream> stream(
2035 new ReadableFakeWebSocketStream);
2036 static const InitFrame frames[] = {
2037 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
2038 CLOSE_DATA(NORMAL_CLOSURE, "OK")},
2039 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "Payload"}};
2040 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2041 set_stream(stream.Pass());
2042 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2043 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2044
2045 {
2046 InSequence s;
2047 EXPECT_CALL(*event_interface_, OnClosingHandshake());
2048 EXPECT_CALL(*event_interface_,
2049 OnFailChannel("Data frame received after close"));
2050 }
2051
2052 CreateChannelAndConnectSuccessfully();
2053 }
2054
2055 // A Close frame with a one-byte payload elicits a specific console error
2056 // message.
TEST_F(WebSocketChannelEventInterfaceTest,OneByteClosePayloadMessage)2057 TEST_F(WebSocketChannelEventInterfaceTest, OneByteClosePayloadMessage) {
2058 scoped_ptr<ReadableFakeWebSocketStream> stream(
2059 new ReadableFakeWebSocketStream);
2060 static const InitFrame frames[] = {
2061 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, "\x03"}};
2062 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2063 set_stream(stream.Pass());
2064 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2065 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2066 EXPECT_CALL(
2067 *event_interface_,
2068 OnFailChannel(
2069 "Received a broken close frame containing an invalid size body."));
2070
2071 CreateChannelAndConnectSuccessfully();
2072 }
2073
2074 // A Close frame with a reserved status code also elicits a specific console
2075 // error message.
TEST_F(WebSocketChannelEventInterfaceTest,ClosePayloadReservedStatusMessage)2076 TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadReservedStatusMessage) {
2077 scoped_ptr<ReadableFakeWebSocketStream> stream(
2078 new ReadableFakeWebSocketStream);
2079 static const InitFrame frames[] = {
2080 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2081 NOT_MASKED, CLOSE_DATA(ABNORMAL_CLOSURE, "Not valid on wire")}};
2082 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2083 set_stream(stream.Pass());
2084 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2085 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2086 EXPECT_CALL(
2087 *event_interface_,
2088 OnFailChannel(
2089 "Received a broken close frame containing a reserved status code."));
2090
2091 CreateChannelAndConnectSuccessfully();
2092 }
2093
2094 // A Close frame with invalid UTF-8 also elicits a specific console error
2095 // message.
TEST_F(WebSocketChannelEventInterfaceTest,ClosePayloadInvalidReason)2096 TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadInvalidReason) {
2097 scoped_ptr<ReadableFakeWebSocketStream> stream(
2098 new ReadableFakeWebSocketStream);
2099 static const InitFrame frames[] = {
2100 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2101 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}};
2102 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2103 set_stream(stream.Pass());
2104 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2105 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2106 EXPECT_CALL(
2107 *event_interface_,
2108 OnFailChannel(
2109 "Received a broken close frame containing invalid UTF-8."));
2110
2111 CreateChannelAndConnectSuccessfully();
2112 }
2113
2114 // The reserved bits must all be clear on received frames. Extensions should
2115 // clear the bits when they are set correctly before passing on the frame.
TEST_F(WebSocketChannelEventInterfaceTest,ReservedBitsMustNotBeSet)2116 TEST_F(WebSocketChannelEventInterfaceTest, ReservedBitsMustNotBeSet) {
2117 scoped_ptr<ReadableFakeWebSocketStream> stream(
2118 new ReadableFakeWebSocketStream);
2119 static const InitFrame frames[] = {
2120 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2121 NOT_MASKED, "sakana"}};
2122 // It is not worth adding support for reserved bits to InitFrame just for this
2123 // one test, so set the bit manually.
2124 ScopedVector<WebSocketFrame> raw_frames = CreateFrameVector(frames);
2125 raw_frames[0]->header.reserved1 = true;
2126 stream->PrepareRawReadFrames(
2127 ReadableFakeWebSocketStream::SYNC, OK, raw_frames.Pass());
2128 set_stream(stream.Pass());
2129 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2130 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2131 EXPECT_CALL(*event_interface_,
2132 OnFailChannel(
2133 "One or more reserved bits are on: reserved1 = 1, "
2134 "reserved2 = 0, reserved3 = 0"));
2135
2136 CreateChannelAndConnectSuccessfully();
2137 }
2138
2139 // The closing handshake times out and sends an OnDropChannel event if no
2140 // response to the client Close message is received.
TEST_F(WebSocketChannelEventInterfaceTest,ClientInitiatedClosingHandshakeTimesOut)2141 TEST_F(WebSocketChannelEventInterfaceTest,
2142 ClientInitiatedClosingHandshakeTimesOut) {
2143 scoped_ptr<ReadableFakeWebSocketStream> stream(
2144 new ReadableFakeWebSocketStream);
2145 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
2146 ERR_IO_PENDING);
2147 set_stream(stream.Pass());
2148 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2149 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2150 // This checkpoint object verifies that the OnDropChannel message comes after
2151 // the timeout.
2152 Checkpoint checkpoint;
2153 TestClosure completion;
2154 {
2155 InSequence s;
2156 EXPECT_CALL(checkpoint, Call(1));
2157 EXPECT_CALL(*event_interface_,
2158 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _))
2159 .WillOnce(InvokeClosureReturnDeleted(completion.closure()));
2160 }
2161 CreateChannelAndConnectSuccessfully();
2162 // OneShotTimer is not very friendly to testing; there is no apparent way to
2163 // set an expectation on it. Instead the tests need to infer that the timeout
2164 // was fired by the behaviour of the WebSocketChannel object.
2165 channel_->SetClosingHandshakeTimeoutForTesting(
2166 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
2167 channel_->StartClosingHandshake(kWebSocketNormalClosure, "");
2168 checkpoint.Call(1);
2169 completion.WaitForResult();
2170 }
2171
2172 // The closing handshake times out and sends an OnDropChannel event if a Close
2173 // message is received but the connection isn't closed by the remote host.
TEST_F(WebSocketChannelEventInterfaceTest,ServerInitiatedClosingHandshakeTimesOut)2174 TEST_F(WebSocketChannelEventInterfaceTest,
2175 ServerInitiatedClosingHandshakeTimesOut) {
2176 scoped_ptr<ReadableFakeWebSocketStream> stream(
2177 new ReadableFakeWebSocketStream);
2178 static const InitFrame frames[] = {
2179 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2180 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
2181 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
2182 set_stream(stream.Pass());
2183 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2184 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2185 Checkpoint checkpoint;
2186 TestClosure completion;
2187 {
2188 InSequence s;
2189 EXPECT_CALL(checkpoint, Call(1));
2190 EXPECT_CALL(*event_interface_, OnClosingHandshake());
2191 EXPECT_CALL(*event_interface_,
2192 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _))
2193 .WillOnce(InvokeClosureReturnDeleted(completion.closure()));
2194 }
2195 CreateChannelAndConnectSuccessfully();
2196 channel_->SetClosingHandshakeTimeoutForTesting(
2197 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
2198 checkpoint.Call(1);
2199 completion.WaitForResult();
2200 }
2201
2202 // The renderer should provide us with some quota immediately, and then
2203 // WebSocketChannel calls ReadFrames as soon as the stream is available.
TEST_F(WebSocketChannelStreamTest,FlowControlEarly)2204 TEST_F(WebSocketChannelStreamTest, FlowControlEarly) {
2205 Checkpoint checkpoint;
2206 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2207 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2208 {
2209 InSequence s;
2210 EXPECT_CALL(checkpoint, Call(1));
2211 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2212 .WillOnce(Return(ERR_IO_PENDING));
2213 EXPECT_CALL(checkpoint, Call(2));
2214 }
2215
2216 set_stream(mock_stream_.Pass());
2217 CreateChannelAndConnect();
2218 channel_->SendFlowControl(kPlentyOfQuota);
2219 checkpoint.Call(1);
2220 connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
2221 checkpoint.Call(2);
2222 }
2223
2224 // If for some reason the connect succeeds before the renderer sends us quota,
2225 // we shouldn't call ReadFrames() immediately.
2226 // TODO(ricea): Actually we should call ReadFrames() with a small limit so we
2227 // can still handle control frames. This should be done once we have any API to
2228 // expose quota to the lower levels.
TEST_F(WebSocketChannelStreamTest,FlowControlLate)2229 TEST_F(WebSocketChannelStreamTest, FlowControlLate) {
2230 Checkpoint checkpoint;
2231 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2232 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2233 {
2234 InSequence s;
2235 EXPECT_CALL(checkpoint, Call(1));
2236 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2237 .WillOnce(Return(ERR_IO_PENDING));
2238 EXPECT_CALL(checkpoint, Call(2));
2239 }
2240
2241 set_stream(mock_stream_.Pass());
2242 CreateChannelAndConnect();
2243 connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
2244 checkpoint.Call(1);
2245 channel_->SendFlowControl(kPlentyOfQuota);
2246 checkpoint.Call(2);
2247 }
2248
2249 // We should stop calling ReadFrames() when all quota is used.
TEST_F(WebSocketChannelStreamTest,FlowControlStopsReadFrames)2250 TEST_F(WebSocketChannelStreamTest, FlowControlStopsReadFrames) {
2251 static const InitFrame frames[] = {
2252 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
2253
2254 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2255 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2256 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2257 .WillOnce(ReturnFrames(&frames));
2258
2259 set_stream(mock_stream_.Pass());
2260 CreateChannelAndConnect();
2261 channel_->SendFlowControl(4);
2262 connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
2263 }
2264
2265 // Providing extra quota causes ReadFrames() to be called again.
TEST_F(WebSocketChannelStreamTest,FlowControlStartsWithMoreQuota)2266 TEST_F(WebSocketChannelStreamTest, FlowControlStartsWithMoreQuota) {
2267 static const InitFrame frames[] = {
2268 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
2269 Checkpoint checkpoint;
2270
2271 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2272 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2273 {
2274 InSequence s;
2275 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2276 .WillOnce(ReturnFrames(&frames));
2277 EXPECT_CALL(checkpoint, Call(1));
2278 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2279 .WillOnce(Return(ERR_IO_PENDING));
2280 }
2281
2282 set_stream(mock_stream_.Pass());
2283 CreateChannelAndConnect();
2284 channel_->SendFlowControl(4);
2285 connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
2286 checkpoint.Call(1);
2287 channel_->SendFlowControl(4);
2288 }
2289
2290 // ReadFrames() isn't called again until all pending data has been passed to
2291 // the renderer.
TEST_F(WebSocketChannelStreamTest,ReadFramesNotCalledUntilQuotaAvailable)2292 TEST_F(WebSocketChannelStreamTest, ReadFramesNotCalledUntilQuotaAvailable) {
2293 static const InitFrame frames[] = {
2294 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
2295 Checkpoint checkpoint;
2296
2297 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2298 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2299 {
2300 InSequence s;
2301 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2302 .WillOnce(ReturnFrames(&frames));
2303 EXPECT_CALL(checkpoint, Call(1));
2304 EXPECT_CALL(checkpoint, Call(2));
2305 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2306 .WillOnce(Return(ERR_IO_PENDING));
2307 }
2308
2309 set_stream(mock_stream_.Pass());
2310 CreateChannelAndConnect();
2311 channel_->SendFlowControl(2);
2312 connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
2313 checkpoint.Call(1);
2314 channel_->SendFlowControl(2);
2315 checkpoint.Call(2);
2316 channel_->SendFlowControl(2);
2317 }
2318
2319 // A message that needs to be split into frames to fit within quota should
2320 // maintain correct semantics.
TEST_F(WebSocketChannelFlowControlTest,SingleFrameMessageSplitSync)2321 TEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitSync) {
2322 scoped_ptr<ReadableFakeWebSocketStream> stream(
2323 new ReadableFakeWebSocketStream);
2324 static const InitFrame frames[] = {
2325 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
2326 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2327 set_stream(stream.Pass());
2328 {
2329 InSequence s;
2330 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2331 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2332 EXPECT_CALL(
2333 *event_interface_,
2334 OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("FO")));
2335 EXPECT_CALL(
2336 *event_interface_,
2337 OnDataFrame(
2338 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("U")));
2339 EXPECT_CALL(
2340 *event_interface_,
2341 OnDataFrame(
2342 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("R")));
2343 }
2344
2345 CreateChannelAndConnectWithQuota(2);
2346 channel_->SendFlowControl(1);
2347 channel_->SendFlowControl(1);
2348 }
2349
2350 // The code path for async messages is slightly different, so test it
2351 // separately.
TEST_F(WebSocketChannelFlowControlTest,SingleFrameMessageSplitAsync)2352 TEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitAsync) {
2353 scoped_ptr<ReadableFakeWebSocketStream> stream(
2354 new ReadableFakeWebSocketStream);
2355 static const InitFrame frames[] = {
2356 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
2357 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
2358 set_stream(stream.Pass());
2359 Checkpoint checkpoint;
2360 {
2361 InSequence s;
2362 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2363 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2364 EXPECT_CALL(checkpoint, Call(1));
2365 EXPECT_CALL(
2366 *event_interface_,
2367 OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("FO")));
2368 EXPECT_CALL(checkpoint, Call(2));
2369 EXPECT_CALL(
2370 *event_interface_,
2371 OnDataFrame(
2372 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("U")));
2373 EXPECT_CALL(checkpoint, Call(3));
2374 EXPECT_CALL(
2375 *event_interface_,
2376 OnDataFrame(
2377 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("R")));
2378 }
2379
2380 CreateChannelAndConnectWithQuota(2);
2381 checkpoint.Call(1);
2382 base::MessageLoop::current()->RunUntilIdle();
2383 checkpoint.Call(2);
2384 channel_->SendFlowControl(1);
2385 checkpoint.Call(3);
2386 channel_->SendFlowControl(1);
2387 }
2388
2389 // A message split into multiple frames which is further split due to quota
2390 // restrictions should stil be correct.
2391 // TODO(ricea): The message ends up split into more frames than are strictly
2392 // necessary. The complexity/performance tradeoffs here need further
2393 // examination.
TEST_F(WebSocketChannelFlowControlTest,MultipleFrameSplit)2394 TEST_F(WebSocketChannelFlowControlTest, MultipleFrameSplit) {
2395 scoped_ptr<ReadableFakeWebSocketStream> stream(
2396 new ReadableFakeWebSocketStream);
2397 static const InitFrame frames[] = {
2398 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2399 NOT_MASKED, "FIRST FRAME IS 25 BYTES. "},
2400 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2401 NOT_MASKED, "SECOND FRAME IS 26 BYTES. "},
2402 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2403 NOT_MASKED, "FINAL FRAME IS 24 BYTES."}};
2404 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2405 set_stream(stream.Pass());
2406 {
2407 InSequence s;
2408 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2409 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2410 EXPECT_CALL(*event_interface_,
2411 OnDataFrame(false,
2412 WebSocketFrameHeader::kOpCodeText,
2413 AsVector("FIRST FRAME IS")));
2414 EXPECT_CALL(*event_interface_,
2415 OnDataFrame(false,
2416 WebSocketFrameHeader::kOpCodeContinuation,
2417 AsVector(" 25 BYTES. ")));
2418 EXPECT_CALL(*event_interface_,
2419 OnDataFrame(false,
2420 WebSocketFrameHeader::kOpCodeContinuation,
2421 AsVector("SECOND FRAME IS 26 BYTES. ")));
2422 EXPECT_CALL(*event_interface_,
2423 OnDataFrame(false,
2424 WebSocketFrameHeader::kOpCodeContinuation,
2425 AsVector("FINAL ")));
2426 EXPECT_CALL(*event_interface_,
2427 OnDataFrame(true,
2428 WebSocketFrameHeader::kOpCodeContinuation,
2429 AsVector("FRAME IS 24 BYTES.")));
2430 }
2431 CreateChannelAndConnectWithQuota(14);
2432 channel_->SendFlowControl(43);
2433 channel_->SendFlowControl(32);
2434 }
2435
2436 // An empty message handled when we are out of quota must not be delivered
2437 // out-of-order with respect to other messages.
TEST_F(WebSocketChannelFlowControlTest,EmptyMessageNoQuota)2438 TEST_F(WebSocketChannelFlowControlTest, EmptyMessageNoQuota) {
2439 scoped_ptr<ReadableFakeWebSocketStream> stream(
2440 new ReadableFakeWebSocketStream);
2441 static const InitFrame frames[] = {
2442 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2443 NOT_MASKED, "FIRST MESSAGE"},
2444 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2445 NOT_MASKED, NULL},
2446 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2447 NOT_MASKED, "THIRD MESSAGE"}};
2448 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2449 set_stream(stream.Pass());
2450 {
2451 InSequence s;
2452 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2453 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2454 EXPECT_CALL(*event_interface_,
2455 OnDataFrame(false,
2456 WebSocketFrameHeader::kOpCodeText,
2457 AsVector("FIRST ")));
2458 EXPECT_CALL(*event_interface_,
2459 OnDataFrame(true,
2460 WebSocketFrameHeader::kOpCodeContinuation,
2461 AsVector("MESSAGE")));
2462 EXPECT_CALL(*event_interface_,
2463 OnDataFrame(true,
2464 WebSocketFrameHeader::kOpCodeText,
2465 AsVector("")));
2466 EXPECT_CALL(*event_interface_,
2467 OnDataFrame(true,
2468 WebSocketFrameHeader::kOpCodeText,
2469 AsVector("THIRD MESSAGE")));
2470 }
2471
2472 CreateChannelAndConnectWithQuota(6);
2473 channel_->SendFlowControl(128);
2474 }
2475
2476 // RFC6455 5.1 "a client MUST mask all frames that it sends to the server".
2477 // WebSocketChannel actually only sets the mask bit in the header, it doesn't
2478 // perform masking itself (not all transports actually use masking).
TEST_F(WebSocketChannelStreamTest,SentFramesAreMasked)2479 TEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) {
2480 static const InitFrame expected[] = {
2481 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2482 MASKED, "NEEDS MASKING"}};
2483 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2484 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2485 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2486 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2487 .WillOnce(Return(OK));
2488
2489 CreateChannelAndConnectSuccessfully();
2490 channel_->SendFrame(
2491 true, WebSocketFrameHeader::kOpCodeText, AsVector("NEEDS MASKING"));
2492 }
2493
2494 // RFC6455 5.5.1 "The application MUST NOT send any more data frames after
2495 // sending a Close frame."
TEST_F(WebSocketChannelStreamTest,NothingIsSentAfterClose)2496 TEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) {
2497 static const InitFrame expected[] = {
2498 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2499 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
2500 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2501 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2502 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2503 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2504 .WillOnce(Return(OK));
2505
2506 CreateChannelAndConnectSuccessfully();
2507 channel_->StartClosingHandshake(1000, "Success");
2508 channel_->SendFrame(
2509 true, WebSocketFrameHeader::kOpCodeText, AsVector("SHOULD BE IGNORED"));
2510 }
2511
2512 // RFC6455 5.5.1 "If an endpoint receives a Close frame and did not previously
2513 // send a Close frame, the endpoint MUST send a Close frame in response."
TEST_F(WebSocketChannelStreamTest,CloseIsEchoedBack)2514 TEST_F(WebSocketChannelStreamTest, CloseIsEchoedBack) {
2515 static const InitFrame frames[] = {
2516 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2517 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
2518 static const InitFrame expected[] = {
2519 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2520 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
2521 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2522 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2523 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2524 .WillOnce(ReturnFrames(&frames))
2525 .WillRepeatedly(Return(ERR_IO_PENDING));
2526 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2527 .WillOnce(Return(OK));
2528
2529 CreateChannelAndConnectSuccessfully();
2530 }
2531
2532 // The converse of the above case; after sending a Close frame, we should not
2533 // send another one.
TEST_F(WebSocketChannelStreamTest,CloseOnlySentOnce)2534 TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
2535 static const InitFrame expected[] = {
2536 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2537 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
2538 static const InitFrame frames_init[] = {
2539 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2540 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
2541
2542 // We store the parameters that were passed to ReadFrames() so that we can
2543 // call them explicitly later.
2544 CompletionCallback read_callback;
2545 ScopedVector<WebSocketFrame>* frames = NULL;
2546
2547 // These are not interesting.
2548 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2549 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2550
2551 // Use a checkpoint to make the ordering of events clearer.
2552 Checkpoint checkpoint;
2553 {
2554 InSequence s;
2555 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2556 .WillOnce(DoAll(SaveArg<0>(&frames),
2557 SaveArg<1>(&read_callback),
2558 Return(ERR_IO_PENDING)));
2559 EXPECT_CALL(checkpoint, Call(1));
2560 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2561 .WillOnce(Return(OK));
2562 EXPECT_CALL(checkpoint, Call(2));
2563 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2564 .WillOnce(Return(ERR_IO_PENDING));
2565 EXPECT_CALL(checkpoint, Call(3));
2566 // WriteFrames() must not be called again. GoogleMock will ensure that the
2567 // test fails if it is.
2568 }
2569
2570 CreateChannelAndConnectSuccessfully();
2571 checkpoint.Call(1);
2572 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Close");
2573 checkpoint.Call(2);
2574
2575 *frames = CreateFrameVector(frames_init);
2576 read_callback.Run(OK);
2577 checkpoint.Call(3);
2578 }
2579
2580 // Invalid close status codes should not be sent on the network.
TEST_F(WebSocketChannelStreamTest,InvalidCloseStatusCodeNotSent)2581 TEST_F(WebSocketChannelStreamTest, InvalidCloseStatusCodeNotSent) {
2582 static const InitFrame expected[] = {
2583 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2584 MASKED, CLOSE_DATA(SERVER_ERROR, "")}};
2585
2586 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2587 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2588 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2589 .WillOnce(Return(ERR_IO_PENDING));
2590
2591 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
2592
2593 CreateChannelAndConnectSuccessfully();
2594 channel_->StartClosingHandshake(999, "");
2595 }
2596
2597 // A Close frame with a reason longer than 123 bytes cannot be sent on the
2598 // network.
TEST_F(WebSocketChannelStreamTest,LongCloseReasonNotSent)2599 TEST_F(WebSocketChannelStreamTest, LongCloseReasonNotSent) {
2600 static const InitFrame expected[] = {
2601 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2602 MASKED, CLOSE_DATA(SERVER_ERROR, "")}};
2603
2604 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2605 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2606 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2607 .WillOnce(Return(ERR_IO_PENDING));
2608
2609 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
2610
2611 CreateChannelAndConnectSuccessfully();
2612 channel_->StartClosingHandshake(1000, std::string(124, 'A'));
2613 }
2614
2615 // We generate code 1005, kWebSocketErrorNoStatusReceived, when there is no
2616 // status in the Close message from the other side. Code 1005 is not allowed to
2617 // appear on the wire, so we should not echo it back. See test
2618 // CloseWithNoPayloadGivesStatus1005, above, for confirmation that code 1005 is
2619 // correctly generated internally.
TEST_F(WebSocketChannelStreamTest,Code1005IsNotEchoed)2620 TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoed) {
2621 static const InitFrame frames[] = {
2622 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
2623 static const InitFrame expected[] = {
2624 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
2625 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2626 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2627 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2628 .WillOnce(ReturnFrames(&frames))
2629 .WillRepeatedly(Return(ERR_IO_PENDING));
2630 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2631 .WillOnce(Return(OK));
2632
2633 CreateChannelAndConnectSuccessfully();
2634 }
2635
TEST_F(WebSocketChannelStreamTest,Code1005IsNotEchoedNull)2636 TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoedNull) {
2637 static const InitFrame frames[] = {
2638 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, NULL}};
2639 static const InitFrame expected[] = {
2640 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
2641 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2642 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2643 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2644 .WillOnce(ReturnFrames(&frames))
2645 .WillRepeatedly(Return(ERR_IO_PENDING));
2646 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2647 .WillOnce(Return(OK));
2648
2649 CreateChannelAndConnectSuccessfully();
2650 }
2651
2652 // Receiving an invalid UTF-8 payload in a Close frame causes us to fail the
2653 // connection.
TEST_F(WebSocketChannelStreamTest,CloseFrameInvalidUtf8)2654 TEST_F(WebSocketChannelStreamTest, CloseFrameInvalidUtf8) {
2655 static const InitFrame frames[] = {
2656 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2657 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}};
2658 static const InitFrame expected[] = {
2659 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2660 MASKED, CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in Close frame")}};
2661
2662 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2663 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2664 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2665 .WillOnce(ReturnFrames(&frames))
2666 .WillRepeatedly(Return(ERR_IO_PENDING));
2667 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2668 .WillOnce(Return(OK));
2669 EXPECT_CALL(*mock_stream_, Close());
2670
2671 CreateChannelAndConnectSuccessfully();
2672 }
2673
2674 // RFC6455 5.5.2 "Upon receipt of a Ping frame, an endpoint MUST send a Pong
2675 // frame in response"
2676 // 5.5.3 "A Pong frame sent in response to a Ping frame must have identical
2677 // "Application data" as found in the message body of the Ping frame being
2678 // replied to."
TEST_F(WebSocketChannelStreamTest,PingRepliedWithPong)2679 TEST_F(WebSocketChannelStreamTest, PingRepliedWithPong) {
2680 static const InitFrame frames[] = {
2681 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
2682 NOT_MASKED, "Application data"}};
2683 static const InitFrame expected[] = {
2684 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
2685 MASKED, "Application data"}};
2686 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2687 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2688 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2689 .WillOnce(ReturnFrames(&frames))
2690 .WillRepeatedly(Return(ERR_IO_PENDING));
2691 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2692 .WillOnce(Return(OK));
2693
2694 CreateChannelAndConnectSuccessfully();
2695 }
2696
2697 // A ping with a NULL payload should be responded to with a Pong with a NULL
2698 // payload.
TEST_F(WebSocketChannelStreamTest,NullPingRepliedWithNullPong)2699 TEST_F(WebSocketChannelStreamTest, NullPingRepliedWithNullPong) {
2700 static const InitFrame frames[] = {
2701 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, NULL}};
2702 static const InitFrame expected[] = {
2703 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, NULL}};
2704 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2705 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2706 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2707 .WillOnce(ReturnFrames(&frames))
2708 .WillRepeatedly(Return(ERR_IO_PENDING));
2709 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2710 .WillOnce(Return(OK));
2711
2712 CreateChannelAndConnectSuccessfully();
2713 }
2714
TEST_F(WebSocketChannelStreamTest,PongInTheMiddleOfDataMessage)2715 TEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) {
2716 static const InitFrame frames[] = {
2717 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
2718 NOT_MASKED, "Application data"}};
2719 static const InitFrame expected1[] = {
2720 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
2721 static const InitFrame expected2[] = {
2722 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
2723 MASKED, "Application data"}};
2724 static const InitFrame expected3[] = {
2725 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2726 MASKED, "World"}};
2727 ScopedVector<WebSocketFrame>* read_frames;
2728 CompletionCallback read_callback;
2729 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2730 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2731 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2732 .WillOnce(DoAll(SaveArg<0>(&read_frames),
2733 SaveArg<1>(&read_callback),
2734 Return(ERR_IO_PENDING)))
2735 .WillRepeatedly(Return(ERR_IO_PENDING));
2736 {
2737 InSequence s;
2738
2739 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
2740 .WillOnce(Return(OK));
2741 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
2742 .WillOnce(Return(OK));
2743 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected3), _))
2744 .WillOnce(Return(OK));
2745 }
2746
2747 CreateChannelAndConnectSuccessfully();
2748 channel_->SendFrame(
2749 false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello "));
2750 *read_frames = CreateFrameVector(frames);
2751 read_callback.Run(OK);
2752 channel_->SendFrame(
2753 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("World"));
2754 }
2755
2756 // WriteFrames() may not be called until the previous write has completed.
2757 // WebSocketChannel must buffer writes that happen in the meantime.
TEST_F(WebSocketChannelStreamTest,WriteFramesOneAtATime)2758 TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) {
2759 static const InitFrame expected1[] = {
2760 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
2761 static const InitFrame expected2[] = {
2762 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "World"}};
2763 CompletionCallback write_callback;
2764 Checkpoint checkpoint;
2765
2766 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2767 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2768 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2769 {
2770 InSequence s;
2771 EXPECT_CALL(checkpoint, Call(1));
2772 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
2773 .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
2774 EXPECT_CALL(checkpoint, Call(2));
2775 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
2776 .WillOnce(Return(ERR_IO_PENDING));
2777 EXPECT_CALL(checkpoint, Call(3));
2778 }
2779
2780 CreateChannelAndConnectSuccessfully();
2781 checkpoint.Call(1);
2782 channel_->SendFrame(
2783 false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello "));
2784 channel_->SendFrame(
2785 true, WebSocketFrameHeader::kOpCodeText, AsVector("World"));
2786 checkpoint.Call(2);
2787 write_callback.Run(OK);
2788 checkpoint.Call(3);
2789 }
2790
2791 // WebSocketChannel must buffer frames while it is waiting for a write to
2792 // complete, and then send them in a single batch. The batching behaviour is
2793 // important to get good throughput in the "many small messages" case.
TEST_F(WebSocketChannelStreamTest,WaitingMessagesAreBatched)2794 TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) {
2795 static const char input_letters[] = "Hello";
2796 static const InitFrame expected1[] = {
2797 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "H"}};
2798 static const InitFrame expected2[] = {
2799 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "e"},
2800 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
2801 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
2802 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "o"}};
2803 CompletionCallback write_callback;
2804
2805 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2806 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2807 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2808 {
2809 InSequence s;
2810 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
2811 .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
2812 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
2813 .WillOnce(Return(ERR_IO_PENDING));
2814 }
2815
2816 CreateChannelAndConnectSuccessfully();
2817 for (size_t i = 0; i < strlen(input_letters); ++i) {
2818 channel_->SendFrame(true,
2819 WebSocketFrameHeader::kOpCodeText,
2820 std::vector<char>(1, input_letters[i]));
2821 }
2822 write_callback.Run(OK);
2823 }
2824
2825 // When the renderer sends more on a channel than it has quota for, we send the
2826 // remote server a kWebSocketErrorGoingAway error code.
TEST_F(WebSocketChannelStreamTest,SendGoingAwayOnRendererQuotaExceeded)2827 TEST_F(WebSocketChannelStreamTest, SendGoingAwayOnRendererQuotaExceeded) {
2828 static const InitFrame expected[] = {
2829 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2830 MASKED, CLOSE_DATA(GOING_AWAY, "")}};
2831 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2832 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2833 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2834 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2835 .WillOnce(Return(OK));
2836 EXPECT_CALL(*mock_stream_, Close());
2837
2838 CreateChannelAndConnectSuccessfully();
2839 channel_->SendFrame(true,
2840 WebSocketFrameHeader::kOpCodeText,
2841 std::vector<char>(kDefaultInitialQuota + 1, 'C'));
2842 }
2843
2844 // For convenience, most of these tests use Text frames. However, the WebSocket
2845 // protocol also has Binary frames and those need to be 8-bit clean. For the
2846 // sake of completeness, this test verifies that they are.
TEST_F(WebSocketChannelStreamTest,WrittenBinaryFramesAre8BitClean)2847 TEST_F(WebSocketChannelStreamTest, WrittenBinaryFramesAre8BitClean) {
2848 ScopedVector<WebSocketFrame>* frames = NULL;
2849
2850 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2851 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2852 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2853 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
2854 .WillOnce(DoAll(SaveArg<0>(&frames), Return(ERR_IO_PENDING)));
2855
2856 CreateChannelAndConnectSuccessfully();
2857 channel_->SendFrame(
2858 true,
2859 WebSocketFrameHeader::kOpCodeBinary,
2860 std::vector<char>(kBinaryBlob, kBinaryBlob + kBinaryBlobSize));
2861 ASSERT_TRUE(frames != NULL);
2862 ASSERT_EQ(1U, frames->size());
2863 const WebSocketFrame* out_frame = (*frames)[0];
2864 EXPECT_EQ(kBinaryBlobSize, out_frame->header.payload_length);
2865 ASSERT_TRUE(out_frame->data);
2866 EXPECT_EQ(0, memcmp(kBinaryBlob, out_frame->data->data(), kBinaryBlobSize));
2867 }
2868
2869 // Test the read path for 8-bit cleanliness as well.
TEST_F(WebSocketChannelEventInterfaceTest,ReadBinaryFramesAre8BitClean)2870 TEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) {
2871 scoped_ptr<WebSocketFrame> frame(
2872 new WebSocketFrame(WebSocketFrameHeader::kOpCodeBinary));
2873 WebSocketFrameHeader& frame_header = frame->header;
2874 frame_header.final = true;
2875 frame_header.payload_length = kBinaryBlobSize;
2876 frame->data = new IOBuffer(kBinaryBlobSize);
2877 memcpy(frame->data->data(), kBinaryBlob, kBinaryBlobSize);
2878 ScopedVector<WebSocketFrame> frames;
2879 frames.push_back(frame.release());
2880 scoped_ptr<ReadableFakeWebSocketStream> stream(
2881 new ReadableFakeWebSocketStream);
2882 stream->PrepareRawReadFrames(
2883 ReadableFakeWebSocketStream::SYNC, OK, frames.Pass());
2884 set_stream(stream.Pass());
2885 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
2886 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2887 EXPECT_CALL(*event_interface_,
2888 OnDataFrame(true,
2889 WebSocketFrameHeader::kOpCodeBinary,
2890 std::vector<char>(kBinaryBlob,
2891 kBinaryBlob + kBinaryBlobSize)));
2892
2893 CreateChannelAndConnectSuccessfully();
2894 }
2895
2896 // Invalid UTF-8 is not permitted in Text frames.
TEST_F(WebSocketChannelSendUtf8Test,InvalidUtf8Rejected)2897 TEST_F(WebSocketChannelSendUtf8Test, InvalidUtf8Rejected) {
2898 EXPECT_CALL(
2899 *event_interface_,
2900 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2901
2902 CreateChannelAndConnectSuccessfully();
2903
2904 channel_->SendFrame(
2905 true, WebSocketFrameHeader::kOpCodeText, AsVector("\xff"));
2906 }
2907
2908 // A Text message cannot end with a partial UTF-8 character.
TEST_F(WebSocketChannelSendUtf8Test,IncompleteCharacterInFinalFrame)2909 TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInFinalFrame) {
2910 EXPECT_CALL(
2911 *event_interface_,
2912 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2913
2914 CreateChannelAndConnectSuccessfully();
2915
2916 channel_->SendFrame(
2917 true, WebSocketFrameHeader::kOpCodeText, AsVector("\xc2"));
2918 }
2919
2920 // A non-final Text frame may end with a partial UTF-8 character (compare to
2921 // previous test).
TEST_F(WebSocketChannelSendUtf8Test,IncompleteCharacterInNonFinalFrame)2922 TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInNonFinalFrame) {
2923 CreateChannelAndConnectSuccessfully();
2924
2925 channel_->SendFrame(
2926 false, WebSocketFrameHeader::kOpCodeText, AsVector("\xc2"));
2927 }
2928
2929 // UTF-8 parsing context must be retained between frames.
TEST_F(WebSocketChannelSendUtf8Test,ValidCharacterSplitBetweenFrames)2930 TEST_F(WebSocketChannelSendUtf8Test, ValidCharacterSplitBetweenFrames) {
2931 CreateChannelAndConnectSuccessfully();
2932
2933 channel_->SendFrame(
2934 false, WebSocketFrameHeader::kOpCodeText, AsVector("\xf1"));
2935 channel_->SendFrame(true,
2936 WebSocketFrameHeader::kOpCodeContinuation,
2937 AsVector("\x80\xa0\xbf"));
2938 }
2939
2940 // Similarly, an invalid character should be detected even if split.
TEST_F(WebSocketChannelSendUtf8Test,InvalidCharacterSplit)2941 TEST_F(WebSocketChannelSendUtf8Test, InvalidCharacterSplit) {
2942 EXPECT_CALL(
2943 *event_interface_,
2944 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2945
2946 CreateChannelAndConnectSuccessfully();
2947
2948 channel_->SendFrame(
2949 false, WebSocketFrameHeader::kOpCodeText, AsVector("\xe1"));
2950 channel_->SendFrame(true,
2951 WebSocketFrameHeader::kOpCodeContinuation,
2952 AsVector("\x80\xa0\xbf"));
2953 }
2954
2955 // An invalid character must be detected in continuation frames.
TEST_F(WebSocketChannelSendUtf8Test,InvalidByteInContinuation)2956 TEST_F(WebSocketChannelSendUtf8Test, InvalidByteInContinuation) {
2957 EXPECT_CALL(
2958 *event_interface_,
2959 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2960
2961 CreateChannelAndConnectSuccessfully();
2962
2963 channel_->SendFrame(
2964 false, WebSocketFrameHeader::kOpCodeText, AsVector("foo"));
2965 channel_->SendFrame(
2966 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("bar"));
2967 channel_->SendFrame(
2968 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("\xff"));
2969 }
2970
2971 // However, continuation frames of a Binary frame will not be tested for UTF-8
2972 // validity.
TEST_F(WebSocketChannelSendUtf8Test,BinaryContinuationNotChecked)2973 TEST_F(WebSocketChannelSendUtf8Test, BinaryContinuationNotChecked) {
2974 CreateChannelAndConnectSuccessfully();
2975
2976 channel_->SendFrame(
2977 false, WebSocketFrameHeader::kOpCodeBinary, AsVector("foo"));
2978 channel_->SendFrame(
2979 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("bar"));
2980 channel_->SendFrame(
2981 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("\xff"));
2982 }
2983
2984 // Multiple text messages can be validated without the validation state getting
2985 // confused.
TEST_F(WebSocketChannelSendUtf8Test,ValidateMultipleTextMessages)2986 TEST_F(WebSocketChannelSendUtf8Test, ValidateMultipleTextMessages) {
2987 CreateChannelAndConnectSuccessfully();
2988
2989 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("foo"));
2990 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("bar"));
2991 }
2992
2993 // UTF-8 validation is enforced on received Text frames.
TEST_F(WebSocketChannelEventInterfaceTest,ReceivedInvalidUtf8)2994 TEST_F(WebSocketChannelEventInterfaceTest, ReceivedInvalidUtf8) {
2995 scoped_ptr<ReadableFakeWebSocketStream> stream(
2996 new ReadableFakeWebSocketStream);
2997 static const InitFrame frames[] = {
2998 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xff"}};
2999 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
3000 set_stream(stream.Pass());
3001
3002 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
3003 EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
3004 EXPECT_CALL(*event_interface_,
3005 OnFailChannel("Could not decode a text frame as UTF-8."));
3006
3007 CreateChannelAndConnectSuccessfully();
3008 base::MessageLoop::current()->RunUntilIdle();
3009 }
3010
3011 // Invalid UTF-8 is not sent over the network.
TEST_F(WebSocketChannelStreamTest,InvalidUtf8TextFrameNotSent)3012 TEST_F(WebSocketChannelStreamTest, InvalidUtf8TextFrameNotSent) {
3013 static const InitFrame expected[] = {{FINAL_FRAME,
3014 WebSocketFrameHeader::kOpCodeClose,
3015 MASKED, CLOSE_DATA(GOING_AWAY, "")}};
3016 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
3017 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
3018 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3019 .WillRepeatedly(Return(ERR_IO_PENDING));
3020 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3021 .WillOnce(Return(OK));
3022 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3023
3024 CreateChannelAndConnectSuccessfully();
3025
3026 channel_->SendFrame(
3027 true, WebSocketFrameHeader::kOpCodeText, AsVector("\xff"));
3028 }
3029
3030 // The rest of the tests for receiving invalid UTF-8 test the communication with
3031 // the server. Since there is only one code path, it would be redundant to
3032 // perform the same tests on the EventInterface as well.
3033
3034 // If invalid UTF-8 is received in a Text frame, the connection is failed.
TEST_F(WebSocketChannelReceiveUtf8Test,InvalidTextFrameRejected)3035 TEST_F(WebSocketChannelReceiveUtf8Test, InvalidTextFrameRejected) {
3036 static const InitFrame frames[] = {
3037 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xff"}};
3038 static const InitFrame expected[] = {
3039 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
3040 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
3041 {
3042 InSequence s;
3043 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3044 .WillOnce(ReturnFrames(&frames))
3045 .WillRepeatedly(Return(ERR_IO_PENDING));
3046 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3047 .WillOnce(Return(OK));
3048 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3049 }
3050
3051 CreateChannelAndConnectSuccessfully();
3052 }
3053
3054 // A received Text message is not permitted to end with a partial UTF-8
3055 // character.
TEST_F(WebSocketChannelReceiveUtf8Test,IncompleteCharacterReceived)3056 TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterReceived) {
3057 static const InitFrame frames[] = {
3058 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}};
3059 static const InitFrame expected[] = {
3060 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
3061 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
3062 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3063 .WillOnce(ReturnFrames(&frames))
3064 .WillRepeatedly(Return(ERR_IO_PENDING));
3065 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3066 .WillOnce(Return(OK));
3067 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3068
3069 CreateChannelAndConnectSuccessfully();
3070 }
3071
3072 // However, a non-final Text frame may end with a partial UTF-8 character.
TEST_F(WebSocketChannelReceiveUtf8Test,IncompleteCharacterIncompleteMessage)3073 TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterIncompleteMessage) {
3074 static const InitFrame frames[] = {
3075 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}};
3076 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3077 .WillOnce(ReturnFrames(&frames))
3078 .WillRepeatedly(Return(ERR_IO_PENDING));
3079
3080 CreateChannelAndConnectSuccessfully();
3081 }
3082
3083 // However, it will become an error if it is followed by an empty final frame.
TEST_F(WebSocketChannelReceiveUtf8Test,TricksyIncompleteCharacter)3084 TEST_F(WebSocketChannelReceiveUtf8Test, TricksyIncompleteCharacter) {
3085 static const InitFrame frames[] = {
3086 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"},
3087 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, ""}};
3088 static const InitFrame expected[] = {
3089 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
3090 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
3091 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3092 .WillOnce(ReturnFrames(&frames))
3093 .WillRepeatedly(Return(ERR_IO_PENDING));
3094 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3095 .WillOnce(Return(OK));
3096 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3097
3098 CreateChannelAndConnectSuccessfully();
3099 }
3100
3101 // UTF-8 parsing context must be retained between received frames of the same
3102 // message.
TEST_F(WebSocketChannelReceiveUtf8Test,ReceivedParsingContextRetained)3103 TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedParsingContextRetained) {
3104 static const InitFrame frames[] = {
3105 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xf1"},
3106 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3107 NOT_MASKED, "\x80\xa0\xbf"}};
3108 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3109 .WillOnce(ReturnFrames(&frames))
3110 .WillRepeatedly(Return(ERR_IO_PENDING));
3111
3112 CreateChannelAndConnectSuccessfully();
3113 }
3114
3115 // An invalid character must be detected even if split between frames.
TEST_F(WebSocketChannelReceiveUtf8Test,SplitInvalidCharacterReceived)3116 TEST_F(WebSocketChannelReceiveUtf8Test, SplitInvalidCharacterReceived) {
3117 static const InitFrame frames[] = {
3118 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xe1"},
3119 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3120 NOT_MASKED, "\x80\xa0\xbf"}};
3121 static const InitFrame expected[] = {
3122 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
3123 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
3124 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3125 .WillOnce(ReturnFrames(&frames))
3126 .WillRepeatedly(Return(ERR_IO_PENDING));
3127 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3128 .WillOnce(Return(OK));
3129 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3130
3131 CreateChannelAndConnectSuccessfully();
3132 }
3133
3134 // An invalid character received in a continuation frame must be detected.
TEST_F(WebSocketChannelReceiveUtf8Test,InvalidReceivedIncontinuation)3135 TEST_F(WebSocketChannelReceiveUtf8Test, InvalidReceivedIncontinuation) {
3136 static const InitFrame frames[] = {
3137 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"},
3138 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3139 NOT_MASKED, "bar"},
3140 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3141 NOT_MASKED, "\xff"}};
3142 static const InitFrame expected[] = {
3143 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
3144 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
3145 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3146 .WillOnce(ReturnFrames(&frames))
3147 .WillRepeatedly(Return(ERR_IO_PENDING));
3148 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3149 .WillOnce(Return(OK));
3150 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3151
3152 CreateChannelAndConnectSuccessfully();
3153 }
3154
3155 // Continuations of binary frames must not be tested for UTF-8 validity.
TEST_F(WebSocketChannelReceiveUtf8Test,ReceivedBinaryNotUtf8Tested)3156 TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedBinaryNotUtf8Tested) {
3157 static const InitFrame frames[] = {
3158 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeBinary, NOT_MASKED, "foo"},
3159 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3160 NOT_MASKED, "bar"},
3161 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3162 NOT_MASKED, "\xff"}};
3163 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3164 .WillOnce(ReturnFrames(&frames))
3165 .WillRepeatedly(Return(ERR_IO_PENDING));
3166
3167 CreateChannelAndConnectSuccessfully();
3168 }
3169
3170 // Multiple Text messages can be validated.
TEST_F(WebSocketChannelReceiveUtf8Test,ValidateMultipleReceived)3171 TEST_F(WebSocketChannelReceiveUtf8Test, ValidateMultipleReceived) {
3172 static const InitFrame frames[] = {
3173 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"},
3174 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "bar"}};
3175 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3176 .WillOnce(ReturnFrames(&frames))
3177 .WillRepeatedly(Return(ERR_IO_PENDING));
3178
3179 CreateChannelAndConnectSuccessfully();
3180 }
3181
3182 // A new data message cannot start in the middle of another data message.
TEST_F(WebSocketChannelEventInterfaceTest,BogusContinuation)3183 TEST_F(WebSocketChannelEventInterfaceTest, BogusContinuation) {
3184 scoped_ptr<ReadableFakeWebSocketStream> stream(
3185 new ReadableFakeWebSocketStream);
3186 static const InitFrame frames[] = {
3187 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeBinary,
3188 NOT_MASKED, "frame1"},
3189 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
3190 NOT_MASKED, "frame2"}};
3191 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
3192 set_stream(stream.Pass());
3193
3194 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
3195 EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
3196 EXPECT_CALL(
3197 *event_interface_,
3198 OnDataFrame(
3199 false, WebSocketFrameHeader::kOpCodeBinary, AsVector("frame1")));
3200 EXPECT_CALL(
3201 *event_interface_,
3202 OnFailChannel(
3203 "Received start of new message but previous message is unfinished."));
3204
3205 CreateChannelAndConnectSuccessfully();
3206 }
3207
3208 // A new message cannot start with a Continuation frame.
TEST_F(WebSocketChannelEventInterfaceTest,MessageStartingWithContinuation)3209 TEST_F(WebSocketChannelEventInterfaceTest, MessageStartingWithContinuation) {
3210 scoped_ptr<ReadableFakeWebSocketStream> stream(
3211 new ReadableFakeWebSocketStream);
3212 static const InitFrame frames[] = {
3213 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3214 NOT_MASKED, "continuation"}};
3215 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
3216 set_stream(stream.Pass());
3217
3218 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
3219 EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
3220 EXPECT_CALL(*event_interface_,
3221 OnFailChannel("Received unexpected continuation frame."));
3222
3223 CreateChannelAndConnectSuccessfully();
3224 }
3225
3226 // A frame passed to the renderer must be either non-empty or have the final bit
3227 // set.
TEST_F(WebSocketChannelEventInterfaceTest,DataFramesNonEmptyOrFinal)3228 TEST_F(WebSocketChannelEventInterfaceTest, DataFramesNonEmptyOrFinal) {
3229 scoped_ptr<ReadableFakeWebSocketStream> stream(
3230 new ReadableFakeWebSocketStream);
3231 static const InitFrame frames[] = {
3232 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, ""},
3233 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3234 NOT_MASKED, ""},
3235 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, ""}};
3236 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
3237 set_stream(stream.Pass());
3238
3239 EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
3240 EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
3241 EXPECT_CALL(
3242 *event_interface_,
3243 OnDataFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
3244
3245 CreateChannelAndConnectSuccessfully();
3246 }
3247
3248 // Calls to OnSSLCertificateError() must be passed through to the event
3249 // interface with the correct URL attached.
TEST_F(WebSocketChannelEventInterfaceTest,OnSSLCertificateErrorCalled)3250 TEST_F(WebSocketChannelEventInterfaceTest, OnSSLCertificateErrorCalled) {
3251 const GURL wss_url("wss://example.com/sslerror");
3252 connect_data_.socket_url = wss_url;
3253 const SSLInfo ssl_info;
3254 const bool fatal = true;
3255 scoped_ptr<WebSocketEventInterface::SSLErrorCallbacks> fake_callbacks(
3256 new FakeSSLErrorCallbacks);
3257
3258 EXPECT_CALL(*event_interface_,
3259 OnSSLCertificateErrorCalled(NotNull(), wss_url, _, fatal));
3260
3261 CreateChannelAndConnect();
3262 connect_data_.creator.connect_delegate->OnSSLCertificateError(
3263 fake_callbacks.Pass(), ssl_info, fatal);
3264 }
3265
3266 // If we receive another frame after Close, it is not valid. It is not
3267 // completely clear what behaviour is required from the standard in this case,
3268 // but the current implementation fails the connection. Since a Close has
3269 // already been sent, this just means closing the connection.
TEST_F(WebSocketChannelStreamTest,PingAfterCloseIsRejected)3270 TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) {
3271 static const InitFrame frames[] = {
3272 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3273 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")},
3274 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
3275 NOT_MASKED, "Ping body"}};
3276 static const InitFrame expected[] = {
3277 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3278 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3279 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
3280 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
3281 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3282 .WillOnce(ReturnFrames(&frames))
3283 .WillRepeatedly(Return(ERR_IO_PENDING));
3284 {
3285 // We only need to verify the relative order of WriteFrames() and
3286 // Close(). The current implementation calls WriteFrames() for the Close
3287 // frame before calling ReadFrames() again, but that is an implementation
3288 // detail and better not to consider required behaviour.
3289 InSequence s;
3290 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3291 .WillOnce(Return(OK));
3292 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3293 }
3294
3295 CreateChannelAndConnectSuccessfully();
3296 }
3297
3298 // A protocol error from the remote server should result in a close frame with
3299 // status 1002, followed by the connection closing.
TEST_F(WebSocketChannelStreamTest,ProtocolError)3300 TEST_F(WebSocketChannelStreamTest, ProtocolError) {
3301 static const InitFrame expected[] = {
3302 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3303 MASKED, CLOSE_DATA(PROTOCOL_ERROR, "WebSocket Protocol Error")}};
3304 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
3305 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
3306 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3307 .WillOnce(Return(ERR_WS_PROTOCOL_ERROR));
3308 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3309 .WillOnce(Return(OK));
3310 EXPECT_CALL(*mock_stream_, Close());
3311
3312 CreateChannelAndConnectSuccessfully();
3313 }
3314
3315 // Set the closing handshake timeout to a very tiny value before connecting.
3316 class WebSocketChannelStreamTimeoutTest : public WebSocketChannelStreamTest {
3317 protected:
WebSocketChannelStreamTimeoutTest()3318 WebSocketChannelStreamTimeoutTest() {}
3319
CreateChannelAndConnectSuccessfully()3320 virtual void CreateChannelAndConnectSuccessfully() OVERRIDE {
3321 set_stream(mock_stream_.Pass());
3322 CreateChannelAndConnect();
3323 channel_->SendFlowControl(kPlentyOfQuota);
3324 channel_->SetClosingHandshakeTimeoutForTesting(
3325 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
3326 connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
3327 }
3328 };
3329
3330 // In this case the server initiates the closing handshake with a Close
3331 // message. WebSocketChannel responds with a matching Close message, and waits
3332 // for the server to close the TCP/IP connection. The server never closes the
3333 // connection, so the closing handshake times out and WebSocketChannel closes
3334 // the connection itself.
TEST_F(WebSocketChannelStreamTimeoutTest,ServerInitiatedCloseTimesOut)3335 TEST_F(WebSocketChannelStreamTimeoutTest, ServerInitiatedCloseTimesOut) {
3336 static const InitFrame frames[] = {
3337 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3338 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3339 static const InitFrame expected[] = {
3340 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3341 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3342 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
3343 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
3344 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3345 .WillOnce(ReturnFrames(&frames))
3346 .WillRepeatedly(Return(ERR_IO_PENDING));
3347 Checkpoint checkpoint;
3348 TestClosure completion;
3349 {
3350 InSequence s;
3351 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3352 .WillOnce(Return(OK));
3353 EXPECT_CALL(checkpoint, Call(1));
3354 EXPECT_CALL(*mock_stream_, Close())
3355 .WillOnce(InvokeClosure(completion.closure()));
3356 }
3357
3358 CreateChannelAndConnectSuccessfully();
3359 checkpoint.Call(1);
3360 completion.WaitForResult();
3361 }
3362
3363 // In this case the client initiates the closing handshake by sending a Close
3364 // message. WebSocketChannel waits for a Close message in response from the
3365 // server. The server never responds to the Close message, so the closing
3366 // handshake times out and WebSocketChannel closes the connection.
TEST_F(WebSocketChannelStreamTimeoutTest,ClientInitiatedCloseTimesOut)3367 TEST_F(WebSocketChannelStreamTimeoutTest, ClientInitiatedCloseTimesOut) {
3368 static const InitFrame expected[] = {
3369 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3370 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3371 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
3372 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
3373 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3374 .WillRepeatedly(Return(ERR_IO_PENDING));
3375 TestClosure completion;
3376 {
3377 InSequence s;
3378 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3379 .WillOnce(Return(OK));
3380 EXPECT_CALL(*mock_stream_, Close())
3381 .WillOnce(InvokeClosure(completion.closure()));
3382 }
3383
3384 CreateChannelAndConnectSuccessfully();
3385 channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK");
3386 completion.WaitForResult();
3387 }
3388
3389 // In this case the client initiates the closing handshake and the server
3390 // responds with a matching Close message. WebSocketChannel waits for the server
3391 // to close the TCP/IP connection, but it never does. The closing handshake
3392 // times out and WebSocketChannel closes the connection.
TEST_F(WebSocketChannelStreamTimeoutTest,ConnectionCloseTimesOut)3393 TEST_F(WebSocketChannelStreamTimeoutTest, ConnectionCloseTimesOut) {
3394 static const InitFrame expected[] = {
3395 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3396 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3397 static const InitFrame frames[] = {
3398 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3399 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3400 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
3401 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
3402 TestClosure completion;
3403 ScopedVector<WebSocketFrame>* read_frames = NULL;
3404 CompletionCallback read_callback;
3405 {
3406 InSequence s;
3407 // Copy the arguments to ReadFrames so that the test can call the callback
3408 // after it has send the close message.
3409 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3410 .WillOnce(DoAll(SaveArg<0>(&read_frames),
3411 SaveArg<1>(&read_callback),
3412 Return(ERR_IO_PENDING)));
3413 // The first real event that happens is the client sending the Close
3414 // message.
3415 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3416 .WillOnce(Return(OK));
3417 // The |read_frames| callback is called (from this test case) at this
3418 // point. ReadFrames is called again by WebSocketChannel, waiting for
3419 // ERR_CONNECTION_CLOSED.
3420 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3421 .WillOnce(Return(ERR_IO_PENDING));
3422 // The timeout happens and so WebSocketChannel closes the stream.
3423 EXPECT_CALL(*mock_stream_, Close())
3424 .WillOnce(InvokeClosure(completion.closure()));
3425 }
3426
3427 CreateChannelAndConnectSuccessfully();
3428 channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK");
3429 ASSERT_TRUE(read_frames);
3430 // Provide the "Close" message from the server.
3431 *read_frames = CreateFrameVector(frames);
3432 read_callback.Run(OK);
3433 completion.WaitForResult();
3434 }
3435
3436 } // namespace
3437 } // namespace net
3438