1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/websockets/websocket_job.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/lazy_instance.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_tokenizer.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h" 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/net_log.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/cookie_policy.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/cookie_store.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/io_buffer.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_util.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_context.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/websockets/websocket_frame_handler.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/websockets/websocket_handshake_handler.h" 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/websockets/websocket_net_log_params.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/websockets/websocket_throttle.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// lower-case header names. 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* const kCookieHeaders[] = { 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "cookie", "cookie2" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* const kSetCookieHeaders[] = { 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "set-cookie", "set-cookie2" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnet::SocketStreamJob* WebSocketJobFactory( 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, net::SocketStream::Delegate* delegate) { 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::WebSocketJob* job = new net::WebSocketJob(delegate); 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch job->InitSocketStream(new net::SocketStream(url, job)); 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return job; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebSocketJobInitSingleton { 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen friend struct base::DefaultLazyInstanceTraits<WebSocketJobInitSingleton>; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebSocketJobInitSingleton() { 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::SocketStreamJob::RegisterProtocolFactory("ws", WebSocketJobFactory); 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::SocketStreamJob::RegisterProtocolFactory("wss", WebSocketJobFactory); 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic base::LazyInstance<WebSocketJobInitSingleton> g_websocket_job_init( 5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::LINKER_INITIALIZED); 5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // anonymous namespace 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net { 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::EnsureInit() { 5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen g_websocket_job_init.Get(); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebSocketJob::WebSocketJob(SocketStream::Delegate* delegate) 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : delegate_(delegate), 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_(INITIALIZED), 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_(false), 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch callback_(NULL), 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_request_(new WebSocketHandshakeRequestHandler), 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_response_(new WebSocketHandshakeResponseHandler), 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_request_sent_(0), 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_cookies_save_index_(0), 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_frame_handler_(new WebSocketFrameHandler), 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch receive_frame_handler_(new WebSocketFrameHandler) { 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebSocketJob::~WebSocketJob() { 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(CLOSED, state_); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!delegate_); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!socket_.get()); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::Connect() { 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(socket_.get()); 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(state_, INITIALIZED); 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = CONNECTING; 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_->Connect(); 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WebSocketJob::SendData(const char* data, int len) { 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (state_) { 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case INITIALIZED: 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case CONNECTING: 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return SendHandshakeRequest(data, len); 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case OPEN: 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_frame_handler_->AppendData(data, len); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If current buffer is sending now, this data will be sent in 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SendPending() after current data was sent. 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Do not buffer sending data for now. Since 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WebCore::SocketStreamHandle controls traffic to keep number of 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // pending bytes less than max_pending_send_allowed, so when sending 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // larger message than max_pending_send_allowed should not be buffered. 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we don't call OnSentData, WebCore::SocketStreamHandle would stop 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // sending more data when pending data reaches max_pending_send_allowed. 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(ukai): Fix this to support compression for larger message. 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int err = 0; 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!send_frame_handler_->GetCurrentBuffer() && 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (err = send_frame_handler_->UpdateCurrentBuffer(false)) > 0) { 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!current_buffer_); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_buffer_ = new DrainableIOBuffer( 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_frame_handler_->GetCurrentBuffer(), 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_frame_handler_->GetCurrentBufferSize()); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return socket_->SendData( 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_buffer_->data(), current_buffer_->BytesRemaining()); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return err >= 0; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case CLOSING: 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case CLOSED: 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::Close() { 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = CLOSING; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_buffer_) { 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Will close in SendPending. 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = CLOSED; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_->Close(); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::RestartWithAuth( 1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16& username, 1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16& password) { 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = CONNECTING; 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_->RestartWithAuth(username, password); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::DetachDelegate() { 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = CLOSED; 14721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen WebSocketThrottle::GetInstance()->RemoveFromQueue(this); 14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen WebSocketThrottle::GetInstance()->WakeupSocketIfNecessary(); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<WebSocketJob> protect(this); 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_ = NULL; 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (socket_) 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_->DetachDelegate(); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_ = NULL; 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (callback_) { 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_ = false; 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch callback_ = NULL; 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); // Balanced with OnStartOpenConnection(). 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint WebSocketJob::OnStartOpenConnection( 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SocketStream* socket, CompletionCallback* callback) { 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!callback_); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = CONNECTING; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch addresses_.Copy(socket->address_list().head(), true); 16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen WebSocketThrottle::GetInstance()->PutInQueue(this); 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!waiting_) 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch callback_ = callback; 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddRef(); // Balanced when callback_ becomes NULL. 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_IO_PENDING; 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::OnConnected( 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SocketStream* socket, int max_pending_send_allowed) { 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ == CLOSED) 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(CONNECTING, state_); 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (delegate_) 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->OnConnected(socket, max_pending_send_allowed); 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::OnSentData(SocketStream* socket, int amount_sent) { 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(INITIALIZED, state_); 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ == CLOSED) 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ == CONNECTING) { 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnSentHandshakeRequest(socket, amount_sent); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (delegate_) { 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(state_ == OPEN || state_ == CLOSING); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_GT(amount_sent, 0); 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(current_buffer_); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_buffer_->DidConsume(amount_sent); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_buffer_->BytesRemaining() > 0) 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We need to report amount_sent of original buffer size, instead of 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // amount sent to |socket|. 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch amount_sent = send_frame_handler_->GetOriginalBufferSize(); 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_GT(amount_sent, 0); 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_buffer_ = NULL; 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_frame_handler_->ReleaseCurrentBuffer(); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->OnSentData(socket, amount_sent); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoopForIO::current()->PostTask( 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FROM_HERE, NewRunnableMethod(this, &WebSocketJob::SendPending)); 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::OnReceivedData( 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SocketStream* socket, const char* data, int len) { 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(INITIALIZED, state_); 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ == CLOSED) 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ == CONNECTING) { 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnReceivedHandshakeResponse(socket, data, len); 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(state_ == OPEN || state_ == CLOSING); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string received_data; 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch receive_frame_handler_->AppendData(data, len); 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't buffer receiving data for now. 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(ukai): fix performance of WebSocketFrameHandler. 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (receive_frame_handler_->UpdateCurrentBuffer(false) > 0) { 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch received_data += 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string(receive_frame_handler_->GetCurrentBuffer()->data(), 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch receive_frame_handler_->GetCurrentBufferSize()); 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch receive_frame_handler_->ReleaseCurrentBuffer(); 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (delegate_ && !received_data.empty()) 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->OnReceivedData( 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket, received_data.data(), received_data.size()); 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::OnClose(SocketStream* socket) { 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = CLOSED; 24021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen WebSocketThrottle::GetInstance()->RemoveFromQueue(this); 24121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen WebSocketThrottle::GetInstance()->WakeupSocketIfNecessary(); 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<WebSocketJob> protect(this); 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SocketStream::Delegate* delegate = delegate_; 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_ = NULL; 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_ = NULL; 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (callback_) { 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_ = false; 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch callback_ = NULL; 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); // Balanced with OnStartOpenConnection(). 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (delegate) 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate->OnClose(socket); 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::OnAuthRequired( 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SocketStream* socket, AuthChallengeInfo* auth_info) { 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (delegate_) 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->OnAuthRequired(socket, auth_info); 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::OnError(const SocketStream* socket, int error) { 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (delegate_) 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->OnError(socket, error); 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WebSocketJob::SendHandshakeRequest(const char* data, int len) { 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(state_, CONNECTING); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!handshake_request_->ParseRequest(data, len)) 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // handshake message is completed. 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddCookieHeaderAndSend(); 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Just buffered in |handshake_request_|. 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::AddCookieHeaderAndSend() { 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int policy = OK; 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (socket_->context()->cookie_policy()) { 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url_for_cookies = GetURLForCookies(); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch policy = socket_->context()->cookie_policy()->CanGetCookies( 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_for_cookies, 285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url_for_cookies); 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_NE(ERR_IO_PENDING, policy); 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnCanGetCookiesCompleted(policy); 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::OnCanGetCookiesCompleted(int policy) { 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (socket_ && delegate_ && state_ == CONNECTING) { 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_request_->RemoveHeaders( 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCookieHeaders, arraysize(kCookieHeaders)); 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (policy == OK) { 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add cookies, including HttpOnly cookies. 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (socket_->context()->cookie_store()) { 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CookieOptions cookie_options; 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cookie_options.set_include_httponly(); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string cookie = 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_->context()->cookie_store()->GetCookiesWithOptions( 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetURLForCookies(), cookie_options); 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!cookie.empty()) 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_request_->AppendHeaderIfMissing("Cookie", cookie); 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& handshake_request = handshake_request_->GetRawRequest(); 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_request_sent_ = 0; 3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick socket_->net_log()->AddEvent( 3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NetLog::TYPE_WEB_SOCKET_SEND_REQUEST_HEADERS, 312513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch make_scoped_refptr( 313513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new NetLogWebSocketHandshakeParameter(handshake_request))); 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_->SendData(handshake_request.data(), 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_request.size()); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::OnSentHandshakeRequest( 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SocketStream* socket, int amount_sent) { 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(state_, CONNECTING); 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_request_sent_ += amount_sent; 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_LE(handshake_request_sent_, handshake_request_->raw_length()); 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (handshake_request_sent_ >= handshake_request_->raw_length()) { 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // handshake request has been sent. 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // notify original size of handshake request to delegate. 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (delegate_) 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->OnSentData( 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket, 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_request_->original_length()); 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_request_.reset(); 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::OnReceivedHandshakeResponse( 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SocketStream* socket, const char* data, int len) { 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(state_, CONNECTING); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (handshake_response_->HasResponse()) { 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we already has handshake response, received data should be frame 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // data, not handshake message. 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch receive_frame_handler_->AppendData(data, len); 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t response_length = handshake_response_->ParseRawResponse(data, len); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!handshake_response_->HasResponse()) { 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // not yet. we need more data. 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // handshake message is completed. 3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick socket_->net_log()->AddEvent( 3523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NetLog::TYPE_WEB_SOCKET_READ_RESPONSE_HEADERS, 353513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch make_scoped_refptr(new NetLogWebSocketHandshakeParameter( 354513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch handshake_response_->GetRawResponse()))); 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (len - response_length > 0) { 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we received extra data, it should be frame data. 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch receive_frame_handler_->AppendData(data + response_length, 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch len - response_length); 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SaveCookiesAndNotifyHeaderComplete(); 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::SaveCookiesAndNotifyHeaderComplete() { 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // handshake message is completed. 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(handshake_response_->HasResponse()); 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_cookies_.clear(); 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_cookies_save_index_ = 0; 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_response_->GetHeaders( 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kSetCookieHeaders, arraysize(kSetCookieHeaders), &response_cookies_); 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now, loop over the response cookies, and attempt to persist each. 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SaveNextCookie(); 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::SaveNextCookie() { 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (response_cookies_save_index_ == response_cookies_.size()) { 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_cookies_.clear(); 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_cookies_save_index_ = 0; 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove cookie headers, with malformed headers preserved. 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Actual handshake should be done in WebKit. 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_response_->RemoveHeaders( 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kSetCookieHeaders, arraysize(kSetCookieHeaders)); 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string received_data = handshake_response_->GetResponse(); 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't buffer receiving data for now. 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(ukai): fix performance of WebSocketFrameHandler. 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (receive_frame_handler_->UpdateCurrentBuffer(false) > 0) { 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch received_data += 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string(receive_frame_handler_->GetCurrentBuffer()->data(), 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch receive_frame_handler_->GetCurrentBufferSize()); 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch receive_frame_handler_->ReleaseCurrentBuffer(); 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = OPEN; 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (delegate_) 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->OnReceivedData( 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_, received_data.data(), received_data.size()); 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_response_.reset(); 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen WebSocketThrottle::GetInstance()->RemoveFromQueue(this); 40421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen WebSocketThrottle::GetInstance()->WakeupSocketIfNecessary(); 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int policy = OK; 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (socket_->context()->cookie_policy()) { 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url_for_cookies = GetURLForCookies(); 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch policy = socket_->context()->cookie_policy()->CanSetCookie( 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_for_cookies, 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_for_cookies, 414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen response_cookies_[response_cookies_save_index_]); 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_NE(ERR_IO_PENDING, policy); 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnCanSetCookieCompleted(policy); 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::OnCanSetCookieCompleted(int policy) { 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (socket_ && delegate_ && state_ == CONNECTING) { 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((policy == OK || policy == OK_FOR_SESSION_ONLY) && 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_->context()->cookie_store()) { 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CookieOptions options; 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options.set_include_httponly(); 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (policy == OK_FOR_SESSION_ONLY) 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options.set_force_session(); 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url_for_cookies = GetURLForCookies(); 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_->context()->cookie_store()->SetCookieWithOptions( 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_for_cookies, response_cookies_[response_cookies_save_index_], 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options); 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_cookies_save_index_++; 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SaveNextCookie(); 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGURL WebSocketJob::GetURLForCookies() const { 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url = socket_->url(); 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string scheme = socket_->is_secure() ? "https" : "http"; 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_canon::Replacements<char> replacements; 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch replacements.SetScheme(scheme.c_str(), 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_parse::Component(0, scheme.length())); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return url.ReplaceComponents(replacements); 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst AddressList& WebSocketJob::address_list() const { 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return addresses_; 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::SetWaiting() { 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_ = true; 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WebSocketJob::IsWaiting() const { 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return waiting_; 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::Wakeup() { 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!waiting_) 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_ = false; 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(callback_); 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoopForIO::current()->PostTask( 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FROM_HERE, 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &WebSocketJob::DoCallback)); 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::DoCallback() { 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |callback_| may be NULL if OnClose() or DetachDelegate() was called. 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (callback_) { 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback = callback_; 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch callback_ = NULL; 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch callback->Run(net::OK); 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); // Balanced with OnStartOpenConnection(). 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocketJob::SendPending() { 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_buffer_) 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Current buffer is done. Try next buffer if any. 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't buffer sending data. See comment on case OPEN in SendData(). 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (send_frame_handler_->UpdateCurrentBuffer(false) <= 0) { 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No more data to send. 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ == CLOSING) 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_->Close(); 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_buffer_ = new DrainableIOBuffer( 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_frame_handler_->GetCurrentBuffer(), 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_frame_handler_->GetCurrentBufferSize()); 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_->SendData(current_buffer_->data(), current_buffer_->BytesRemaining()); 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace net 499