Home | History | Annotate | Download | only in websockets
      1 // Copyright 2014 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 "config.h"
      6 
      7 #include "modules/websockets/DOMWebSocket.h"
      8 
      9 #include "bindings/core/v8/ExceptionState.h"
     10 #include "bindings/core/v8/V8Binding.h"
     11 #include "core/dom/Document.h"
     12 #include "core/dom/ExceptionCode.h"
     13 #include "core/fileapi/Blob.h"
     14 #include "core/frame/ConsoleTypes.h"
     15 #include "core/testing/DummyPageHolder.h"
     16 #include "wtf/ArrayBuffer.h"
     17 #include "wtf/OwnPtr.h"
     18 #include "wtf/Uint8Array.h"
     19 #include "wtf/Vector.h"
     20 #include "wtf/testing/WTFTestHelpers.h"
     21 #include "wtf/text/WTFString.h"
     22 #include <gmock/gmock.h>
     23 #include <gtest/gtest.h>
     24 #include <v8.h>
     25 
     26 using testing::_;
     27 using testing::AnyNumber;
     28 using testing::InSequence;
     29 using testing::Ref;
     30 using testing::Return;
     31 
     32 namespace blink {
     33 
     34 namespace {
     35 
     36 typedef testing::StrictMock<testing::MockFunction<void(int)> > Checkpoint;  // NOLINT
     37 
     38 class MockWebSocketChannel : public WebSocketChannel {
     39 public:
     40     static MockWebSocketChannel* create()
     41     {
     42         return adoptRefCountedGarbageCollected(new testing::StrictMock<MockWebSocketChannel>());
     43     }
     44 
     45     virtual ~MockWebSocketChannel()
     46     {
     47     }
     48 
     49     MOCK_METHOD2(connect, bool(const KURL&, const String&));
     50     MOCK_METHOD1(send, void(const String&));
     51     MOCK_METHOD3(send, void(const ArrayBuffer&, unsigned, unsigned));
     52     MOCK_METHOD1(send, void(PassRefPtr<BlobDataHandle>));
     53     MOCK_METHOD1(send, void(PassOwnPtr<Vector<char> >));
     54     MOCK_CONST_METHOD0(bufferedAmount, unsigned long());
     55     MOCK_METHOD2(close, void(int, const String&));
     56     MOCK_METHOD4(fail, void(const String&, MessageLevel, const String&, unsigned));
     57     MOCK_METHOD0(disconnect, void());
     58     MOCK_METHOD0(suspend, void());
     59     MOCK_METHOD0(resume, void());
     60 
     61     MockWebSocketChannel()
     62     {
     63     }
     64 };
     65 
     66 class DOMWebSocketWithMockChannel FINAL : public DOMWebSocket {
     67 public:
     68     static DOMWebSocketWithMockChannel* create(ExecutionContext* context)
     69     {
     70         DOMWebSocketWithMockChannel* websocket = adoptRefCountedGarbageCollectedWillBeNoop(new DOMWebSocketWithMockChannel(context));
     71         websocket->suspendIfNeeded();
     72         return websocket;
     73     }
     74 
     75     MockWebSocketChannel* channel() { return m_channel.get(); }
     76 
     77     virtual WebSocketChannel* createChannel(ExecutionContext*, WebSocketChannelClient*) OVERRIDE
     78     {
     79         ASSERT(!m_hasCreatedChannel);
     80         m_hasCreatedChannel = true;
     81         return m_channel.get();
     82     }
     83 
     84     virtual void trace(Visitor* visitor) OVERRIDE
     85     {
     86         visitor->trace(m_channel);
     87         DOMWebSocket::trace(visitor);
     88     }
     89 
     90 private:
     91     DOMWebSocketWithMockChannel(ExecutionContext* context)
     92         : DOMWebSocket(context)
     93         , m_channel(MockWebSocketChannel::create())
     94         , m_hasCreatedChannel(false) { }
     95 
     96     Member<MockWebSocketChannel> m_channel;
     97     bool m_hasCreatedChannel;
     98 };
     99 
    100 class DOMWebSocketTestBase {
    101 public:
    102     DOMWebSocketTestBase()
    103         : m_pageHolder(DummyPageHolder::create())
    104         , m_websocket(DOMWebSocketWithMockChannel::create(&m_pageHolder->document()))
    105         , m_executionScope(v8::Isolate::GetCurrent())
    106         , m_exceptionState(ExceptionState::ConstructionContext, "property", "interface", m_executionScope.scriptState()->context()->Global(), m_executionScope.isolate())
    107     {
    108     }
    109 
    110     virtual ~DOMWebSocketTestBase()
    111     {
    112         if (!m_websocket)
    113             return;
    114         // These statements are needed to clear WebSocket::m_channel to
    115         // avoid ASSERTION failure on ~WebSocket.
    116         ASSERT(m_websocket->channel());
    117         ::testing::Mock::VerifyAndClear(m_websocket->channel());
    118         EXPECT_CALL(channel(), disconnect()).Times(AnyNumber());
    119 
    120         m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, "");
    121         m_websocket.clear();
    122         Heap::collectAllGarbage();
    123     }
    124 
    125     MockWebSocketChannel& channel() { return *m_websocket->channel(); }
    126 
    127     OwnPtr<DummyPageHolder> m_pageHolder;
    128     Persistent<DOMWebSocketWithMockChannel> m_websocket;
    129     V8TestingScope m_executionScope;
    130     ExceptionState m_exceptionState;
    131 };
    132 
    133 class DOMWebSocketTest : public DOMWebSocketTestBase, public ::testing::Test {
    134 public:
    135 };
    136 
    137 TEST_F(DOMWebSocketTest, connectToBadURL)
    138 {
    139     m_websocket->connect("xxx", Vector<String>(), m_exceptionState);
    140 
    141 
    142     EXPECT_TRUE(m_exceptionState.hadException());
    143     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    144     EXPECT_EQ("The URL 'xxx' is invalid.", m_exceptionState.message());
    145     EXPECT_EQ(DOMWebSocket::CLOSED, m_websocket->readyState());
    146 }
    147 
    148 TEST_F(DOMWebSocketTest, connectToNonWsURL)
    149 {
    150     m_websocket->connect("http://example.com/", Vector<String>(), m_exceptionState);
    151 
    152 
    153     EXPECT_TRUE(m_exceptionState.hadException());
    154     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    155     EXPECT_EQ("The URL's scheme must be either 'ws' or 'wss'. 'http' is not allowed.", m_exceptionState.message());
    156     EXPECT_EQ(DOMWebSocket::CLOSED, m_websocket->readyState());
    157 }
    158 
    159 TEST_F(DOMWebSocketTest, connectToURLHavingFragmentIdentifier)
    160 {
    161     m_websocket->connect("ws://example.com/#fragment", Vector<String>(), m_exceptionState);
    162 
    163 
    164     EXPECT_TRUE(m_exceptionState.hadException());
    165     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    166     EXPECT_EQ("The URL contains a fragment identifier ('fragment'). Fragment identifiers are not allowed in WebSocket URLs.", m_exceptionState.message());
    167     EXPECT_EQ(DOMWebSocket::CLOSED, m_websocket->readyState());
    168 }
    169 
    170 TEST_F(DOMWebSocketTest, invalidPort)
    171 {
    172     m_websocket->connect("ws://example.com:7", Vector<String>(), m_exceptionState);
    173 
    174 
    175     EXPECT_TRUE(m_exceptionState.hadException());
    176     EXPECT_EQ(SecurityError, m_exceptionState.code());
    177     EXPECT_EQ("The port 7 is not allowed.", m_exceptionState.message());
    178     EXPECT_EQ(DOMWebSocket::CLOSED, m_websocket->readyState());
    179 }
    180 
    181 // FIXME: Add a test for Content Security Policy.
    182 
    183 TEST_F(DOMWebSocketTest, invalidSubprotocols)
    184 {
    185     Vector<String> subprotocols;
    186     subprotocols.append("@subprotocol-|'\"x\x01\x02\x03x");
    187 
    188     {
    189         InSequence s;
    190         EXPECT_CALL(channel(), disconnect());
    191     }
    192 
    193     m_websocket->connect("ws://example.com/", subprotocols, m_exceptionState);
    194 
    195     EXPECT_TRUE(m_exceptionState.hadException());
    196     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    197     EXPECT_EQ("The subprotocol '@subprotocol-|'\"x\\u0001\\u0002\\u0003x' is invalid.", m_exceptionState.message());
    198     EXPECT_EQ(DOMWebSocket::CLOSED, m_websocket->readyState());
    199 }
    200 
    201 TEST_F(DOMWebSocketTest, channelConnectSuccess)
    202 {
    203     Vector<String> subprotocols;
    204     subprotocols.append("aa");
    205     subprotocols.append("bb");
    206 
    207     {
    208         InSequence s;
    209         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/hoge"), String("aa, bb"))).WillOnce(Return(true));
    210     }
    211 
    212     m_websocket->connect("ws://example.com/hoge", Vector<String>(subprotocols), m_exceptionState);
    213 
    214 
    215     EXPECT_FALSE(m_exceptionState.hadException());
    216     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    217     EXPECT_EQ(KURL(KURL(), "ws://example.com/hoge"), m_websocket->url());
    218 }
    219 
    220 TEST_F(DOMWebSocketTest, channelConnectFail)
    221 {
    222     Vector<String> subprotocols;
    223     subprotocols.append("aa");
    224     subprotocols.append("bb");
    225 
    226     {
    227         InSequence s;
    228         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String("aa, bb"))).WillOnce(Return(false));
    229         EXPECT_CALL(channel(), disconnect());
    230     }
    231 
    232     m_websocket->connect("ws://example.com/", Vector<String>(subprotocols), m_exceptionState);
    233 
    234 
    235     EXPECT_TRUE(m_exceptionState.hadException());
    236     EXPECT_EQ(SecurityError, m_exceptionState.code());
    237     EXPECT_EQ("An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.", m_exceptionState.message());
    238     EXPECT_EQ(DOMWebSocket::CLOSED, m_websocket->readyState());
    239 }
    240 
    241 TEST_F(DOMWebSocketTest, isValidSubprotocolString)
    242 {
    243     EXPECT_TRUE(DOMWebSocket::isValidSubprotocolString("Helloworld!!"));
    244     EXPECT_FALSE(DOMWebSocket::isValidSubprotocolString("Hello, world!!"));
    245     EXPECT_FALSE(DOMWebSocket::isValidSubprotocolString(String()));
    246     EXPECT_FALSE(DOMWebSocket::isValidSubprotocolString(""));
    247 
    248     const char validCharacters[] = "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~";
    249     size_t length = strlen(validCharacters);
    250     for (size_t i = 0; i < length; ++i) {
    251         String s;
    252         s.append(static_cast<UChar>(validCharacters[i]));
    253         EXPECT_TRUE(DOMWebSocket::isValidSubprotocolString(s));
    254     }
    255     for (size_t i = 0; i < 256; ++i) {
    256         if (std::find(validCharacters, validCharacters + length, static_cast<char>(i)) != validCharacters + length) {
    257             continue;
    258         }
    259         String s;
    260         s.append(static_cast<UChar>(i));
    261         EXPECT_FALSE(DOMWebSocket::isValidSubprotocolString(s));
    262     }
    263 }
    264 
    265 TEST_F(DOMWebSocketTest, connectSuccess)
    266 {
    267     Vector<String> subprotocols;
    268     subprotocols.append("aa");
    269     subprotocols.append("bb");
    270     {
    271         InSequence s;
    272         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String("aa, bb"))).WillOnce(Return(true));
    273     }
    274     m_websocket->connect("ws://example.com/", subprotocols, m_exceptionState);
    275 
    276     EXPECT_FALSE(m_exceptionState.hadException());
    277     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    278 
    279     m_websocket->didConnect("bb", "cc");
    280 
    281     EXPECT_EQ(DOMWebSocket::OPEN, m_websocket->readyState());
    282     EXPECT_EQ("bb", m_websocket->protocol());
    283     EXPECT_EQ("cc", m_websocket->extensions());
    284 }
    285 
    286 TEST_F(DOMWebSocketTest, didClose)
    287 {
    288     {
    289         InSequence s;
    290         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    291         EXPECT_CALL(channel(), disconnect());
    292     }
    293     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    294 
    295     EXPECT_FALSE(m_exceptionState.hadException());
    296     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    297 
    298     m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, "");
    299 
    300     EXPECT_EQ(DOMWebSocket::CLOSED, m_websocket->readyState());
    301 }
    302 
    303 TEST_F(DOMWebSocketTest, maximumReasonSize)
    304 {
    305     {
    306         InSequence s;
    307         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    308         EXPECT_CALL(channel(), fail(_, _, _, _));
    309     }
    310     String reason;
    311     for (size_t i = 0; i < 123; ++i)
    312         reason.append("a");
    313     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    314 
    315     EXPECT_FALSE(m_exceptionState.hadException());
    316     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    317 
    318     m_websocket->close(1000, reason, m_exceptionState);
    319 
    320     EXPECT_FALSE(m_exceptionState.hadException());
    321     EXPECT_EQ(DOMWebSocket::CLOSING, m_websocket->readyState());
    322 }
    323 
    324 TEST_F(DOMWebSocketTest, reasonSizeExceeding)
    325 {
    326     {
    327         InSequence s;
    328         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    329     }
    330     String reason;
    331     for (size_t i = 0; i < 124; ++i)
    332         reason.append("a");
    333     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    334 
    335     EXPECT_FALSE(m_exceptionState.hadException());
    336     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    337 
    338     m_websocket->close(1000, reason, m_exceptionState);
    339 
    340     EXPECT_TRUE(m_exceptionState.hadException());
    341     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    342     EXPECT_EQ("The message must not be greater than 123 bytes.", m_exceptionState.message());
    343     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    344 }
    345 
    346 TEST_F(DOMWebSocketTest, closeWhenConnecting)
    347 {
    348     {
    349         InSequence s;
    350         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    351         EXPECT_CALL(channel(), fail(String("WebSocket is closed before the connection is established."), WarningMessageLevel, String(), 0));
    352     }
    353     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    354 
    355     EXPECT_FALSE(m_exceptionState.hadException());
    356     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    357 
    358     m_websocket->close(1000, "bye", m_exceptionState);
    359 
    360     EXPECT_FALSE(m_exceptionState.hadException());
    361     EXPECT_EQ(DOMWebSocket::CLOSING, m_websocket->readyState());
    362 }
    363 
    364 TEST_F(DOMWebSocketTest, close)
    365 {
    366     {
    367         InSequence s;
    368         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    369         EXPECT_CALL(channel(), close(3005, String("bye")));
    370     }
    371     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    372 
    373     EXPECT_FALSE(m_exceptionState.hadException());
    374     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    375 
    376     m_websocket->didConnect("", "");
    377     EXPECT_EQ(DOMWebSocket::OPEN, m_websocket->readyState());
    378     m_websocket->close(3005, "bye", m_exceptionState);
    379 
    380     EXPECT_FALSE(m_exceptionState.hadException());
    381     EXPECT_EQ(DOMWebSocket::CLOSING, m_websocket->readyState());
    382 }
    383 
    384 TEST_F(DOMWebSocketTest, closeWithoutReason)
    385 {
    386     {
    387         InSequence s;
    388         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    389         EXPECT_CALL(channel(), close(3005, String()));
    390     }
    391     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    392 
    393     EXPECT_FALSE(m_exceptionState.hadException());
    394     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    395 
    396     m_websocket->didConnect("", "");
    397     EXPECT_EQ(DOMWebSocket::OPEN, m_websocket->readyState());
    398     m_websocket->close(3005, m_exceptionState);
    399 
    400     EXPECT_FALSE(m_exceptionState.hadException());
    401     EXPECT_EQ(DOMWebSocket::CLOSING, m_websocket->readyState());
    402 }
    403 
    404 TEST_F(DOMWebSocketTest, closeWithoutCodeAndReason)
    405 {
    406     {
    407         InSequence s;
    408         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    409         EXPECT_CALL(channel(), close(-1, String()));
    410     }
    411     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    412 
    413     EXPECT_FALSE(m_exceptionState.hadException());
    414     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    415 
    416     m_websocket->didConnect("", "");
    417     EXPECT_EQ(DOMWebSocket::OPEN, m_websocket->readyState());
    418     m_websocket->close(m_exceptionState);
    419 
    420     EXPECT_FALSE(m_exceptionState.hadException());
    421     EXPECT_EQ(DOMWebSocket::CLOSING, m_websocket->readyState());
    422 }
    423 
    424 TEST_F(DOMWebSocketTest, closeWhenClosing)
    425 {
    426     {
    427         InSequence s;
    428         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    429         EXPECT_CALL(channel(), close(-1, String()));
    430     }
    431     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    432 
    433     EXPECT_FALSE(m_exceptionState.hadException());
    434     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    435 
    436     m_websocket->didConnect("", "");
    437     EXPECT_EQ(DOMWebSocket::OPEN, m_websocket->readyState());
    438     m_websocket->close(m_exceptionState);
    439     EXPECT_FALSE(m_exceptionState.hadException());
    440     EXPECT_EQ(DOMWebSocket::CLOSING, m_websocket->readyState());
    441 
    442     m_websocket->close(m_exceptionState);
    443 
    444     EXPECT_FALSE(m_exceptionState.hadException());
    445     EXPECT_EQ(DOMWebSocket::CLOSING, m_websocket->readyState());
    446 }
    447 
    448 TEST_F(DOMWebSocketTest, closeWhenClosed)
    449 {
    450     {
    451         InSequence s;
    452         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    453         EXPECT_CALL(channel(), close(-1, String()));
    454         EXPECT_CALL(channel(), disconnect());
    455     }
    456     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    457 
    458     EXPECT_FALSE(m_exceptionState.hadException());
    459     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    460 
    461     m_websocket->didConnect("", "");
    462     EXPECT_EQ(DOMWebSocket::OPEN, m_websocket->readyState());
    463     m_websocket->close(m_exceptionState);
    464     EXPECT_FALSE(m_exceptionState.hadException());
    465     EXPECT_EQ(DOMWebSocket::CLOSING, m_websocket->readyState());
    466 
    467     m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeComplete, 1000, String());
    468     EXPECT_EQ(DOMWebSocket::CLOSED, m_websocket->readyState());
    469     m_websocket->close(m_exceptionState);
    470 
    471     EXPECT_FALSE(m_exceptionState.hadException());
    472     EXPECT_EQ(DOMWebSocket::CLOSED, m_websocket->readyState());
    473 }
    474 
    475 TEST_F(DOMWebSocketTest, sendStringWhenConnecting)
    476 {
    477     {
    478         InSequence s;
    479         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    480     }
    481     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    482 
    483     EXPECT_FALSE(m_exceptionState.hadException());
    484 
    485     m_websocket->send("hello", m_exceptionState);
    486 
    487     EXPECT_TRUE(m_exceptionState.hadException());
    488     EXPECT_EQ(InvalidStateError, m_exceptionState.code());
    489     EXPECT_EQ("Still in CONNECTING state.", m_exceptionState.message());
    490     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    491 }
    492 
    493 TEST_F(DOMWebSocketTest, sendStringWhenClosing)
    494 {
    495     Checkpoint checkpoint;
    496     {
    497         InSequence s;
    498         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    499         EXPECT_CALL(channel(), fail(_, _, _, _));
    500     }
    501     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    502 
    503     EXPECT_FALSE(m_exceptionState.hadException());
    504 
    505     m_websocket->close(m_exceptionState);
    506     EXPECT_FALSE(m_exceptionState.hadException());
    507 
    508     m_websocket->send("hello", m_exceptionState);
    509 
    510     EXPECT_FALSE(m_exceptionState.hadException());
    511     EXPECT_EQ(DOMWebSocket::CLOSING, m_websocket->readyState());
    512 }
    513 
    514 TEST_F(DOMWebSocketTest, sendStringWhenClosed)
    515 {
    516     Checkpoint checkpoint;
    517     {
    518         InSequence s;
    519         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    520         EXPECT_CALL(channel(), disconnect());
    521         EXPECT_CALL(checkpoint, Call(1));
    522     }
    523     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    524 
    525     EXPECT_FALSE(m_exceptionState.hadException());
    526 
    527     m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, "");
    528     checkpoint.Call(1);
    529 
    530     m_websocket->send("hello", m_exceptionState);
    531 
    532     EXPECT_FALSE(m_exceptionState.hadException());
    533     EXPECT_EQ(DOMWebSocket::CLOSED, m_websocket->readyState());
    534 }
    535 
    536 TEST_F(DOMWebSocketTest, sendStringSuccess)
    537 {
    538     {
    539         InSequence s;
    540         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    541         EXPECT_CALL(channel(), send(String("hello")));
    542     }
    543     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    544 
    545     EXPECT_FALSE(m_exceptionState.hadException());
    546 
    547     m_websocket->didConnect("", "");
    548     m_websocket->send("hello", m_exceptionState);
    549 
    550     EXPECT_FALSE(m_exceptionState.hadException());
    551     EXPECT_EQ(DOMWebSocket::OPEN, m_websocket->readyState());
    552 }
    553 
    554 TEST_F(DOMWebSocketTest, sendArrayBufferWhenConnecting)
    555 {
    556     RefPtr<ArrayBufferView> view = Uint8Array::create(8);
    557     {
    558         InSequence s;
    559         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    560     }
    561     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    562 
    563     EXPECT_FALSE(m_exceptionState.hadException());
    564 
    565     m_websocket->send(view->buffer().get(), m_exceptionState);
    566 
    567     EXPECT_TRUE(m_exceptionState.hadException());
    568     EXPECT_EQ(InvalidStateError, m_exceptionState.code());
    569     EXPECT_EQ("Still in CONNECTING state.", m_exceptionState.message());
    570     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    571 }
    572 
    573 TEST_F(DOMWebSocketTest, sendArrayBufferWhenClosing)
    574 {
    575     RefPtr<ArrayBufferView> view = Uint8Array::create(8);
    576     {
    577         InSequence s;
    578         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    579         EXPECT_CALL(channel(), fail(_, _, _, _));
    580     }
    581     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    582 
    583     EXPECT_FALSE(m_exceptionState.hadException());
    584 
    585     m_websocket->close(m_exceptionState);
    586     EXPECT_FALSE(m_exceptionState.hadException());
    587 
    588     m_websocket->send(view->buffer().get(), m_exceptionState);
    589 
    590     EXPECT_FALSE(m_exceptionState.hadException());
    591     EXPECT_EQ(DOMWebSocket::CLOSING, m_websocket->readyState());
    592 }
    593 
    594 TEST_F(DOMWebSocketTest, sendArrayBufferWhenClosed)
    595 {
    596     Checkpoint checkpoint;
    597     RefPtr<ArrayBufferView> view = Uint8Array::create(8);
    598     {
    599         InSequence s;
    600         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    601         EXPECT_CALL(channel(), disconnect());
    602         EXPECT_CALL(checkpoint, Call(1));
    603     }
    604     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    605 
    606     EXPECT_FALSE(m_exceptionState.hadException());
    607 
    608     m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, "");
    609     checkpoint.Call(1);
    610 
    611     m_websocket->send(view->buffer().get(), m_exceptionState);
    612 
    613     EXPECT_FALSE(m_exceptionState.hadException());
    614     EXPECT_EQ(DOMWebSocket::CLOSED, m_websocket->readyState());
    615 }
    616 
    617 TEST_F(DOMWebSocketTest, sendArrayBufferSuccess)
    618 {
    619     RefPtr<ArrayBufferView> view = Uint8Array::create(8);
    620     {
    621         InSequence s;
    622         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    623         EXPECT_CALL(channel(), send(Ref(*view->buffer()), 0, 8));
    624     }
    625     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    626 
    627     EXPECT_FALSE(m_exceptionState.hadException());
    628 
    629     m_websocket->didConnect("", "");
    630     m_websocket->send(view->buffer().get(), m_exceptionState);
    631 
    632     EXPECT_FALSE(m_exceptionState.hadException());
    633     EXPECT_EQ(DOMWebSocket::OPEN, m_websocket->readyState());
    634 }
    635 
    636 // FIXME: We should have Blob tests here.
    637 // We can't create a Blob because the blob registration cannot be mocked yet.
    638 
    639 // FIXME: We should add tests for bufferedAmount.
    640 
    641 // FIXME: We should add tests for data receiving.
    642 
    643 TEST_F(DOMWebSocketTest, binaryType)
    644 {
    645     EXPECT_EQ("blob", m_websocket->binaryType());
    646 
    647     m_websocket->setBinaryType("hoge");
    648 
    649     EXPECT_EQ("blob", m_websocket->binaryType());
    650 
    651     m_websocket->setBinaryType("arraybuffer");
    652 
    653     EXPECT_EQ("arraybuffer", m_websocket->binaryType());
    654 
    655     m_websocket->setBinaryType("fuga");
    656 
    657     EXPECT_EQ("arraybuffer", m_websocket->binaryType());
    658 
    659     m_websocket->setBinaryType("blob");
    660 
    661     EXPECT_EQ("blob", m_websocket->binaryType());
    662 }
    663 
    664 // FIXME: We should add tests for suspend / resume.
    665 
    666 class DOMWebSocketValidClosingTest : public DOMWebSocketTestBase, public ::testing::TestWithParam<unsigned short> {
    667 public:
    668 };
    669 
    670 TEST_P(DOMWebSocketValidClosingTest, test)
    671 {
    672     {
    673         InSequence s;
    674         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    675         EXPECT_CALL(channel(), fail(_, _, _, _));
    676     }
    677     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    678 
    679     EXPECT_FALSE(m_exceptionState.hadException());
    680     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    681 
    682     m_websocket->close(GetParam(), "bye", m_exceptionState);
    683 
    684     EXPECT_FALSE(m_exceptionState.hadException());
    685     EXPECT_EQ(DOMWebSocket::CLOSING, m_websocket->readyState());
    686 }
    687 
    688 INSTANTIATE_TEST_CASE_P(DOMWebSocketValidClosing, DOMWebSocketValidClosingTest, ::testing::Values(1000, 3000, 3001, 4998, 4999));
    689 
    690 class DOMWebSocketInvalidClosingCodeTest : public DOMWebSocketTestBase, public ::testing::TestWithParam<unsigned short> {
    691 public:
    692 };
    693 
    694 TEST_P(DOMWebSocketInvalidClosingCodeTest, test)
    695 {
    696     {
    697         InSequence s;
    698         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    699     }
    700     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    701 
    702     EXPECT_FALSE(m_exceptionState.hadException());
    703     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    704 
    705     m_websocket->close(GetParam(), "bye", m_exceptionState);
    706 
    707     EXPECT_TRUE(m_exceptionState.hadException());
    708     EXPECT_EQ(InvalidAccessError, m_exceptionState.code());
    709     EXPECT_EQ(String::format("The code must be either 1000, or between 3000 and 4999. %d is neither.", GetParam()), m_exceptionState.message());
    710     EXPECT_EQ(DOMWebSocket::CONNECTING, m_websocket->readyState());
    711 }
    712 
    713 INSTANTIATE_TEST_CASE_P(DOMWebSocketInvalidClosingCode, DOMWebSocketInvalidClosingCodeTest, ::testing::Values(0, 1, 998, 999, 1001, 2999, 5000, 9999, 65535));
    714 
    715 } // namespace
    716 
    717 } // namespace blink
    718