Home | History | Annotate | Download | only in websockets
      1 /*
      2  * Copyright (C) 2011 Google Inc.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #ifndef WorkerThreadableWebSocketChannel_h
     32 #define WorkerThreadableWebSocketChannel_h
     33 
     34 #include "core/page/ConsoleTypes.h"
     35 #include "core/workers/WorkerGlobalScope.h"
     36 #include "modules/websockets/WebSocketChannel.h"
     37 #include "modules/websockets/WebSocketChannelClient.h"
     38 
     39 #include "wtf/PassOwnPtr.h"
     40 #include "wtf/PassRefPtr.h"
     41 #include "wtf/RefCounted.h"
     42 #include "wtf/RefPtr.h"
     43 #include "wtf/Threading.h"
     44 #include "wtf/Vector.h"
     45 #include "wtf/text/WTFString.h"
     46 
     47 namespace WebCore {
     48 
     49 class KURL;
     50 class ScriptExecutionContext;
     51 class ThreadableWebSocketChannelClientWrapper;
     52 class WorkerGlobalScope;
     53 class WorkerLoaderProxy;
     54 class WorkerRunLoop;
     55 
     56 class WorkerThreadableWebSocketChannel : public RefCounted<WorkerThreadableWebSocketChannel>, public WebSocketChannel {
     57     WTF_MAKE_FAST_ALLOCATED;
     58 public:
     59     static PassRefPtr<WebSocketChannel> create(WorkerGlobalScope* workerGlobalScope, WebSocketChannelClient* client, const String& taskMode)
     60     {
     61         return adoptRef(new WorkerThreadableWebSocketChannel(workerGlobalScope, client, taskMode));
     62     }
     63     virtual ~WorkerThreadableWebSocketChannel();
     64 
     65     // WebSocketChannel functions.
     66     virtual void connect(const KURL&, const String& protocol) OVERRIDE;
     67     virtual String subprotocol() OVERRIDE;
     68     virtual String extensions() OVERRIDE;
     69     virtual WebSocketChannel::SendResult send(const String& message) OVERRIDE;
     70     virtual WebSocketChannel::SendResult send(const ArrayBuffer&, unsigned byteOffset, unsigned byteLength) OVERRIDE;
     71     virtual WebSocketChannel::SendResult send(const Blob&) OVERRIDE;
     72     virtual unsigned long bufferedAmount() const OVERRIDE;
     73     virtual void close(int code, const String& reason) OVERRIDE;
     74     virtual void fail(const String& reason, MessageLevel, const String&, unsigned) OVERRIDE;
     75     virtual void disconnect() OVERRIDE; // Will suppress didClose().
     76     virtual void suspend() OVERRIDE;
     77     virtual void resume() OVERRIDE;
     78 
     79     // Generated by the bridge. The Peer and its bridge should have identical
     80     // lifetimes.
     81     class Peer : public WebSocketChannelClient {
     82         WTF_MAKE_NONCOPYABLE(Peer); WTF_MAKE_FAST_ALLOCATED;
     83     public:
     84         // sourceURLAtConnection and lineNumberAtConnection parameters may
     85         // be shown when the connection fails.
     86         static Peer* create(PassRefPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, WorkerLoaderProxy& loaderProxy, ScriptExecutionContext* context, const String& taskMode, const String& sourceURLAtConnection, unsigned lineNumberAtConnection)
     87         {
     88             return new Peer(clientWrapper, loaderProxy, context, taskMode, sourceURLAtConnection, lineNumberAtConnection);
     89         }
     90         ~Peer();
     91 
     92         void connect(const KURL&, const String& protocol);
     93         void send(const String& message);
     94         void send(const ArrayBuffer&);
     95         void send(const Blob&);
     96         void bufferedAmount();
     97         void close(int code, const String& reason);
     98         void fail(const String& reason, MessageLevel, const String& sourceURL, unsigned lineNumber);
     99         void disconnect();
    100         void suspend();
    101         void resume();
    102 
    103         // WebSocketChannelClient functions.
    104         virtual void didConnect() OVERRIDE;
    105         virtual void didReceiveMessage(const String& message) OVERRIDE;
    106         virtual void didReceiveBinaryData(PassOwnPtr<Vector<char> >) OVERRIDE;
    107         virtual void didUpdateBufferedAmount(unsigned long bufferedAmount) OVERRIDE;
    108         virtual void didStartClosingHandshake() OVERRIDE;
    109         virtual void didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus, unsigned short code, const String& reason) OVERRIDE;
    110         virtual void didReceiveMessageError() OVERRIDE;
    111 
    112     private:
    113         Peer(PassRefPtr<ThreadableWebSocketChannelClientWrapper>, WorkerLoaderProxy&, ScriptExecutionContext*, const String& taskMode, const String& sourceURL, unsigned lineNumber);
    114 
    115         RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper;
    116         WorkerLoaderProxy& m_loaderProxy;
    117         RefPtr<WebSocketChannel> m_mainWebSocketChannel;
    118         String m_taskMode;
    119     };
    120 
    121     using RefCounted<WorkerThreadableWebSocketChannel>::ref;
    122     using RefCounted<WorkerThreadableWebSocketChannel>::deref;
    123 
    124 protected:
    125     // WebSocketChannel functions.
    126     virtual void refWebSocketChannel() OVERRIDE { ref(); }
    127     virtual void derefWebSocketChannel() OVERRIDE { deref(); }
    128 
    129 private:
    130     // Bridge for Peer. Running on the worker thread.
    131     class Bridge : public RefCounted<Bridge> {
    132     public:
    133         static PassRefPtr<Bridge> create(PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, PassRefPtr<WorkerGlobalScope> workerGlobalScope, const String& taskMode)
    134         {
    135             return adoptRef(new Bridge(workerClientWrapper, workerGlobalScope, taskMode));
    136         }
    137         ~Bridge();
    138         // sourceURLAtConnection and lineNumberAtConnection parameters may
    139         // be shown when the connection fails.
    140         void initialize(const String& sourceURLAtConnection, unsigned lineNumberAtConnection);
    141         void connect(const KURL&, const String& protocol);
    142         WebSocketChannel::SendResult send(const String& message);
    143         WebSocketChannel::SendResult send(const ArrayBuffer&, unsigned byteOffset, unsigned byteLength);
    144         WebSocketChannel::SendResult send(const Blob&);
    145         unsigned long bufferedAmount();
    146         void close(int code, const String& reason);
    147         void fail(const String& reason, MessageLevel, const String& sourceURL, unsigned lineNumber);
    148         void disconnect();
    149         void suspend();
    150         void resume();
    151 
    152         using RefCounted<Bridge>::ref;
    153         using RefCounted<Bridge>::deref;
    154 
    155     private:
    156         Bridge(PassRefPtr<ThreadableWebSocketChannelClientWrapper>, PassRefPtr<WorkerGlobalScope>, const String& taskMode);
    157 
    158         static void setWebSocketChannel(ScriptExecutionContext*, Bridge* thisPtr, Peer*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>);
    159 
    160         // Executed on the main thread to create a Peer for this bridge.
    161         // sourceURL and lineNumber provides the source filename and
    162         // the line number information at the connection initiation
    163         // respectively. They may be shown when the connection fails.
    164         static void mainThreadInitialize(ScriptExecutionContext*, WorkerLoaderProxy*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>, const String& taskMode, const String& sourceURL, unsigned lineNumber);
    165 
    166         // Executed on the worker context's thread.
    167         void clearClientWrapper();
    168 
    169         void setMethodNotCompleted();
    170         void waitForMethodCompletion();
    171 
    172         RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper;
    173         RefPtr<WorkerGlobalScope> m_workerGlobalScope;
    174         WorkerLoaderProxy& m_loaderProxy;
    175         String m_taskMode;
    176         Peer* m_peer;
    177     };
    178 
    179     WorkerThreadableWebSocketChannel(WorkerGlobalScope*, WebSocketChannelClient*, const String& taskMode);
    180 
    181     static void mainThreadConnect(ScriptExecutionContext*, Peer*, const KURL&, const String& protocol);
    182     static void mainThreadSend(ScriptExecutionContext*, Peer*, const String& message);
    183     static void mainThreadSendArrayBuffer(ScriptExecutionContext*, Peer*, PassOwnPtr<Vector<char> >);
    184     static void mainThreadSendBlob(ScriptExecutionContext*, Peer*, const KURL&, const String& type, long long size);
    185     static void mainThreadBufferedAmount(ScriptExecutionContext*, Peer*);
    186     static void mainThreadClose(ScriptExecutionContext*, Peer*, int code, const String& reason);
    187     static void mainThreadFail(ScriptExecutionContext*, Peer*, const String& reason, MessageLevel, const String& sourceURL, unsigned lineNumber);
    188     static void mainThreadDestroy(ScriptExecutionContext*, PassOwnPtr<Peer>);
    189     static void mainThreadSuspend(ScriptExecutionContext*, Peer*);
    190     static void mainThreadResume(ScriptExecutionContext*, Peer*);
    191 
    192     class WorkerGlobalScopeDidInitializeTask;
    193 
    194     RefPtr<WorkerGlobalScope> m_workerGlobalScope;
    195     RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper;
    196     RefPtr<Bridge> m_bridge;
    197     String m_sourceURLAtConnection;
    198     unsigned m_lineNumberAtConnection;
    199 };
    200 
    201 } // namespace WebCore
    202 
    203 #endif // WorkerThreadableWebSocketChannel_h
    204