15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011, 2012 Google Inc.  All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/websockets/WorkerThreadableWebSocketChannel.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
35197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ScriptCallStackFactory.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/CrossThreadTask.h"
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h"
381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "core/dom/ExecutionContext.h"
399e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#include "core/dom/ExecutionContextTask.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/fileapi/Blob.h"
4181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)#include "core/inspector/ScriptCallFrame.h"
4281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)#include "core/inspector/ScriptCallStack.h"
439e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#include "core/workers/WorkerGlobalScope.h"
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/workers/WorkerLoaderProxy.h"
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/workers/WorkerThread.h"
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/websockets/MainThreadWebSocketChannel.h"
4709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "modules/websockets/NewWebSocketChannelImpl.h"
4876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)#include "platform/RuntimeEnabledFeatures.h"
4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "public/platform/Platform.h"
5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "public/platform/WebWaitableEvent.h"
5153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/ArrayBuffer.h"
52323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)#include "wtf/Assertions.h"
5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "wtf/Functional.h"
5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/MainThread.h"
559e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#include "wtf/text/WTFString.h"
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
57c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
58c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
59c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)typedef WorkerThreadableWebSocketChannel::Bridge Bridge;
60c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)typedef WorkerThreadableWebSocketChannel::Peer Peer;
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Created and destroyed on the worker thread. All setters of this class are
6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// called on the main thread, while all getters are called on the worker
6409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// thread. signalWorkerThread() must be called before any getters are called.
65c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)class ThreadableWebSocketChannelSyncHelper : public GarbageCollectedFinalized<ThreadableWebSocketChannelSyncHelper> {
6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
67e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    static ThreadableWebSocketChannelSyncHelper* create(PassOwnPtr<WebWaitableEvent> event)
68197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
69c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return new ThreadableWebSocketChannelSyncHelper(event);
70197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
71197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
72197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ~ThreadableWebSocketChannelSyncHelper()
7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
7409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
7509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // All setters are called on the main thread.
77f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    void setConnectRequestResult(bool connectRequestResult)
78f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
79f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        m_connectRequestResult = connectRequestResult;
80f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
8109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
8209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // All getter are called on the worker thread.
83f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    bool connectRequestResult() const
84f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
85f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return m_connectRequestResult;
86f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
8709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // This should be called after all setters are called and before any
8909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // getters are called.
9009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void signalWorkerThread()
9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
9209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_event->signal();
9309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
94c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    void wait()
9509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
96c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_event->wait();
9709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
99197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void trace(Visitor* visitor) { }
100197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
10109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)private:
102e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    explicit ThreadableWebSocketChannelSyncHelper(PassOwnPtr<WebWaitableEvent> event)
10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        : m_event(event)
104f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        , m_connectRequestResult(false)
10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
10609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
10709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
108e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    OwnPtr<WebWaitableEvent> m_event;
109f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    bool m_connectRequestResult;
11009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
11109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
112323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)WorkerThreadableWebSocketChannel::WorkerThreadableWebSocketChannel(WorkerGlobalScope& workerGlobalScope, WebSocketChannelClient* client, const String& sourceURL, unsigned lineNumber)
1139e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    : m_bridge(new Bridge(client, workerGlobalScope))
114a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    , m_sourceURLAtConnection(sourceURL)
115a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    , m_lineNumberAtConnection(lineNumber)
11681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles){
11781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    m_bridge->initialize(sourceURL, lineNumber);
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WorkerThreadableWebSocketChannel::~WorkerThreadableWebSocketChannel()
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
122197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(!m_bridge);
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
125f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liubool WorkerThreadableWebSocketChannel::connect(const KURL& url, const String& protocol)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
127c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_bridge);
128c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return m_bridge->connect(url, protocol);
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
131c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThreadableWebSocketChannel::send(const String& message)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
133c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_bridge);
134c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_bridge->send(message);
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
137c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThreadableWebSocketChannel::send(const ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength)
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
139c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_bridge);
140c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_bridge->send(binaryData, byteOffset, byteLength);
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
143c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThreadableWebSocketChannel::send(PassRefPtr<BlobDataHandle> blobData)
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
145c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_bridge);
146c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_bridge->send(blobData);
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WorkerThreadableWebSocketChannel::close(int code, const String& reason)
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
151c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_bridge);
152c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_bridge->close(code, reason);
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15581a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)void WorkerThreadableWebSocketChannel::fail(const String& reason, MessageLevel level, const String& sourceURL, unsigned lineNumber)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    if (!m_bridge)
15881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        return;
15981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)
1605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    RefPtrWillBeRawPtr<ScriptCallStack> callStack = createScriptCallStack(1, true);
16181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    if (callStack && callStack->size())  {
16281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        // In order to emulate the ConsoleMessage behavior,
16381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        // we should ignore the specified url and line number if
16481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        // we can get the JavaScript context.
16581a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        m_bridge->fail(reason, level, callStack->at(0).sourceURL(), callStack->at(0).lineNumber());
16681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    } else if (sourceURL.isEmpty() && !lineNumber) {
16781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        // No information is specified by the caller - use the url
16881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        // and the line number at the connection.
16981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        m_bridge->fail(reason, level, m_sourceURLAtConnection, m_lineNumberAtConnection);
17081a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    } else {
17181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        // Use the specified information.
17281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        m_bridge->fail(reason, level, sourceURL, lineNumber);
17381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    }
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WorkerThreadableWebSocketChannel::disconnect()
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_bridge->disconnect();
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_bridge.clear();
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)void WorkerThreadableWebSocketChannel::trace(Visitor* visitor)
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
184197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    visitor->trace(m_bridge);
1855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    WebSocketChannel::trace(visitor);
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1889e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)Peer::Peer(Bridge* bridge, WorkerLoaderProxy& loaderProxy, ThreadableWebSocketChannelSyncHelper* syncHelper)
1899e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    : m_bridge(bridge)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_loaderProxy(loaderProxy)
191d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_mainWebSocketChannel(nullptr)
19209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , m_syncHelper(syncHelper)
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
194c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(!isMainThread());
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
197c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)Peer::~Peer()
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
199c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(!isMainThread());
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
202c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::initializeInternal(ExecutionContext* context, const String& sourceURL, unsigned lineNumber)
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
20409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(isMainThread());
205c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    Document* document = toDocument(context);
206c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (RuntimeEnabledFeatures::experimentalWebSocketEnabled()) {
207c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_mainWebSocketChannel = NewWebSocketChannelImpl::create(document, this, sourceURL, lineNumber);
208c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    } else {
209c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_mainWebSocketChannel = MainThreadWebSocketChannel::create(document, this, sourceURL, lineNumber);
210c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
211197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    m_syncHelper->signalWorkerThread();
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
214c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::connect(const KURL& url, const String& protocol)
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
217c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_syncHelper);
218323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (!m_mainWebSocketChannel) {
219f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        m_syncHelper->setConnectRequestResult(false);
220f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    } else {
221f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        bool connectRequestResult = m_mainWebSocketChannel->connect(url, protocol);
222f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        m_syncHelper->setConnectRequestResult(connectRequestResult);
223f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
224f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    m_syncHelper->signalWorkerThread();
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
227c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::send(const String& message)
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
230c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_mainWebSocketChannel)
231c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_mainWebSocketChannel->send(message);
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
234c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::sendArrayBuffer(PassOwnPtr<Vector<char> > data)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
237c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_mainWebSocketChannel)
238c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_mainWebSocketChannel->send(data);
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
241c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::sendBlob(PassRefPtr<BlobDataHandle> blobData)
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
24309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(isMainThread());
244c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_mainWebSocketChannel)
245c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_mainWebSocketChannel->send(blobData);
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
248c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::close(int code, const String& reason)
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
251c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_syncHelper);
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_mainWebSocketChannel)
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_mainWebSocketChannel->close(code, reason);
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
257c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::fail(const String& reason, MessageLevel level, const String& sourceURL, unsigned lineNumber)
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
260c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_syncHelper);
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_mainWebSocketChannel)
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
26381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    m_mainWebSocketChannel->fail(reason, level, sourceURL, lineNumber);
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
266c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::disconnect()
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
269c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_syncHelper);
270c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_mainWebSocketChannel) {
271c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_mainWebSocketChannel->disconnect();
272c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_mainWebSocketChannel = nullptr;
273c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
274c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_syncHelper->signalWorkerThread();
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2779e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)static void workerGlobalScopeDidConnect(ExecutionContext* context, Bridge* bridge, const String& subprotocol, const String& extensions)
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
279591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_UNUSED(context, context->isWorkerGlobalScope());
2809e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if (bridge->client())
2819e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        bridge->client()->didConnect(subprotocol, extensions);
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
284c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::didConnect(const String& subprotocol, const String& extensions)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
2879e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    m_loaderProxy.postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlobalScopeDidConnect, m_bridge, subprotocol, extensions));
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2909e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)static void workerGlobalScopeDidReceiveMessage(ExecutionContext* context, Bridge* bridge, const String& message)
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
292591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_UNUSED(context, context->isWorkerGlobalScope());
2939e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if (bridge->client())
2949e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        bridge->client()->didReceiveMessage(message);
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
297c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::didReceiveMessage(const String& message)
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
3009e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    m_loaderProxy.postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlobalScopeDidReceiveMessage, m_bridge, message));
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3039e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)static void workerGlobalScopeDidReceiveBinaryData(ExecutionContext* context, Bridge* bridge, PassOwnPtr<Vector<char> > binaryData)
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
305591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_UNUSED(context, context->isWorkerGlobalScope());
3069e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if (bridge->client())
3079e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        bridge->client()->didReceiveBinaryData(binaryData);
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
310c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::didReceiveBinaryData(PassOwnPtr<Vector<char> > binaryData)
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
3139e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    m_loaderProxy.postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlobalScopeDidReceiveBinaryData, m_bridge, binaryData));
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3169e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)static void workerGlobalScopeDidConsumeBufferedAmount(ExecutionContext* context, Bridge* bridge, unsigned long consumed)
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
318591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_UNUSED(context, context->isWorkerGlobalScope());
3199e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if (bridge->client())
3209e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        bridge->client()->didConsumeBufferedAmount(consumed);
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
323c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::didConsumeBufferedAmount(unsigned long consumed)
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
3269e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    m_loaderProxy.postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlobalScopeDidConsumeBufferedAmount, m_bridge, consumed));
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3299e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)static void workerGlobalScopeDidStartClosingHandshake(ExecutionContext* context, Bridge* bridge)
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
331591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_UNUSED(context, context->isWorkerGlobalScope());
3329e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if (bridge->client())
3339e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        bridge->client()->didStartClosingHandshake();
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
336c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::didStartClosingHandshake()
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
3399e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    m_loaderProxy.postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlobalScopeDidStartClosingHandshake, m_bridge));
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3429e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)static void workerGlobalScopeDidClose(ExecutionContext* context, Bridge* bridge, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
344591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_UNUSED(context, context->isWorkerGlobalScope());
3459e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if (bridge->client())
3469e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        bridge->client()->didClose(closingHandshakeCompletion, code, reason);
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
349c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::didClose(ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
352c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_mainWebSocketChannel) {
353c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_mainWebSocketChannel->disconnect();
354c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_mainWebSocketChannel = nullptr;
355c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
3569e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    m_loaderProxy.postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlobalScopeDidClose, m_bridge, closingHandshakeCompletion, code, reason));
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3599e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)static void workerGlobalScopeDidReceiveMessageError(ExecutionContext* context, Bridge* bridge)
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
361591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_UNUSED(context, context->isWorkerGlobalScope());
3629e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if (bridge->client())
3639e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        bridge->client()->didReceiveMessageError();
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
366c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::didReceiveMessageError()
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
36853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ASSERT(isMainThread());
3699e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    m_loaderProxy.postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlobalScopeDidReceiveMessageError, m_bridge));
370197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
371197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
372c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Peer::trace(Visitor* visitor)
373197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
3749e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    visitor->trace(m_bridge);
375197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    visitor->trace(m_mainWebSocketChannel);
376197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    visitor->trace(m_syncHelper);
377197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WebSocketChannelClient::trace(visitor);
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3809e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)Bridge::Bridge(WebSocketChannelClient* client, WorkerGlobalScope& workerGlobalScope)
3819e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    : m_client(client)
382591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    , m_workerGlobalScope(workerGlobalScope)
383591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy())
384e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    , m_syncHelper(ThreadableWebSocketChannelSyncHelper::create(adoptPtr(Platform::current()->createWaitableEvent())))
3859e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    , m_peer(new Peer(this, m_loaderProxy, m_syncHelper))
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
389c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)Bridge::~Bridge()
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
391c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(!m_peer);
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
394c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Bridge::initialize(const String& sourceURL, unsigned lineNumber)
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3969e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if (!waitForMethodCompletion(createCrossThreadTask(&Peer::initialize, AllowCrossThreadAccess(m_peer.get()), sourceURL, lineNumber))) {
39709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // The worker thread has been signalled to shutdown before method completion.
398197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        disconnect();
39909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
402c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)bool Bridge::connect(const KURL& url, const String& protocol)
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
404c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!m_peer)
405f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return false;
406323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
407c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, m_peer.get(), url, protocol)))
408323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        return false;
409323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
410f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    return m_syncHelper->connectRequestResult();
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
413c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Bridge::send(const String& message)
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
415c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_peer);
416c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::send, m_peer.get(), message));
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
419c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Bridge::send(const ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength)
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
421c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_peer);
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied into Vector<char>.
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OwnPtr<Vector<char> > data = adoptPtr(new Vector<char>(byteLength));
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (binaryData.byteLength())
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        memcpy(data->data(), static_cast<const char*>(binaryData.data()) + byteOffset, byteLength);
426f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
427c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::sendArrayBuffer, m_peer.get(), data.release()));
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
430c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Bridge::send(PassRefPtr<BlobDataHandle> data)
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
432c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_peer);
433c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::sendBlob, m_peer.get(), data));
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
436c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Bridge::close(int code, const String& reason)
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
438c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_peer);
439c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::close, m_peer.get(), code, reason));
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
442c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Bridge::fail(const String& reason, MessageLevel level, const String& sourceURL, unsigned lineNumber)
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
444c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_peer);
445c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::fail, m_peer.get(), reason, level, sourceURL, lineNumber));
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
448c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Bridge::disconnect()
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
450c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!m_peer)
451197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return;
452197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
453c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    waitForMethodCompletion(createCrossThreadTask(&Peer::disconnect, m_peer.get()));
454c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // Here |m_peer| is detached from the main thread and we can delete it.
455c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
4569e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    m_client = nullptr;
457c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_peer = nullptr;
458c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_syncHelper = nullptr;
459c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // We won't use this any more.
460c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_workerGlobalScope.clear();
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
46309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Caller of this function should hold a reference to the bridge, because this function may call WebSocket::didClose() in the end,
46409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// which causes the bridge to get disconnected from the WebSocket and deleted if there is no other reference.
465c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)bool Bridge::waitForMethodCompletion(PassOwnPtr<ExecutionContextTask> task)
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
467323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    ASSERT(m_workerGlobalScope);
468323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    ASSERT(m_syncHelper);
469323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
470323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    m_loaderProxy.postTaskToLoader(task);
47109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
4725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // We wait for the syncHelper event even if a shutdown event is fired.
4735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // See https://codereview.chromium.org/267323004/#msg43 for why we need to wait this.
474a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack);
475c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_syncHelper->wait();
4765d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // This is checking whether a shutdown event is fired or not.
477c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return !m_workerGlobalScope->thread()->terminated();
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
480c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void Bridge::trace(Visitor* visitor)
481197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
4829e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    visitor->trace(m_client);
483197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    visitor->trace(m_workerGlobalScope);
484197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    visitor->trace(m_syncHelper);
485197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    visitor->trace(m_peer);
486197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
487197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
488c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
489