Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: webkit/plugins/ppapi/ppb_websocket_impl.cc

Issue 8698007: Revert r111596 "WebSocket Pepper API: in process API implementation" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/plugins/ppapi/ppb_websocket_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/plugins/ppapi/ppb_websocket_impl.h" 5 #include "webkit/plugins/ppapi/ppb_websocket_impl.h"
6 6
7 #include <string>
8
9 #include "base/logging.h"
10 #include "googleurl/src/gurl.h"
11 #include "net/base/net_util.h"
12 #include "ppapi/c/pp_completion_callback.h"
13 #include "ppapi/c/pp_errors.h" 7 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/c/pp_var.h" 8 #include "ppapi/c/pp_var.h"
15 #include "ppapi/c/ppb_var.h"
16 #include "ppapi/cpp/module.h"
17 #include "ppapi/shared_impl/var.h"
18 #include "ppapi/shared_impl/var_tracker.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSocket.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
26 #include "webkit/plugins/ppapi/host_globals.h"
27 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
28 #include "webkit/plugins/ppapi/resource_helper.h"
29 9
30 using ppapi::PpapiGlobals;
31 using ppapi::StringVar;
32 using ppapi::thunk::PPB_WebSocket_API; 10 using ppapi::thunk::PPB_WebSocket_API;
33 using ppapi::VarTracker;
34 using WebKit::WebData;
35 using WebKit::WebDocument;
36 using WebKit::WebString;
37 using WebKit::WebSocket;
38 using WebKit::WebSocketClient;
39 using WebKit::WebURL;
40
41 static const uint32_t kMaxReasonSizeInBytes = 123;
42 11
43 namespace webkit { 12 namespace webkit {
44 namespace ppapi { 13 namespace ppapi {
45 14
46 PPB_WebSocket_Impl::PPB_WebSocket_Impl(PP_Instance instance) 15 PPB_WebSocket_Impl::PPB_WebSocket_Impl(PP_Instance instance)
47 : Resource(instance), 16 : Resource(instance) {
48 state_(PP_WEBSOCKETREADYSTATE_INVALID_DEV),
49 receive_callback_var_(NULL),
50 wait_for_receive_(false),
51 close_code_(0),
52 close_was_clean_(PP_FALSE) {
53 empty_string_ = new StringVar(
54 PpapiGlobals::Get()->GetModuleForInstance(instance), "", 0);
55 } 17 }
56 18
57 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() { 19 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() {
58 if (websocket_.get())
59 websocket_->disconnect();
60
61 // Clean up received and unread messages
62 VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
63 while (!received_messages_.empty()) {
64 PP_Var var = received_messages_.front();
65 received_messages_.pop();
66 var_tracker->ReleaseVar(var);
67 }
68 } 20 }
69 21
70 // static 22 // static
71 PP_Resource PPB_WebSocket_Impl::Create(PP_Instance instance) { 23 PP_Resource PPB_WebSocket_Impl::Create(PP_Instance instance) {
72 scoped_refptr<PPB_WebSocket_Impl> ws(new PPB_WebSocket_Impl(instance)); 24 scoped_refptr<PPB_WebSocket_Impl> ws(new PPB_WebSocket_Impl(instance));
73 return ws->GetReference(); 25 return ws->GetReference();
74 } 26 }
75 27
76 PPB_WebSocket_API* PPB_WebSocket_Impl::AsPPB_WebSocket_API() { 28 PPB_WebSocket_API* PPB_WebSocket_Impl::AsPPB_WebSocket_API() {
77 return this; 29 return this;
78 } 30 }
79 31
80 int32_t PPB_WebSocket_Impl::Connect(PP_Var url, 32 int32_t PPB_WebSocket_Impl::Connect(PP_Var url,
81 const PP_Var protocols[], 33 const PP_Var protocols[],
82 uint32_t protocol_count, 34 uint32_t protocol_count,
83 PP_CompletionCallback callback) { 35 PP_CompletionCallback callback) {
84 // Check mandatory interfaces. 36 // TODO(toyoshim): Implement it.
85 PluginInstance* plugin_instance = ResourceHelper::GetPluginInstance(this); 37 return PP_ERROR_NOTSUPPORTED;
86 DCHECK(plugin_instance);
87 if (!plugin_instance)
88 return PP_ERROR_FAILED;
89
90 // Connect() can be called at most once.
91 if (websocket_.get())
92 return PP_ERROR_INPROGRESS;
93 if (state_ != PP_WEBSOCKETREADYSTATE_INVALID_DEV)
94 return PP_ERROR_INPROGRESS;
95 state_ = PP_WEBSOCKETREADYSTATE_CLOSED_DEV;
96
97 // Validate |callback| (Doesn't support blocking callback)
98 if (!callback.func)
99 return PP_ERROR_BLOCKS_MAIN_THREAD;
100
101 // Validate url and convert it to WebURL.
102 scoped_refptr<StringVar> url_string = StringVar::FromPPVar(url);
103 if (!url_string)
104 return PP_ERROR_BADARGUMENT;
105 GURL gurl(url_string->value());
106 if (!gurl.is_valid())
107 return PP_ERROR_BADARGUMENT;
108 if (!gurl.SchemeIs("ws") && !gurl.SchemeIs("wss"))
109 return PP_ERROR_BADARGUMENT;
110 if (gurl.has_ref())
111 return PP_ERROR_BADARGUMENT;
112 if (!net::IsPortAllowedByDefault(gurl.IntPort()))
113 return PP_ERROR_BADARGUMENT;
114 WebURL web_url(gurl);
115
116 // Validate protocols and convert it to WebString.
117 // TODO(toyoshim): Detect duplicated protocols as error.
118 std::string protocol_string;
119 for (uint32_t i = 0; i < protocol_count; i++) {
120 // TODO(toyoshim): Similar function exist in WebKit::WebSocket.
121 // We must rearrange them into WebKit::WebChannel and share its protocol
122 // related implementation via WebKit API.
123 scoped_refptr<StringVar> string_var;
124 string_var = StringVar::FromPPVar(protocols[i]);
125 if (!string_var || !string_var->value().length())
126 return PP_ERROR_BADARGUMENT;
127 for (std::string::const_iterator it = string_var->value().begin();
128 it != string_var->value().end();
129 ++it) {
130 uint8_t character = static_cast<uint8_t>(*it);
131 // WebSocket specification says "(Subprotocol string must consist of)
132 // characters in the range U+0021 to U+007E not including separator
133 // characters as defined in [RFC2616]."
134 const uint8_t minimumProtocolCharacter = '!'; // U+0021.
135 const uint8_t maximumProtocolCharacter = '~'; // U+007E.
136 if (character < minimumProtocolCharacter ||
137 character > maximumProtocolCharacter ||
138 character == '"' || character == '(' || character == ')' ||
139 character == ',' || character == '/' ||
140 (character >= ':' && character <= '@') || // U+003A - U+0040
141 (character >= '[' && character <= ']') || // U+005B - u+005D
142 character == '{' || character == '}')
143 return PP_ERROR_BADARGUMENT;
144 }
145 if (i != 0)
146 protocol_string.append(",");
147 protocol_string.append(string_var->value());
148 }
149 WebString web_protocols = WebString::fromUTF8(protocol_string);
150
151 // Create WebKit::WebSocket object.
152 WebDocument document = plugin_instance->container()->element().document();
153 websocket_.reset(WebSocket::create(document, this));
154 DCHECK(websocket_.get());
155 if (!websocket_.get())
156 return PP_ERROR_NOTSUPPORTED;
157
158 websocket_->connect(web_url, web_protocols);
159 state_ = PP_WEBSOCKETREADYSTATE_CONNECTING_DEV;
160
161 // Install callback.
162 connect_callback_ = callback;
163
164 return PP_OK_COMPLETIONPENDING;
165 } 38 }
166 39
167 int32_t PPB_WebSocket_Impl::Close(uint16_t code, 40 int32_t PPB_WebSocket_Impl::Close(uint16_t code,
168 PP_Var reason, 41 PP_Var reason,
169 PP_CompletionCallback callback) { 42 PP_CompletionCallback callback) {
170 // Check mandarory interfaces. 43 // TODO(toyoshim): Implement it.
171 if (!websocket_.get()) 44 return PP_ERROR_NOTSUPPORTED;
172 return PP_ERROR_FAILED;
173
174 // Validate |callback| (Doesn't support blocking callback)
175 if (!callback.func)
176 return PP_ERROR_BLOCKS_MAIN_THREAD;
177
178 // Validate |code|.
179 if (code != WebSocket::CloseEventCodeNotSpecified) {
180 if (!(code == WebSocket::CloseEventCodeNormalClosure ||
181 (WebSocket::CloseEventCodeMinimumUserDefined <= code &&
182 code <= WebSocket::CloseEventCodeMaximumUserDefined)))
183 return PP_ERROR_NOACCESS;
184 }
185 // Validate |reason|.
186 // TODO(toyoshim): Returns PP_ERROR_BADARGUMENT if |reason| contains any
187 // surrogates.
188 scoped_refptr<StringVar> reason_string = StringVar::FromPPVar(reason);
189 if (!reason_string || reason_string->value().size() > kMaxReasonSizeInBytes)
190 return PP_ERROR_BADARGUMENT;
191
192 // Check state.
193 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV ||
194 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV)
195 return PP_ERROR_INPROGRESS;
196
197 // Install |callback|.
198 close_callback_ = callback;
199
200 if (state_ == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) {
201 state_ = PP_WEBSOCKETREADYSTATE_CLOSING_DEV;
202 PP_RunAndClearCompletionCallback(&connect_callback_, PP_ERROR_ABORTED);
203 websocket_->fail(
204 "WebSocket was closed before the connection was established.");
205 return PP_OK_COMPLETIONPENDING;
206 }
207
208 // TODO(toyoshim): Handle bufferedAmount here.
209
210 state_ = PP_WEBSOCKETREADYSTATE_CLOSING_DEV;
211 WebString web_reason = WebString::fromUTF8(reason_string->value());
212 websocket_->close(code, web_reason);
213
214 return PP_OK_COMPLETIONPENDING;
215 } 45 }
216 46
217 int32_t PPB_WebSocket_Impl::ReceiveMessage(PP_Var* message, 47 int32_t PPB_WebSocket_Impl::ReceiveMessage(PP_Var* message,
218 PP_CompletionCallback callback) { 48 PP_CompletionCallback callback) {
219 // Check state. 49 // TODO(toyoshim): Implement it.
220 if (state_ == PP_WEBSOCKETREADYSTATE_INVALID_DEV || 50 return PP_ERROR_NOTSUPPORTED;
221 state_ == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV)
222 return PP_ERROR_BADARGUMENT;
223
224 // Just return received message if any received message is queued.
225 if (!received_messages_.empty())
226 return DoReceive();
227
228 // Or retain |message| as buffer to store and install |callback|.
229 wait_for_receive_ = true;
230 receive_callback_var_ = message;
231 receive_callback_ = callback;
232
233 return PP_OK_COMPLETIONPENDING;
234 } 51 }
235 52
236 int32_t PPB_WebSocket_Impl::SendMessage(PP_Var message) { 53 int32_t PPB_WebSocket_Impl::SendMessage(PP_Var message) {
237 // Check mandatory interfaces. 54 // TODO(toyoshim): Implement it.
238 if (!websocket_.get()) 55 return PP_ERROR_NOTSUPPORTED;
239 return PP_ERROR_FAILED;
240
241 // Check state.
242 if (state_ == PP_WEBSOCKETREADYSTATE_INVALID_DEV ||
243 state_ == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV)
244 return PP_ERROR_BADARGUMENT;
245
246 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV ||
247 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) {
248 // TODO(toyoshim): Handle bufferedAmount here.
249 }
250
251 if (message.type != PP_VARTYPE_STRING) {
252 // TODO(toyoshim): Support binary data.
253 return PP_ERROR_NOTSUPPORTED;
254 }
255
256 // Convert message to WebString.
257 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message);
258 if (!message_string)
259 return PP_ERROR_BADARGUMENT;
260 WebString web_message = WebString::fromUTF8(message_string->value());
261 if (!websocket_->sendText(web_message))
262 return PP_ERROR_BADARGUMENT;
263
264 return PP_OK;
265 } 56 }
266 57
267 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() { 58 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() {
268 // TODO(toyoshim): Implement. 59 // TODO(toyoshim): Implement it.
269 return 0; 60 return 0;
270 } 61 }
271 62
272 uint16_t PPB_WebSocket_Impl::GetCloseCode() { 63 uint16_t PPB_WebSocket_Impl::GetCloseCode() {
273 return close_code_; 64 // TODO(toyoshim): Implement it.
65 return 0;
274 } 66 }
275 67
276 PP_Var PPB_WebSocket_Impl::GetCloseReason() { 68 PP_Var PPB_WebSocket_Impl::GetCloseReason() {
277 if (!close_reason_) 69 // TODO(toyoshim): Implement it.
278 return empty_string_->GetPPVar(); 70 return PP_MakeUndefined();
279 return close_reason_->GetPPVar();
280 } 71 }
281 72
282 PP_Bool PPB_WebSocket_Impl::GetCloseWasClean() { 73 PP_Bool PPB_WebSocket_Impl::GetCloseWasClean() {
283 return close_was_clean_; 74 // TODO(toyoshim): Implement it.
75 return PP_FALSE;
284 } 76 }
285 77
286 PP_Var PPB_WebSocket_Impl::GetExtensions() { 78 PP_Var PPB_WebSocket_Impl::GetExtensions() {
287 // TODO(toyoshim): For now, always returns empty string. 79 // TODO(toyoshim): Implement it.
288 if (!extensions_) 80 return PP_MakeUndefined();
289 return empty_string_->GetPPVar();
290 return extensions_->GetPPVar();
291 } 81 }
292 82
293 PP_Var PPB_WebSocket_Impl::GetProtocol() { 83 PP_Var PPB_WebSocket_Impl::GetProtocol() {
294 // TODO(toyoshim): Implement. 84 // TODO(toyoshim): Implement it.
295 if (!protocol_) 85 return PP_MakeUndefined();
296 return empty_string_->GetPPVar();
297 return protocol_->GetPPVar();
298 } 86 }
299 87
300 PP_WebSocketReadyState_Dev PPB_WebSocket_Impl::GetReadyState() { 88 PP_WebSocketReadyState_Dev PPB_WebSocket_Impl::GetReadyState() {
301 return state_; 89 // TODO(toyoshim): Implement it.
90 return PP_WEBSOCKETREADYSTATE_INVALID_DEV;
302 } 91 }
303 92
304 PP_Var PPB_WebSocket_Impl::GetURL() { 93 PP_Var PPB_WebSocket_Impl::GetURL() {
305 // TODO(toyoshim): For now, always returns empty string. 94 // TODO(toyoshim): Implement it.
306 if (!url_) 95 return PP_MakeUndefined();
307 return empty_string_->GetPPVar();
308 return url_->GetPPVar();
309 }
310
311 void PPB_WebSocket_Impl::didConnect() {
312 DCHECK_EQ(PP_WEBSOCKETREADYSTATE_CONNECTING_DEV, state_);
313 state_ = PP_WEBSOCKETREADYSTATE_OPEN_DEV;
314 PP_RunAndClearCompletionCallback(&connect_callback_, PP_OK);
315 }
316
317 void PPB_WebSocket_Impl::didReceiveMessage(const WebString& message) {
318 // Append received data to queue.
319 std::string string = message.utf8();
320 PP_Var var = StringVar::StringToPPVar(
321 PpapiGlobals::Get()->GetModuleForInstance(pp_instance()), string);
322 received_messages_.push(var);
323
324 if (!wait_for_receive_)
325 return;
326
327 PP_RunAndClearCompletionCallback(&receive_callback_, DoReceive());
328 }
329
330 void PPB_WebSocket_Impl::didReceiveBinaryData(const WebData& binaryData) {
331 DLOG(INFO) << "didReceiveBinaryData is not implemented yet.";
332 // TODO(toyoshim): Support to receive binary data.
333 }
334
335 void PPB_WebSocket_Impl::didReceiveMessageError() {
336 // TODO(toyoshim): Must implement.
337 DLOG(INFO) << "didReceiveMessageError is not implemented yet.";
338 }
339
340 void PPB_WebSocket_Impl::didStartClosingHandshake() {
341 // TODO(toyoshim): Must implement.
342 DLOG(INFO) << "didStartClosingHandshake is not implemented yet.";
343 }
344
345 void PPB_WebSocket_Impl::didClose(unsigned long bufferedAmount,
346 ClosingHandshakeCompletionStatus status,
347 unsigned short code,
348 const WebString& reason) {
349 // Store code and reason.
350 close_code_ = code;
351 std::string reason_string = reason.utf8();
352 close_reason_ = new StringVar(
353 PpapiGlobals::Get()->GetModuleForInstance(pp_instance()), reason_string);
354
355 // TODO(toyoshim): Set close_was_clean_.
356
357 // Handle state transition and invoking callback.
358 DCHECK_NE(PP_WEBSOCKETREADYSTATE_CLOSED_DEV, state_);
359 PP_WebSocketReadyState_Dev state = state_;
360 state_ = PP_WEBSOCKETREADYSTATE_CLOSED_DEV;
361
362 if (state == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV)
363 PP_RunAndClearCompletionCallback(&connect_callback_, PP_OK);
364
365 if (state == PP_WEBSOCKETREADYSTATE_CLOSING_DEV)
366 PP_RunAndClearCompletionCallback(&close_callback_, PP_OK);
367 }
368
369 int32_t PPB_WebSocket_Impl::DoReceive() {
370 // TODO(toyoshim): Check state.
371
372 if (!receive_callback_var_)
373 return PP_OK;
374
375 *receive_callback_var_ = received_messages_.front();
376 received_messages_.pop();
377 receive_callback_var_ = NULL;
378 wait_for_receive_ = false;
379 return PP_OK;
380 } 96 }
381 97
382 } // namespace ppapi 98 } // namespace ppapi
383 } // namespace webkit 99 } // namespace webkit
OLDNEW
« no previous file with comments | « webkit/plugins/ppapi/ppb_websocket_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698