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 | #pragma once |
32 | |
33 | #include "ThreadableWebSocketChannel.h" |
34 | #include "WebSocketChannelClient.h" |
35 | #include "WorkerGlobalScope.h" |
36 | #include <wtf/RefCounted.h> |
37 | #include <wtf/RefPtr.h> |
38 | #include <wtf/text/WTFString.h> |
39 | |
40 | namespace WebCore { |
41 | |
42 | class ScriptExecutionContext; |
43 | class ThreadableWebSocketChannelClientWrapper; |
44 | class WorkerGlobalScope; |
45 | class WorkerLoaderProxy; |
46 | class WorkerRunLoop; |
47 | |
48 | class WorkerThreadableWebSocketChannel : public RefCounted<WorkerThreadableWebSocketChannel>, public ThreadableWebSocketChannel { |
49 | WTF_MAKE_FAST_ALLOCATED; |
50 | public: |
51 | static Ref<ThreadableWebSocketChannel> create(WorkerGlobalScope& workerGlobalScope, WebSocketChannelClient& client, const String& taskMode, SocketProvider& provider) |
52 | { |
53 | return adoptRef(*new WorkerThreadableWebSocketChannel(workerGlobalScope, client, taskMode, provider)); |
54 | } |
55 | virtual ~WorkerThreadableWebSocketChannel(); |
56 | |
57 | // ThreadableWebSocketChannel functions. |
58 | void connect(const URL&, const String& protocol) override; |
59 | String subprotocol() override; |
60 | String extensions() override; |
61 | ThreadableWebSocketChannel::SendResult send(const String& message) override; |
62 | ThreadableWebSocketChannel::SendResult send(const JSC::ArrayBuffer&, unsigned byteOffset, unsigned byteLength) override; |
63 | ThreadableWebSocketChannel::SendResult send(Blob&) override; |
64 | unsigned bufferedAmount() const override; |
65 | void close(int code, const String& reason) override; |
66 | void fail(const String& reason) override; |
67 | void disconnect() override; // Will suppress didClose(). |
68 | void suspend() override; |
69 | void resume() override; |
70 | |
71 | // Generated by the bridge. The Peer and its bridge should have identical |
72 | // lifetimes. |
73 | class Peer : public WebSocketChannelClient { |
74 | WTF_MAKE_NONCOPYABLE(Peer); WTF_MAKE_FAST_ALLOCATED; |
75 | public: |
76 | Peer(Ref<ThreadableWebSocketChannelClientWrapper>&&, WorkerLoaderProxy&, ScriptExecutionContext&, const String& taskMode, SocketProvider&); |
77 | ~Peer(); |
78 | |
79 | void connect(const URL&, const String& protocol); |
80 | void send(const String& message); |
81 | void send(const JSC::ArrayBuffer&); |
82 | void send(Blob&); |
83 | void bufferedAmount(); |
84 | void close(int code, const String& reason); |
85 | void fail(const String& reason); |
86 | void disconnect(); |
87 | void suspend(); |
88 | void resume(); |
89 | |
90 | // WebSocketChannelClient functions. |
91 | void didConnect() final; |
92 | void didReceiveMessage(const String& message) final; |
93 | void didReceiveBinaryData(Vector<uint8_t>&&) final; |
94 | void didUpdateBufferedAmount(unsigned bufferedAmount) final; |
95 | void didStartClosingHandshake() final; |
96 | void didClose(unsigned unhandledBufferedAmount, ClosingHandshakeCompletionStatus, unsigned short code, const String& reason) final; |
97 | void didReceiveMessageError() final; |
98 | void didUpgradeURL() final; |
99 | |
100 | private: |
101 | Ref<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; |
102 | WorkerLoaderProxy& m_loaderProxy; |
103 | RefPtr<ThreadableWebSocketChannel> m_mainWebSocketChannel; |
104 | String m_taskMode; |
105 | }; |
106 | |
107 | using RefCounted<WorkerThreadableWebSocketChannel>::ref; |
108 | using RefCounted<WorkerThreadableWebSocketChannel>::deref; |
109 | |
110 | protected: |
111 | void refThreadableWebSocketChannel() override { ref(); } |
112 | void derefThreadableWebSocketChannel() override { deref(); } |
113 | |
114 | private: |
115 | // Bridge for Peer. Running on the worker thread. |
116 | class Bridge : public RefCounted<Bridge> { |
117 | public: |
118 | static Ref<Bridge> create(Ref<ThreadableWebSocketChannelClientWrapper>&& workerClientWrapper, Ref<WorkerGlobalScope>&& workerGlobalScope, const String& taskMode, Ref<SocketProvider>&& provider) |
119 | { |
120 | return adoptRef(*new Bridge(WTFMove(workerClientWrapper), WTFMove(workerGlobalScope), taskMode, WTFMove(provider))); |
121 | } |
122 | ~Bridge(); |
123 | void initialize(); |
124 | void connect(const URL&, const String& protocol); |
125 | ThreadableWebSocketChannel::SendResult send(const String& message); |
126 | ThreadableWebSocketChannel::SendResult send(const JSC::ArrayBuffer&, unsigned byteOffset, unsigned byteLength); |
127 | ThreadableWebSocketChannel::SendResult send(Blob&); |
128 | unsigned bufferedAmount(); |
129 | void close(int code, const String& reason); |
130 | void fail(const String& reason); |
131 | void disconnect(); |
132 | void suspend(); |
133 | void resume(); |
134 | |
135 | using RefCounted<Bridge>::ref; |
136 | using RefCounted<Bridge>::deref; |
137 | |
138 | private: |
139 | Bridge(Ref<ThreadableWebSocketChannelClientWrapper>&&, Ref<WorkerGlobalScope>&&, const String& taskMode, Ref<SocketProvider>&&); |
140 | |
141 | static void setWebSocketChannel(ScriptExecutionContext*, Bridge* thisPtr, Peer*, Ref<ThreadableWebSocketChannelClientWrapper>&&); |
142 | |
143 | // Executed on the main thread to create a Peer for this bridge. |
144 | static void mainThreadInitialize(ScriptExecutionContext&, WorkerLoaderProxy&, Ref<ThreadableWebSocketChannelClientWrapper>&&, const String& taskMode, Ref<SocketProvider>&&); |
145 | |
146 | // Executed on the worker context's thread. |
147 | void clearClientWrapper(); |
148 | |
149 | void setMethodNotCompleted(); |
150 | void waitForMethodCompletion(); |
151 | |
152 | Ref<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; |
153 | RefPtr<WorkerGlobalScope> m_workerGlobalScope; |
154 | WorkerLoaderProxy& m_loaderProxy; |
155 | String m_taskMode; |
156 | Peer* m_peer { nullptr }; |
157 | Ref<SocketProvider> m_socketProvider; |
158 | }; |
159 | |
160 | WEBCORE_EXPORT WorkerThreadableWebSocketChannel(WorkerGlobalScope&, WebSocketChannelClient&, const String& taskMode, SocketProvider&); |
161 | |
162 | class WorkerGlobalScopeDidInitializeTask; |
163 | |
164 | Ref<WorkerGlobalScope> m_workerGlobalScope; |
165 | Ref<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; |
166 | RefPtr<Bridge> m_bridge; |
167 | Ref<SocketProvider> m_socketProvider; |
168 | }; |
169 | |
170 | } // namespace WebCore |
171 | |