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

Side by Side Diff: content/browser/renderer_host/websocket_host.cc

Issue 2119973002: Port WebSockets to Mojo IPC (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove unused code Created 4 years, 5 months 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
OLDNEW
(Empty)
1 // Copyright 2013 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 "content/browser/renderer_host/websocket_host.h"
6
7 #include <inttypes.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/threading/thread_task_runner_handle.h"
21 #include "content/browser/bad_message.h"
22 #include "content/browser/renderer_host/websocket_blob_sender.h"
23 #include "content/browser/renderer_host/websocket_dispatcher_host.h"
24 #include "content/browser/ssl/ssl_error_handler.h"
25 #include "content/browser/ssl/ssl_manager.h"
26 #include "content/common/websocket_messages.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/render_frame_host.h"
29 #include "content/public/browser/storage_partition.h"
30 #include "ipc/ipc_message_macros.h"
31 #include "net/base/net_errors.h"
32 #include "net/http/http_request_headers.h"
33 #include "net/http/http_response_headers.h"
34 #include "net/http/http_util.h"
35 #include "net/ssl/ssl_info.h"
36 #include "net/websockets/websocket_channel.h"
37 #include "net/websockets/websocket_errors.h"
38 #include "net/websockets/websocket_event_interface.h"
39 #include "net/websockets/websocket_frame.h" // for WebSocketFrameHeader::OpCode
40 #include "net/websockets/websocket_handshake_request_info.h"
41 #include "net/websockets/websocket_handshake_response_info.h"
42 #include "url/origin.h"
43
44 namespace content {
45
46 namespace {
47
48 typedef net::WebSocketEventInterface::ChannelState ChannelState;
49
50 // Convert a content::WebSocketMessageType to a
51 // net::WebSocketFrameHeader::OpCode
52 net::WebSocketFrameHeader::OpCode MessageTypeToOpCode(
53 WebSocketMessageType type) {
54 DCHECK(type == WEB_SOCKET_MESSAGE_TYPE_CONTINUATION ||
55 type == WEB_SOCKET_MESSAGE_TYPE_TEXT ||
56 type == WEB_SOCKET_MESSAGE_TYPE_BINARY);
57 typedef net::WebSocketFrameHeader::OpCode OpCode;
58 // These compile asserts verify that the same underlying values are used for
59 // both types, so we can simply cast between them.
60 static_assert(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_CONTINUATION) ==
61 net::WebSocketFrameHeader::kOpCodeContinuation,
62 "enum values must match for opcode continuation");
63 static_assert(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_TEXT) ==
64 net::WebSocketFrameHeader::kOpCodeText,
65 "enum values must match for opcode text");
66 static_assert(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_BINARY) ==
67 net::WebSocketFrameHeader::kOpCodeBinary,
68 "enum values must match for opcode binary");
69 return static_cast<OpCode>(type);
70 }
71
72 WebSocketMessageType OpCodeToMessageType(
73 net::WebSocketFrameHeader::OpCode opCode) {
74 DCHECK(opCode == net::WebSocketFrameHeader::kOpCodeContinuation ||
75 opCode == net::WebSocketFrameHeader::kOpCodeText ||
76 opCode == net::WebSocketFrameHeader::kOpCodeBinary);
77 // This cast is guaranteed valid by the static_assert() statements above.
78 return static_cast<WebSocketMessageType>(opCode);
79 }
80
81 ChannelState StateCast(WebSocketDispatcherHost::WebSocketHostState host_state) {
82 const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_ALIVE =
83 WebSocketDispatcherHost::WEBSOCKET_HOST_ALIVE;
84 const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_DELETED =
85 WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED;
86
87 DCHECK(host_state == WEBSOCKET_HOST_ALIVE ||
88 host_state == WEBSOCKET_HOST_DELETED);
89 // These compile asserts verify that we can get away with using static_cast<>
90 // for the conversion.
91 static_assert(static_cast<ChannelState>(WEBSOCKET_HOST_ALIVE) ==
92 net::WebSocketEventInterface::CHANNEL_ALIVE,
93 "enum values must match for state_alive");
94 static_assert(static_cast<ChannelState>(WEBSOCKET_HOST_DELETED) ==
95 net::WebSocketEventInterface::CHANNEL_DELETED,
96 "enum values must match for state_deleted");
97 return static_cast<ChannelState>(host_state);
98 }
99
100 // Implementation of WebSocketBlobSender::Channel
101 class SendChannelImpl final : public WebSocketBlobSender::Channel {
102 public:
103 explicit SendChannelImpl(net::WebSocketChannel* channel)
104 : channel_(channel) {}
105
106 // Implementation of WebSocketBlobSender::Channel
107 size_t GetSendQuota() const override {
108 return static_cast<size_t>(channel_->current_send_quota());
109 }
110
111 ChannelState SendFrame(bool fin, const std::vector<char>& data) override {
112 int opcode = first_frame_ ? net::WebSocketFrameHeader::kOpCodeBinary
113 : net::WebSocketFrameHeader::kOpCodeContinuation;
114 first_frame_ = false;
115 return channel_->SendFrame(fin, opcode, data);
116 }
117
118 private:
119 net::WebSocketChannel* channel_;
120 bool first_frame_ = true;
121
122 DISALLOW_COPY_AND_ASSIGN(SendChannelImpl);
123 };
124
125 } // namespace
126
127 // Implementation of net::WebSocketEventInterface. Receives events from our
128 // WebSocketChannel object. Each event is translated to an IPC and sent to the
129 // renderer or child process via WebSocketDispatcherHost.
130 class WebSocketHost::WebSocketEventHandler final
131 : public net::WebSocketEventInterface {
132 public:
133 WebSocketEventHandler(WebSocketDispatcherHost* dispatcher,
134 WebSocketHost* host,
135 int routing_id,
136 int render_frame_id);
137 ~WebSocketEventHandler() override;
138
139 // net::WebSocketEventInterface implementation
140
141 ChannelState OnAddChannelResponse(const std::string& selected_subprotocol,
142 const std::string& extensions) override;
143 ChannelState OnDataFrame(bool fin,
144 WebSocketMessageType type,
145 const std::vector<char>& data) override;
146 ChannelState OnClosingHandshake() override;
147 ChannelState OnFlowControl(int64_t quota) override;
148 ChannelState OnDropChannel(bool was_clean,
149 uint16_t code,
150 const std::string& reason) override;
151 ChannelState OnFailChannel(const std::string& message) override;
152 ChannelState OnStartOpeningHandshake(
153 std::unique_ptr<net::WebSocketHandshakeRequestInfo> request) override;
154 ChannelState OnFinishOpeningHandshake(
155 std::unique_ptr<net::WebSocketHandshakeResponseInfo> response) override;
156 ChannelState OnSSLCertificateError(
157 std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
158 callbacks,
159 const GURL& url,
160 const net::SSLInfo& ssl_info,
161 bool fatal) override;
162
163 private:
164 class SSLErrorHandlerDelegate final : public SSLErrorHandler::Delegate {
165 public:
166 SSLErrorHandlerDelegate(
167 std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
168 callbacks);
169 ~SSLErrorHandlerDelegate() override;
170
171 base::WeakPtr<SSLErrorHandler::Delegate> GetWeakPtr();
172
173 // SSLErrorHandler::Delegate methods
174 void CancelSSLRequest(int error, const net::SSLInfo* ssl_info) override;
175 void ContinueSSLRequest() override;
176
177 private:
178 std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks_;
179 base::WeakPtrFactory<SSLErrorHandlerDelegate> weak_ptr_factory_;
180
181 DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerDelegate);
182 };
183
184 WebSocketDispatcherHost* const dispatcher_;
185 WebSocketHost* const host_;
186 const int routing_id_;
187 const int render_frame_id_;
188 std::unique_ptr<SSLErrorHandlerDelegate> ssl_error_handler_delegate_;
189
190 DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
191 };
192
193 WebSocketHost::WebSocketEventHandler::WebSocketEventHandler(
194 WebSocketDispatcherHost* dispatcher,
195 WebSocketHost* host,
196 int routing_id,
197 int render_frame_id)
198 : dispatcher_(dispatcher),
199 host_(host),
200 routing_id_(routing_id),
201 render_frame_id_(render_frame_id) {}
202
203 WebSocketHost::WebSocketEventHandler::~WebSocketEventHandler() {
204 DVLOG(1) << "WebSocketEventHandler destroyed routing_id=" << routing_id_;
205 }
206
207 ChannelState WebSocketHost::WebSocketEventHandler::OnAddChannelResponse(
208 const std::string& selected_protocol,
209 const std::string& extensions) {
210 DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse"
211 << " routing_id=" << routing_id_
212 << " selected_protocol=\"" << selected_protocol << "\""
213 << " extensions=\"" << extensions << "\"";
214
215 return StateCast(dispatcher_->SendAddChannelResponse(
216 routing_id_, selected_protocol, extensions));
217 }
218
219 ChannelState WebSocketHost::WebSocketEventHandler::OnDataFrame(
220 bool fin,
221 net::WebSocketFrameHeader::OpCode type,
222 const std::vector<char>& data) {
223 DVLOG(3) << "WebSocketEventHandler::OnDataFrame"
224 << " routing_id=" << routing_id_ << " fin=" << fin
225 << " type=" << type << " data is " << data.size() << " bytes";
226
227 return StateCast(dispatcher_->SendFrame(routing_id_, fin,
228 OpCodeToMessageType(type), data));
229 }
230
231 ChannelState WebSocketHost::WebSocketEventHandler::OnClosingHandshake() {
232 DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake"
233 << " routing_id=" << routing_id_;
234
235 return StateCast(dispatcher_->NotifyClosingHandshake(routing_id_));
236 }
237
238 ChannelState WebSocketHost::WebSocketEventHandler::OnFlowControl(
239 int64_t quota) {
240 DVLOG(3) << "WebSocketEventHandler::OnFlowControl"
241 << " routing_id=" << routing_id_ << " quota=" << quota;
242
243 if (host_->blob_sender_)
244 host_->blob_sender_->OnNewSendQuota();
245 return StateCast(dispatcher_->SendFlowControl(routing_id_, quota));
246 }
247
248 ChannelState WebSocketHost::WebSocketEventHandler::OnDropChannel(
249 bool was_clean,
250 uint16_t code,
251 const std::string& reason) {
252 DVLOG(3) << "WebSocketEventHandler::OnDropChannel"
253 << " routing_id=" << routing_id_ << " was_clean=" << was_clean
254 << " code=" << code << " reason=\"" << reason << "\"";
255
256 return StateCast(
257 dispatcher_->DoDropChannel(routing_id_, was_clean, code, reason));
258 }
259
260 ChannelState WebSocketHost::WebSocketEventHandler::OnFailChannel(
261 const std::string& message) {
262 DVLOG(3) << "WebSocketEventHandler::OnFailChannel"
263 << " routing_id=" << routing_id_ << " message=\"" << message << "\"";
264
265 return StateCast(dispatcher_->NotifyFailure(routing_id_, message));
266 }
267
268 ChannelState WebSocketHost::WebSocketEventHandler::OnStartOpeningHandshake(
269 std::unique_ptr<net::WebSocketHandshakeRequestInfo> request) {
270 bool should_send = dispatcher_->CanReadRawCookies();
271 DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake "
272 << "should_send=" << should_send;
273
274 if (!should_send)
275 return WebSocketEventInterface::CHANNEL_ALIVE;
276
277 WebSocketHandshakeRequest request_to_pass;
278 request_to_pass.url.Swap(&request->url);
279 net::HttpRequestHeaders::Iterator it(request->headers);
280 while (it.GetNext())
281 request_to_pass.headers.push_back(std::make_pair(it.name(), it.value()));
282 request_to_pass.headers_text =
283 base::StringPrintf("GET %s HTTP/1.1\r\n",
284 request_to_pass.url.spec().c_str()) +
285 request->headers.ToString();
286 request_to_pass.request_time = request->request_time;
287
288 return StateCast(
289 dispatcher_->NotifyStartOpeningHandshake(routing_id_, request_to_pass));
290 }
291
292 ChannelState WebSocketHost::WebSocketEventHandler::OnFinishOpeningHandshake(
293 std::unique_ptr<net::WebSocketHandshakeResponseInfo> response) {
294 bool should_send = dispatcher_->CanReadRawCookies();
295 DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake "
296 << "should_send=" << should_send;
297
298 if (!should_send)
299 return WebSocketEventInterface::CHANNEL_ALIVE;
300
301 WebSocketHandshakeResponse response_to_pass;
302 response_to_pass.url.Swap(&response->url);
303 response_to_pass.status_code = response->status_code;
304 response_to_pass.status_text.swap(response->status_text);
305 size_t iter = 0;
306 std::string name, value;
307 while (response->headers->EnumerateHeaderLines(&iter, &name, &value))
308 response_to_pass.headers.push_back(std::make_pair(name, value));
309 response_to_pass.headers_text =
310 net::HttpUtil::ConvertHeadersBackToHTTPResponse(
311 response->headers->raw_headers());
312 response_to_pass.response_time = response->response_time;
313
314 return StateCast(
315 dispatcher_->NotifyFinishOpeningHandshake(routing_id_, response_to_pass));
316 }
317
318 ChannelState WebSocketHost::WebSocketEventHandler::OnSSLCertificateError(
319 std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
320 const GURL& url,
321 const net::SSLInfo& ssl_info,
322 bool fatal) {
323 DVLOG(3) << "WebSocketEventHandler::OnSSLCertificateError"
324 << " routing_id=" << routing_id_ << " url=" << url.spec()
325 << " cert_status=" << ssl_info.cert_status << " fatal=" << fatal;
326 ssl_error_handler_delegate_.reset(
327 new SSLErrorHandlerDelegate(std::move(callbacks)));
328 SSLManager::OnSSLCertificateSubresourceError(
329 ssl_error_handler_delegate_->GetWeakPtr(), url,
330 dispatcher_->render_process_id(), render_frame_id_, ssl_info, fatal);
331 // The above method is always asynchronous.
332 return WebSocketEventInterface::CHANNEL_ALIVE;
333 }
334
335 WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
336 SSLErrorHandlerDelegate(
337 std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
338 callbacks)
339 : callbacks_(std::move(callbacks)), weak_ptr_factory_(this) {}
340
341 WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
342 ~SSLErrorHandlerDelegate() {}
343
344 base::WeakPtr<SSLErrorHandler::Delegate>
345 WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() {
346 return weak_ptr_factory_.GetWeakPtr();
347 }
348
349 void WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
350 CancelSSLRequest(int error, const net::SSLInfo* ssl_info) {
351 DVLOG(3) << "SSLErrorHandlerDelegate::CancelSSLRequest"
352 << " error=" << error
353 << " cert_status=" << (ssl_info ? ssl_info->cert_status
354 : static_cast<net::CertStatus>(-1));
355 callbacks_->CancelSSLRequest(error, ssl_info);
356 }
357
358 void WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
359 ContinueSSLRequest() {
360 DVLOG(3) << "SSLErrorHandlerDelegate::ContinueSSLRequest";
361 callbacks_->ContinueSSLRequest();
362 }
363
364 WebSocketHost::WebSocketHost(int routing_id,
365 WebSocketDispatcherHost* dispatcher,
366 net::URLRequestContext* url_request_context,
367 base::TimeDelta delay)
368 : dispatcher_(dispatcher),
369 url_request_context_(url_request_context),
370 routing_id_(routing_id),
371 delay_(delay),
372 pending_flow_control_quota_(0),
373 handshake_succeeded_(false),
374 weak_ptr_factory_(this) {
375 DVLOG(1) << "WebSocketHost: created routing_id=" << routing_id;
376 }
377
378 WebSocketHost::~WebSocketHost() {}
379
380 void WebSocketHost::GoAway() {
381 OnDropChannel(false, static_cast<uint16_t>(net::kWebSocketErrorGoingAway),
382 "");
383 }
384
385 bool WebSocketHost::OnMessageReceived(const IPC::Message& message) {
386 bool handled = true;
387 IPC_BEGIN_MESSAGE_MAP(WebSocketHost, message)
388 IPC_MESSAGE_HANDLER(WebSocketHostMsg_AddChannelRequest, OnAddChannelRequest)
389 IPC_MESSAGE_HANDLER(WebSocketHostMsg_SendBlob, OnSendBlob)
390 IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, OnSendFrame)
391 IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, OnFlowControl)
392 IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, OnDropChannel)
393 IPC_MESSAGE_UNHANDLED(handled = false)
394 IPC_END_MESSAGE_MAP()
395 return handled;
396 }
397
398 void WebSocketHost::OnAddChannelRequest(
399 const GURL& socket_url,
400 const std::vector<std::string>& requested_protocols,
401 const url::Origin& origin,
402 const std::string& user_agent_override,
403 int render_frame_id) {
404 DVLOG(3) << "WebSocketHost::OnAddChannelRequest"
405 << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
406 << "\" requested_protocols=\""
407 << base::JoinString(requested_protocols, ", ") << "\" origin=\""
408 << origin << "\" user_agent_override=\"" << user_agent_override
409 << "\"";
410
411 DCHECK(!channel_);
412 if (delay_ > base::TimeDelta()) {
413 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
414 FROM_HERE,
415 base::Bind(&WebSocketHost::AddChannel, weak_ptr_factory_.GetWeakPtr(),
416 socket_url, requested_protocols, origin,
417 user_agent_override, render_frame_id),
418 delay_);
419 } else {
420 AddChannel(socket_url, requested_protocols, origin,
421 user_agent_override, render_frame_id);
422 }
423 // |this| may have been deleted here.
424 }
425
426 void WebSocketHost::AddChannel(
427 const GURL& socket_url,
428 const std::vector<std::string>& requested_protocols,
429 const url::Origin& origin,
430 const std::string& user_agent_override,
431 int render_frame_id) {
432 DVLOG(3) << "WebSocketHost::AddChannel"
433 << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
434 << "\" requested_protocols=\""
435 << base::JoinString(requested_protocols, ", ") << "\" origin=\""
436 << origin << "\" user_agent_override=\""
437 << user_agent_override << "\"";
438
439 DCHECK(!channel_);
440
441 std::unique_ptr<net::WebSocketEventInterface> event_interface(
442 new WebSocketEventHandler(dispatcher_, this, routing_id_,
443 render_frame_id));
444 channel_.reset(new net::WebSocketChannel(std::move(event_interface),
445 url_request_context_));
446
447 if (pending_flow_control_quota_ > 0) {
448 // channel_->SendFlowControl(pending_flow_control_quota_) must be called
449 // after channel_->SendAddChannelRequest() below.
450 // We post OnFlowControl() here using |weak_ptr_factory_| instead of
451 // calling SendFlowControl directly, because |this| may have been deleted
452 // after channel_->SendAddChannelRequest().
453 base::ThreadTaskRunnerHandle::Get()->PostTask(
454 FROM_HERE, base::Bind(&WebSocketHost::OnFlowControl,
455 weak_ptr_factory_.GetWeakPtr(),
456 pending_flow_control_quota_));
457 pending_flow_control_quota_ = 0;
458 }
459
460 std::string additional_headers;
461 if (user_agent_override != "") {
462 if (!net::HttpUtil::IsValidHeaderValue(user_agent_override)) {
463 bad_message::ReceivedBadMessage(
464 dispatcher_, bad_message::WSH_INVALID_HEADER_VALUE);
465 return;
466 }
467 additional_headers = base::StringPrintf("%s:%s",
468 net::HttpRequestHeaders::kUserAgent,
469 user_agent_override.c_str());
470 }
471 channel_->SendAddChannelRequest(
472 socket_url, requested_protocols, origin,
473 additional_headers);
474 // |this| may have been deleted here.
475 }
476
477 void WebSocketHost::OnSendBlob(const std::string& uuid,
478 uint64_t expected_size) {
479 DVLOG(3) << "WebSocketHost::OnSendBlob"
480 << " routing_id=" << routing_id_ << " uuid=" << uuid
481 << " expected_size=" << expected_size;
482
483 DCHECK(channel_);
484 if (blob_sender_) {
485 bad_message::ReceivedBadMessage(
486 dispatcher_, bad_message::WSH_SEND_BLOB_DURING_BLOB_SEND);
487 return;
488 }
489 blob_sender_.reset(new WebSocketBlobSender(
490 base::WrapUnique(new SendChannelImpl(channel_.get()))));
491 StoragePartition* partition = dispatcher_->storage_partition();
492 storage::FileSystemContext* file_system_context =
493 partition->GetFileSystemContext();
494
495 net::WebSocketEventInterface::ChannelState channel_state =
496 net::WebSocketEventInterface::CHANNEL_ALIVE;
497
498 // This use of base::Unretained is safe because the WebSocketBlobSender object
499 // is owned by this object and will not call it back after destruction.
500 int rv = blob_sender_->Start(
501 uuid, expected_size, dispatcher_->blob_storage_context(),
502 file_system_context,
503 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get(),
504 &channel_state,
505 base::Bind(&WebSocketHost::BlobSendComplete, base::Unretained(this)));
506 if (channel_state == net::WebSocketEventInterface::CHANNEL_ALIVE &&
507 rv != net::ERR_IO_PENDING)
508 BlobSendComplete(rv);
509 // |this| may be destroyed here.
510 }
511
512 void WebSocketHost::OnSendFrame(bool fin,
513 WebSocketMessageType type,
514 const std::vector<char>& data) {
515 DVLOG(3) << "WebSocketHost::OnSendFrame"
516 << " routing_id=" << routing_id_ << " fin=" << fin
517 << " type=" << type << " data is " << data.size() << " bytes";
518
519 DCHECK(channel_);
520 if (blob_sender_) {
521 bad_message::ReceivedBadMessage(
522 dispatcher_, bad_message::WSH_SEND_FRAME_DURING_BLOB_SEND);
523 return;
524 }
525 channel_->SendFrame(fin, MessageTypeToOpCode(type), data);
526 }
527
528 void WebSocketHost::OnFlowControl(int64_t quota) {
529 DVLOG(3) << "WebSocketHost::OnFlowControl"
530 << " routing_id=" << routing_id_ << " quota=" << quota;
531
532 if (!channel_) {
533 // WebSocketChannel is not yet created due to the delay introduced by
534 // per-renderer WebSocket throttling.
535 // SendFlowControl() is called after WebSocketChannel is created.
536 pending_flow_control_quota_ += quota;
537 return;
538 }
539
540 ignore_result(channel_->SendFlowControl(quota));
541 }
542
543 void WebSocketHost::OnDropChannel(bool was_clean,
544 uint16_t code,
545 const std::string& reason) {
546 DVLOG(3) << "WebSocketHost::OnDropChannel"
547 << " routing_id=" << routing_id_ << " was_clean=" << was_clean
548 << " code=" << code << " reason=\"" << reason << "\"";
549
550 if (!channel_) {
551 // WebSocketChannel is not yet created due to the delay introduced by
552 // per-renderer WebSocket throttling.
553 WebSocketDispatcherHost::WebSocketHostState result =
554 dispatcher_->DoDropChannel(routing_id_, false,
555 net::kWebSocketErrorAbnormalClosure, "");
556 DCHECK_EQ(WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED, result);
557 return;
558 }
559
560 blob_sender_.reset();
561 // TODO(yhirano): Handle |was_clean| appropriately.
562 ignore_result(channel_->StartClosingHandshake(code, reason));
563 }
564
565 void WebSocketHost::BlobSendComplete(int result) {
566 DVLOG(3) << "WebSocketHost::BlobSendComplete"
567 << " routing_id=" << routing_id_
568 << " result=" << net::ErrorToString(result);
569
570 // All paths through this method must reset blob_sender_, so take ownership
571 // at the beginning.
572 std::unique_ptr<WebSocketBlobSender> blob_sender(std::move(blob_sender_));
573 switch (result) {
574 case net::OK:
575 ignore_result(dispatcher_->BlobSendComplete(routing_id_));
576 // |this| may be destroyed here.
577 return;
578
579 case net::ERR_UPLOAD_FILE_CHANGED: {
580 uint64_t expected_size = blob_sender->expected_size();
581 uint64_t actual_size = blob_sender->ActualSize();
582 if (expected_size != actual_size) {
583 ignore_result(dispatcher_->NotifyFailure(
584 routing_id_,
585 base::StringPrintf("Blob size mismatch; renderer size = %" PRIu64
586 ", browser size = %" PRIu64,
587 expected_size, actual_size)));
588 // |this| is destroyed here.
589 return;
590 } // else fallthrough
591 }
592
593 default:
594 ignore_result(dispatcher_->NotifyFailure(
595 routing_id_,
596 "Failed to load Blob: error code = " + net::ErrorToString(result)));
597 // |this| is destroyed here.
598 return;
599 }
600 }
601
602 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698