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

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: Fix compile error Created 4 years, 4 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 WebSocketHostMsg_AddChannelRequest_Params& params) {
400 DVLOG(3) << "WebSocketHost::OnAddChannelRequest"
401 << " routing_id=" << routing_id_ << " socket_url=\""
402 << params.socket_url << "\" requested_protocols=\""
403 << base::JoinString(params.requested_protocols, ", ")
404 << "\" origin=\"" << params.origin
405 << "\" first_party_for_cookies=\""
406 << params.first_party_for_cookies << "\" user_agent_override=\""
407 << params.user_agent_override
408 << "\"";
409
410 DCHECK(!channel_);
411 if (delay_ > base::TimeDelta()) {
412 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
413 FROM_HERE,
414 base::Bind(&WebSocketHost::AddChannel, weak_ptr_factory_.GetWeakPtr(),
415 params.socket_url, params.requested_protocols,
416 params.origin, params.first_party_for_cookies,
417 params.user_agent_override, params.render_frame_id),
418 delay_);
419 } else {
420 AddChannel(
421 params.socket_url, params.requested_protocols, params.origin,
422 params.first_party_for_cookies, params.user_agent_override,
423 params.render_frame_id);
424 }
425 // |this| may have been deleted here.
426 }
427
428 void WebSocketHost::AddChannel(
429 const GURL& socket_url,
430 const std::vector<std::string>& requested_protocols,
431 const url::Origin& origin,
432 const GURL& first_party_for_cookies,
433 const std::string& user_agent_override,
434 int render_frame_id) {
435 DVLOG(3) << "WebSocketHost::AddChannel"
436 << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
437 << "\" requested_protocols=\""
438 << base::JoinString(requested_protocols, ", ") << "\" origin=\""
439 << origin << "\" first_party_for_cookies=\""
440 << first_party_for_cookies << "\" user_agent_override=\""
441 << user_agent_override << "\"";
442
443 DCHECK(!channel_);
444
445 std::unique_ptr<net::WebSocketEventInterface> event_interface(
446 new WebSocketEventHandler(dispatcher_, this, routing_id_,
447 render_frame_id));
448 channel_.reset(new net::WebSocketChannel(std::move(event_interface),
449 url_request_context_));
450
451 if (pending_flow_control_quota_ > 0) {
452 // channel_->SendFlowControl(pending_flow_control_quota_) must be called
453 // after channel_->SendAddChannelRequest() below.
454 // We post OnFlowControl() here using |weak_ptr_factory_| instead of
455 // calling SendFlowControl directly, because |this| may have been deleted
456 // after channel_->SendAddChannelRequest().
457 base::ThreadTaskRunnerHandle::Get()->PostTask(
458 FROM_HERE, base::Bind(&WebSocketHost::OnFlowControl,
459 weak_ptr_factory_.GetWeakPtr(),
460 pending_flow_control_quota_));
461 pending_flow_control_quota_ = 0;
462 }
463
464 std::string additional_headers;
465 if (user_agent_override != "") {
466 if (!net::HttpUtil::IsValidHeaderValue(user_agent_override)) {
467 bad_message::ReceivedBadMessage(
468 dispatcher_, bad_message::WSH_INVALID_HEADER_VALUE);
469 return;
470 }
471 additional_headers = base::StringPrintf("%s:%s",
472 net::HttpRequestHeaders::kUserAgent,
473 user_agent_override.c_str());
474 }
475 channel_->SendAddChannelRequest(
476 socket_url, requested_protocols, origin, first_party_for_cookies,
477 additional_headers);
478 // |this| may have been deleted here.
479 }
480
481 void WebSocketHost::OnSendBlob(const std::string& uuid,
482 uint64_t expected_size) {
483 DVLOG(3) << "WebSocketHost::OnSendBlob"
484 << " routing_id=" << routing_id_ << " uuid=" << uuid
485 << " expected_size=" << expected_size;
486
487 DCHECK(channel_);
488 if (blob_sender_) {
489 bad_message::ReceivedBadMessage(
490 dispatcher_, bad_message::WSH_SEND_BLOB_DURING_BLOB_SEND);
491 return;
492 }
493 blob_sender_.reset(new WebSocketBlobSender(
494 base::WrapUnique(new SendChannelImpl(channel_.get()))));
495 StoragePartition* partition = dispatcher_->storage_partition();
496 storage::FileSystemContext* file_system_context =
497 partition->GetFileSystemContext();
498
499 net::WebSocketEventInterface::ChannelState channel_state =
500 net::WebSocketEventInterface::CHANNEL_ALIVE;
501
502 // This use of base::Unretained is safe because the WebSocketBlobSender object
503 // is owned by this object and will not call it back after destruction.
504 int rv = blob_sender_->Start(
505 uuid, expected_size, dispatcher_->blob_storage_context(),
506 file_system_context,
507 BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE).get(),
508 &channel_state,
509 base::Bind(&WebSocketHost::BlobSendComplete, base::Unretained(this)));
510 if (channel_state == net::WebSocketEventInterface::CHANNEL_ALIVE &&
511 rv != net::ERR_IO_PENDING)
512 BlobSendComplete(rv);
513 // |this| may be destroyed here.
514 }
515
516 void WebSocketHost::OnSendFrame(bool fin,
517 WebSocketMessageType type,
518 const std::vector<char>& data) {
519 DVLOG(3) << "WebSocketHost::OnSendFrame"
520 << " routing_id=" << routing_id_ << " fin=" << fin
521 << " type=" << type << " data is " << data.size() << " bytes";
522
523 DCHECK(channel_);
524 if (blob_sender_) {
525 bad_message::ReceivedBadMessage(
526 dispatcher_, bad_message::WSH_SEND_FRAME_DURING_BLOB_SEND);
527 return;
528 }
529 channel_->SendFrame(fin, MessageTypeToOpCode(type), data);
530 }
531
532 void WebSocketHost::OnFlowControl(int64_t quota) {
533 DVLOG(3) << "WebSocketHost::OnFlowControl"
534 << " routing_id=" << routing_id_ << " quota=" << quota;
535
536 if (!channel_) {
537 // WebSocketChannel is not yet created due to the delay introduced by
538 // per-renderer WebSocket throttling.
539 // SendFlowControl() is called after WebSocketChannel is created.
540 pending_flow_control_quota_ += quota;
541 return;
542 }
543
544 ignore_result(channel_->SendFlowControl(quota));
545 }
546
547 void WebSocketHost::OnDropChannel(bool was_clean,
548 uint16_t code,
549 const std::string& reason) {
550 DVLOG(3) << "WebSocketHost::OnDropChannel"
551 << " routing_id=" << routing_id_ << " was_clean=" << was_clean
552 << " code=" << code << " reason=\"" << reason << "\"";
553
554 if (!channel_) {
555 // WebSocketChannel is not yet created due to the delay introduced by
556 // per-renderer WebSocket throttling.
557 WebSocketDispatcherHost::WebSocketHostState result =
558 dispatcher_->DoDropChannel(routing_id_, false,
559 net::kWebSocketErrorAbnormalClosure, "");
560 DCHECK_EQ(WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED, result);
561 return;
562 }
563
564 blob_sender_.reset();
565 // TODO(yhirano): Handle |was_clean| appropriately.
566 ignore_result(channel_->StartClosingHandshake(code, reason));
567 }
568
569 void WebSocketHost::BlobSendComplete(int result) {
570 DVLOG(3) << "WebSocketHost::BlobSendComplete"
571 << " routing_id=" << routing_id_
572 << " result=" << net::ErrorToString(result);
573
574 // All paths through this method must reset blob_sender_, so take ownership
575 // at the beginning.
576 std::unique_ptr<WebSocketBlobSender> blob_sender(std::move(blob_sender_));
577 switch (result) {
578 case net::OK:
579 ignore_result(dispatcher_->BlobSendComplete(routing_id_));
580 // |this| may be destroyed here.
581 return;
582
583 case net::ERR_UPLOAD_FILE_CHANGED: {
584 uint64_t expected_size = blob_sender->expected_size();
585 uint64_t actual_size = blob_sender->ActualSize();
586 if (expected_size != actual_size) {
587 ignore_result(dispatcher_->NotifyFailure(
588 routing_id_,
589 base::StringPrintf("Blob size mismatch; renderer size = %" PRIu64
590 ", browser size = %" PRIu64,
591 expected_size, actual_size)));
592 // |this| is destroyed here.
593 return;
594 } // else fallthrough
595 }
596
597 default:
598 ignore_result(dispatcher_->NotifyFailure(
599 routing_id_,
600 "Failed to load Blob: error code = " + net::ErrorToString(result)));
601 // |this| is destroyed here.
602 return;
603 }
604 }
605
606 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698