OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "net/websockets/websocket_job.h" | 5 #include "net/websockets/websocket_job.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 case INITIALIZED: | 103 case INITIALIZED: |
104 return false; | 104 return false; |
105 | 105 |
106 case CONNECTING: | 106 case CONNECTING: |
107 return SendHandshakeRequest(data, len); | 107 return SendHandshakeRequest(data, len); |
108 | 108 |
109 case OPEN: | 109 case OPEN: |
110 { | 110 { |
111 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(len); | 111 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(len); |
112 memcpy(buffer->data(), data, len); | 112 memcpy(buffer->data(), data, len); |
113 if (current_send_buffer_ || !send_buffer_queue_.empty()) { | 113 if (current_send_buffer_.get() || !send_buffer_queue_.empty()) { |
114 send_buffer_queue_.push_back(buffer); | 114 send_buffer_queue_.push_back(buffer); |
115 return true; | 115 return true; |
116 } | 116 } |
117 current_send_buffer_ = new DrainableIOBuffer(buffer.get(), len); | 117 current_send_buffer_ = new DrainableIOBuffer(buffer.get(), len); |
118 return SendDataInternal(current_send_buffer_->data(), | 118 return SendDataInternal(current_send_buffer_->data(), |
119 current_send_buffer_->BytesRemaining()); | 119 current_send_buffer_->BytesRemaining()); |
120 } | 120 } |
121 | 121 |
122 case CLOSING: | 122 case CLOSING: |
123 case CLOSED: | 123 case CLOSED: |
124 return false; | 124 return false; |
125 } | 125 } |
126 return false; | 126 return false; |
127 } | 127 } |
128 | 128 |
129 void WebSocketJob::Close() { | 129 void WebSocketJob::Close() { |
130 if (state_ == CLOSED) | 130 if (state_ == CLOSED) |
131 return; | 131 return; |
132 | 132 |
133 state_ = CLOSING; | 133 state_ = CLOSING; |
134 if (current_send_buffer_) { | 134 if (current_send_buffer_.get()) { |
135 // Will close in SendPending. | 135 // Will close in SendPending. |
136 return; | 136 return; |
137 } | 137 } |
138 state_ = CLOSED; | 138 state_ = CLOSED; |
139 CloseInternal(); | 139 CloseInternal(); |
140 } | 140 } |
141 | 141 |
142 void WebSocketJob::RestartWithAuth(const AuthCredentials& credentials) { | 142 void WebSocketJob::RestartWithAuth(const AuthCredentials& credentials) { |
143 state_ = CONNECTING; | 143 state_ = CONNECTING; |
144 socket_->RestartWithAuth(credentials); | 144 socket_->RestartWithAuth(credentials); |
145 } | 145 } |
146 | 146 |
147 void WebSocketJob::DetachDelegate() { | 147 void WebSocketJob::DetachDelegate() { |
148 state_ = CLOSED; | 148 state_ = CLOSED; |
149 WebSocketThrottle::GetInstance()->RemoveFromQueue(this); | 149 WebSocketThrottle::GetInstance()->RemoveFromQueue(this); |
150 WebSocketThrottle::GetInstance()->WakeupSocketIfNecessary(); | 150 WebSocketThrottle::GetInstance()->WakeupSocketIfNecessary(); |
151 | 151 |
152 scoped_refptr<WebSocketJob> protect(this); | 152 scoped_refptr<WebSocketJob> protect(this); |
153 weak_ptr_factory_.InvalidateWeakPtrs(); | 153 weak_ptr_factory_.InvalidateWeakPtrs(); |
154 weak_ptr_factory_for_send_pending_.InvalidateWeakPtrs(); | 154 weak_ptr_factory_for_send_pending_.InvalidateWeakPtrs(); |
155 | 155 |
156 delegate_ = NULL; | 156 delegate_ = NULL; |
157 if (socket_) | 157 if (socket_.get()) |
158 socket_->DetachDelegate(); | 158 socket_->DetachDelegate(); |
159 socket_ = NULL; | 159 socket_ = NULL; |
160 if (!callback_.is_null()) { | 160 if (!callback_.is_null()) { |
161 waiting_ = false; | 161 waiting_ = false; |
162 callback_.Reset(); | 162 callback_.Reset(); |
163 Release(); // Balanced with OnStartOpenConnection(). | 163 Release(); // Balanced with OnStartOpenConnection(). |
164 } | 164 } |
165 } | 165 } |
166 | 166 |
167 int WebSocketJob::OnStartOpenConnection( | 167 int WebSocketJob::OnStartOpenConnection( |
(...skipping 29 matching lines...) Expand all Loading... |
197 DCHECK_NE(INITIALIZED, state_); | 197 DCHECK_NE(INITIALIZED, state_); |
198 DCHECK_GT(amount_sent, 0); | 198 DCHECK_GT(amount_sent, 0); |
199 if (state_ == CLOSED) | 199 if (state_ == CLOSED) |
200 return; | 200 return; |
201 if (state_ == CONNECTING) { | 201 if (state_ == CONNECTING) { |
202 OnSentHandshakeRequest(socket, amount_sent); | 202 OnSentHandshakeRequest(socket, amount_sent); |
203 return; | 203 return; |
204 } | 204 } |
205 if (delegate_) { | 205 if (delegate_) { |
206 DCHECK(state_ == OPEN || state_ == CLOSING); | 206 DCHECK(state_ == OPEN || state_ == CLOSING); |
207 if (!current_send_buffer_) { | 207 if (!current_send_buffer_.get()) { |
208 VLOG(1) << "OnSentData current_send_buffer=NULL amount_sent=" | 208 VLOG(1) << "OnSentData current_send_buffer=NULL amount_sent=" |
209 << amount_sent; | 209 << amount_sent; |
210 return; | 210 return; |
211 } | 211 } |
212 current_send_buffer_->DidConsume(amount_sent); | 212 current_send_buffer_->DidConsume(amount_sent); |
213 if (current_send_buffer_->BytesRemaining() > 0) | 213 if (current_send_buffer_->BytesRemaining() > 0) |
214 return; | 214 return; |
215 | 215 |
216 // We need to report amount_sent of original buffer size, instead of | 216 // We need to report amount_sent of original buffer size, instead of |
217 // amount sent to |socket|. | 217 // amount sent to |socket|. |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 } | 294 } |
295 | 295 |
296 CompleteIO(result); | 296 CompleteIO(result); |
297 } | 297 } |
298 | 298 |
299 void WebSocketJob::OnSentSpdyHeaders(int result) { | 299 void WebSocketJob::OnSentSpdyHeaders(int result) { |
300 DCHECK_NE(INITIALIZED, state_); | 300 DCHECK_NE(INITIALIZED, state_); |
301 if (state_ != CONNECTING) | 301 if (state_ != CONNECTING) |
302 return; | 302 return; |
303 if (delegate_) | 303 if (delegate_) |
304 delegate_->OnSentData(socket_, handshake_request_->original_length()); | 304 delegate_->OnSentData(socket_.get(), handshake_request_->original_length()); |
305 handshake_request_.reset(); | 305 handshake_request_.reset(); |
306 } | 306 } |
307 | 307 |
308 int WebSocketJob::OnReceivedSpdyResponseHeader( | 308 int WebSocketJob::OnReceivedSpdyResponseHeader( |
309 const SpdyHeaderBlock& headers, int status) { | 309 const SpdyHeaderBlock& headers, int status) { |
310 DCHECK_NE(INITIALIZED, state_); | 310 DCHECK_NE(INITIALIZED, state_); |
311 if (state_ != CONNECTING) | 311 if (state_ != CONNECTING) |
312 return status; | 312 return status; |
313 if (status != OK) | 313 if (status != OK) |
314 return status; | 314 return status; |
315 // TODO(toyoshim): Fallback to non-spdy connection? | 315 // TODO(toyoshim): Fallback to non-spdy connection? |
316 handshake_response_->ParseResponseHeaderBlock(headers, | 316 handshake_response_->ParseResponseHeaderBlock(headers, |
317 challenge_, | 317 challenge_, |
318 spdy_protocol_version_); | 318 spdy_protocol_version_); |
319 | 319 |
320 SaveCookiesAndNotifyHeaderComplete(); | 320 SaveCookiesAndNotifyHeaderComplete(); |
321 return OK; | 321 return OK; |
322 } | 322 } |
323 | 323 |
324 void WebSocketJob::OnSentSpdyData(int amount_sent) { | 324 void WebSocketJob::OnSentSpdyData(int amount_sent) { |
325 DCHECK_NE(INITIALIZED, state_); | 325 DCHECK_NE(INITIALIZED, state_); |
326 DCHECK_NE(CONNECTING, state_); | 326 DCHECK_NE(CONNECTING, state_); |
327 if (state_ == CLOSED) | 327 if (state_ == CLOSED) |
328 return; | 328 return; |
329 if (!spdy_websocket_stream_.get()) | 329 if (!spdy_websocket_stream_.get()) |
330 return; | 330 return; |
331 OnSentData(socket_, amount_sent); | 331 OnSentData(socket_.get(), amount_sent); |
332 } | 332 } |
333 | 333 |
334 void WebSocketJob::OnReceivedSpdyData(const char* data, int length) { | 334 void WebSocketJob::OnReceivedSpdyData(const char* data, int length) { |
335 DCHECK_NE(INITIALIZED, state_); | 335 DCHECK_NE(INITIALIZED, state_); |
336 DCHECK_NE(CONNECTING, state_); | 336 DCHECK_NE(CONNECTING, state_); |
337 if (state_ == CLOSED) | 337 if (state_ == CLOSED) |
338 return; | 338 return; |
339 if (!spdy_websocket_stream_.get()) | 339 if (!spdy_websocket_stream_.get()) |
340 return; | 340 return; |
341 OnReceivedData(socket_, data, length); | 341 OnReceivedData(socket_.get(), data, length); |
342 } | 342 } |
343 | 343 |
344 void WebSocketJob::OnCloseSpdyStream() { | 344 void WebSocketJob::OnCloseSpdyStream() { |
345 spdy_websocket_stream_.reset(); | 345 spdy_websocket_stream_.reset(); |
346 OnClose(socket_); | 346 OnClose(socket_.get()); |
347 } | 347 } |
348 | 348 |
349 bool WebSocketJob::SendHandshakeRequest(const char* data, int len) { | 349 bool WebSocketJob::SendHandshakeRequest(const char* data, int len) { |
350 DCHECK_EQ(state_, CONNECTING); | 350 DCHECK_EQ(state_, CONNECTING); |
351 if (started_to_send_handshake_request_) | 351 if (started_to_send_handshake_request_) |
352 return false; | 352 return false; |
353 if (!handshake_request_->ParseRequest(data, len)) | 353 if (!handshake_request_->ParseRequest(data, len)) |
354 return false; | 354 return false; |
355 | 355 |
356 // handshake message is completed. | 356 // handshake message is completed. |
357 handshake_response_->set_protocol_version( | 357 handshake_response_->set_protocol_version( |
358 handshake_request_->protocol_version()); | 358 handshake_request_->protocol_version()); |
359 AddCookieHeaderAndSend(); | 359 AddCookieHeaderAndSend(); |
360 return true; | 360 return true; |
361 } | 361 } |
362 | 362 |
363 void WebSocketJob::AddCookieHeaderAndSend() { | 363 void WebSocketJob::AddCookieHeaderAndSend() { |
364 bool allow = true; | 364 bool allow = true; |
365 if (delegate_ && !delegate_->CanGetCookies(socket_, GetURLForCookies())) | 365 if (delegate_ && !delegate_->CanGetCookies(socket_.get(), GetURLForCookies())) |
366 allow = false; | 366 allow = false; |
367 | 367 |
368 if (socket_ && delegate_ && state_ == CONNECTING) { | 368 if (socket_.get() && delegate_ && state_ == CONNECTING) { |
369 handshake_request_->RemoveHeaders( | 369 handshake_request_->RemoveHeaders( |
370 kCookieHeaders, arraysize(kCookieHeaders)); | 370 kCookieHeaders, arraysize(kCookieHeaders)); |
371 if (allow && socket_->context()->cookie_store()) { | 371 if (allow && socket_->context()->cookie_store()) { |
372 // Add cookies, including HttpOnly cookies. | 372 // Add cookies, including HttpOnly cookies. |
373 CookieOptions cookie_options; | 373 CookieOptions cookie_options; |
374 cookie_options.set_include_httponly(); | 374 cookie_options.set_include_httponly(); |
375 socket_->context()->cookie_store()->GetCookiesWithOptionsAsync( | 375 socket_->context()->cookie_store()->GetCookiesWithOptionsAsync( |
376 GetURLForCookies(), cookie_options, | 376 GetURLForCookies(), cookie_options, |
377 base::Bind(&WebSocketJob::LoadCookieCallback, | 377 base::Bind(&WebSocketJob::LoadCookieCallback, |
378 weak_ptr_factory_.GetWeakPtr())); | 378 weak_ptr_factory_.GetWeakPtr())); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 received_data.insert(received_data.end(), | 482 received_data.insert(received_data.end(), |
483 received_data_after_handshake_.begin(), | 483 received_data_after_handshake_.begin(), |
484 received_data_after_handshake_.end()); | 484 received_data_after_handshake_.end()); |
485 received_data_after_handshake_.clear(); | 485 received_data_after_handshake_.clear(); |
486 | 486 |
487 state_ = OPEN; | 487 state_ = OPEN; |
488 | 488 |
489 DCHECK(!received_data.empty()); | 489 DCHECK(!received_data.empty()); |
490 if (delegate_) | 490 if (delegate_) |
491 delegate_->OnReceivedData( | 491 delegate_->OnReceivedData( |
492 socket_, &received_data.front(), received_data.size()); | 492 socket_.get(), &received_data.front(), received_data.size()); |
493 | 493 |
494 handshake_response_.reset(); | 494 handshake_response_.reset(); |
495 | 495 |
496 WebSocketThrottle::GetInstance()->RemoveFromQueue(this); | 496 WebSocketThrottle::GetInstance()->RemoveFromQueue(this); |
497 WebSocketThrottle::GetInstance()->WakeupSocketIfNecessary(); | 497 WebSocketThrottle::GetInstance()->WakeupSocketIfNecessary(); |
498 return; | 498 return; |
499 } | 499 } |
500 | 500 |
501 bool allow = true; | 501 bool allow = true; |
502 CookieOptions options; | 502 CookieOptions options; |
503 GURL url = GetURLForCookies(); | 503 GURL url = GetURLForCookies(); |
504 std::string cookie = response_cookies_[response_cookies_save_index_]; | 504 std::string cookie = response_cookies_[response_cookies_save_index_]; |
505 if (delegate_ && !delegate_->CanSetCookie(socket_, url, cookie, &options)) | 505 if ( |
| 506 delegate_ && !delegate_-> |
| 507 CanSetCookie(socket_.get(), url, cookie, &options)) |
506 allow = false; | 508 allow = false; |
507 | 509 |
508 if (socket_ && delegate_ && state_ == CONNECTING) { | 510 if (socket_.get() && delegate_ && state_ == CONNECTING) { |
509 response_cookies_save_index_++; | 511 response_cookies_save_index_++; |
510 if (allow && socket_->context()->cookie_store()) { | 512 if (allow && socket_->context()->cookie_store()) { |
511 options.set_include_httponly(); | 513 options.set_include_httponly(); |
512 socket_->context()->cookie_store()->SetCookieWithOptionsAsync( | 514 socket_->context()->cookie_store()->SetCookieWithOptionsAsync( |
513 url, cookie, options, | 515 url, cookie, options, |
514 base::Bind(&WebSocketJob::SaveCookieCallback, | 516 base::Bind(&WebSocketJob::SaveCookieCallback, |
515 weak_ptr_factory_.GetWeakPtr())); | 517 weak_ptr_factory_.GetWeakPtr())); |
516 } else { | 518 } else { |
517 SaveNextCookie(); | 519 SaveNextCookie(); |
518 } | 520 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 SSLInfo ssl_info; | 566 SSLInfo ssl_info; |
565 bool was_npn_negotiated; | 567 bool was_npn_negotiated; |
566 NextProto protocol_negotiated = kProtoUnknown; | 568 NextProto protocol_negotiated = kProtoUnknown; |
567 bool use_ssl = spdy_session->GetSSLInfo( | 569 bool use_ssl = spdy_session->GetSSLInfo( |
568 &ssl_info, &was_npn_negotiated, &protocol_negotiated); | 570 &ssl_info, &was_npn_negotiated, &protocol_negotiated); |
569 if (socket_->is_secure() && !use_ssl) | 571 if (socket_->is_secure() && !use_ssl) |
570 return OK; | 572 return OK; |
571 | 573 |
572 // Create SpdyWebSocketStream. | 574 // Create SpdyWebSocketStream. |
573 spdy_protocol_version_ = spdy_session->GetProtocolVersion(); | 575 spdy_protocol_version_ = spdy_session->GetProtocolVersion(); |
574 spdy_websocket_stream_.reset(new SpdyWebSocketStream(spdy_session, this)); | 576 spdy_websocket_stream_.reset( |
| 577 new SpdyWebSocketStream(spdy_session.get(), this)); |
575 | 578 |
576 int result = spdy_websocket_stream_->InitializeStream( | 579 int result = spdy_websocket_stream_->InitializeStream( |
577 socket_->url(), MEDIUM, *socket_->net_log()); | 580 socket_->url(), MEDIUM, *socket_->net_log()); |
578 if (result == OK) { | 581 if (result == OK) { |
579 OnConnected(socket_, kMaxPendingSendAllowed); | 582 OnConnected(socket_.get(), kMaxPendingSendAllowed); |
580 return ERR_PROTOCOL_SWITCHED; | 583 return ERR_PROTOCOL_SWITCHED; |
581 } | 584 } |
582 if (result != ERR_IO_PENDING) { | 585 if (result != ERR_IO_PENDING) { |
583 spdy_websocket_stream_.reset(); | 586 spdy_websocket_stream_.reset(); |
584 return OK; | 587 return OK; |
585 } | 588 } |
586 | 589 |
587 return ERR_IO_PENDING; | 590 return ERR_IO_PENDING; |
588 } | 591 } |
589 | 592 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 } | 637 } |
635 | 638 |
636 void WebSocketJob::CloseInternal() { | 639 void WebSocketJob::CloseInternal() { |
637 if (spdy_websocket_stream_.get()) | 640 if (spdy_websocket_stream_.get()) |
638 spdy_websocket_stream_->Close(); | 641 spdy_websocket_stream_->Close(); |
639 if (socket_.get()) | 642 if (socket_.get()) |
640 socket_->Close(); | 643 socket_->Close(); |
641 } | 644 } |
642 | 645 |
643 void WebSocketJob::SendPending() { | 646 void WebSocketJob::SendPending() { |
644 if (current_send_buffer_) | 647 if (current_send_buffer_.get()) |
645 return; | 648 return; |
646 | 649 |
647 // Current buffer has been sent. Try next if any. | 650 // Current buffer has been sent. Try next if any. |
648 if (send_buffer_queue_.empty()) { | 651 if (send_buffer_queue_.empty()) { |
649 // No more data to send. | 652 // No more data to send. |
650 if (state_ == CLOSING) | 653 if (state_ == CLOSING) |
651 CloseInternal(); | 654 CloseInternal(); |
652 return; | 655 return; |
653 } | 656 } |
654 | 657 |
655 scoped_refptr<IOBufferWithSize> next_buffer = send_buffer_queue_.front(); | 658 scoped_refptr<IOBufferWithSize> next_buffer = send_buffer_queue_.front(); |
656 send_buffer_queue_.pop_front(); | 659 send_buffer_queue_.pop_front(); |
657 current_send_buffer_ = new DrainableIOBuffer(next_buffer, | 660 current_send_buffer_ = new DrainableIOBuffer(next_buffer.get(), |
658 next_buffer->size()); | 661 next_buffer->size()); |
659 SendDataInternal(current_send_buffer_->data(), | 662 SendDataInternal(current_send_buffer_->data(), |
660 current_send_buffer_->BytesRemaining()); | 663 current_send_buffer_->BytesRemaining()); |
661 } | 664 } |
662 | 665 |
663 } // namespace net | 666 } // namespace net |
OLD | NEW |