blob: 369ef56d1c837bf2a9eaccc42f0a0a11d7b2e302 [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_WEBSOCKETS_WEBSOCKET_JOB_H_
#define NET_WEBSOCKETS_WEBSOCKET_JOB_H_
#pragma once
#include <string>
#include <vector>
#include "base/string16.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
#include "net/socket_stream/socket_stream_job.h"
class GURL;
namespace net {
class DrainableIOBuffer;
class WebSocketFrameHandler;
class WebSocketHandshakeRequestHandler;
class WebSocketHandshakeResponseHandler;
// WebSocket protocol specific job on SocketStream.
// It captures WebSocket handshake message and handles cookie operations.
// Chrome security policy doesn't allow renderer process (except dev tools)
// see HttpOnly cookies, so it injects cookie header in handshake request and
// strips set-cookie headers in handshake response.
// TODO(ukai): refactor websocket.cc to use this.
class NET_API WebSocketJob
: public SocketStreamJob,
public SocketStream::Delegate {
public:
// This is state of WebSocket, not SocketStream.
enum State {
INITIALIZED = -1,
CONNECTING = 0,
OPEN = 1,
CLOSING = 2,
CLOSED = 3,
};
explicit WebSocketJob(SocketStream::Delegate* delegate);
static void EnsureInit();
// Enable or Disable WebSocket over SPDY feature.
// This function is intended to be called before I/O thread starts.
static void set_websocket_over_spdy_enabled(bool enabled);
State state() const { return state_; }
virtual void Connect();
virtual bool SendData(const char* data, int len);
virtual void Close();
virtual void RestartWithAuth(
const string16& username,
const string16& password);
virtual void DetachDelegate();
// SocketStream::Delegate methods.
virtual int OnStartOpenConnection(
SocketStream* socket, CompletionCallback* callback);
virtual void OnConnected(SocketStream* socket, int max_pending_send_allowed);
virtual void OnSentData(SocketStream* socket, int amount_sent);
virtual void OnReceivedData(SocketStream* socket, const char* data, int len);
virtual void OnClose(SocketStream* socket);
virtual void OnAuthRequired(
SocketStream* socket, AuthChallengeInfo* auth_info);
virtual void OnError(const SocketStream* socket, int error);
private:
friend class WebSocketThrottle;
friend class WebSocketJobTest;
virtual ~WebSocketJob();
bool SendHandshakeRequest(const char* data, int len);
void AddCookieHeaderAndSend();
void OnSentHandshakeRequest(SocketStream* socket, int amount_sent);
void OnReceivedHandshakeResponse(
SocketStream* socket, const char* data, int len);
void SaveCookiesAndNotifyHeaderComplete();
void SaveNextCookie();
GURL GetURLForCookies() const;
const AddressList& address_list() const;
int TrySpdyStream();
void SetWaiting();
bool IsWaiting() const;
void Wakeup();
void RetryPendingIO();
bool SendDataInternal(const char* data, int length);
void CloseInternal();
void SendPending();
static bool websocket_over_spdy_enabled_;
SocketStream::Delegate* delegate_;
State state_;
bool waiting_;
AddressList addresses_;
CompletionCallback* callback_; // for throttling.
scoped_ptr<WebSocketHandshakeRequestHandler> handshake_request_;
scoped_ptr<WebSocketHandshakeResponseHandler> handshake_response_;
bool started_to_send_handshake_request_;
size_t handshake_request_sent_;
std::vector<std::string> response_cookies_;
size_t response_cookies_save_index_;
scoped_ptr<WebSocketFrameHandler> send_frame_handler_;
scoped_refptr<DrainableIOBuffer> current_buffer_;
scoped_ptr<WebSocketFrameHandler> receive_frame_handler_;
DISALLOW_COPY_AND_ASSIGN(WebSocketJob);
};
} // namespace
#endif // NET_WEBSOCKETS_WEBSOCKET_JOB_H_