Revert "Temporarily landing my ClientSocketPool refactor. Will revert right after."
Review URL: http://codereview.chromium.org/113760 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16732 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
base
net
@ -447,11 +447,4 @@ std::vector<T> SetToVector(const std::set<T>& values) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Test to see if a set, map, hash_set or hash_map contains a particular key.
|
||||
// Returns true if the key is in the collection.
|
||||
template <typename Collection, typename Key>
|
||||
bool ContainsKey(const Collection& collection, const Key& key) {
|
||||
return collection.find(key) != collection.end();
|
||||
}
|
||||
|
||||
#endif // BASE_STL_UTIL_INL_H_
|
||||
|
@ -4,70 +4,37 @@
|
||||
|
||||
#include "net/base/client_socket_handle.h"
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "net/base/client_socket.h"
|
||||
#include "net/base/client_socket_pool.h"
|
||||
#include "net/base/net_errors.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
ClientSocketHandle::ClientSocketHandle(ClientSocketPool* pool)
|
||||
: pool_(pool),
|
||||
socket_(NULL),
|
||||
is_reused_(false),
|
||||
ALLOW_THIS_IN_INITIALIZER_LIST(
|
||||
callback_(this, &ClientSocketHandle::OnIOComplete)) {}
|
||||
: pool_(pool), socket_(NULL) {
|
||||
}
|
||||
|
||||
ClientSocketHandle::~ClientSocketHandle() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
int ClientSocketHandle::Init(const std::string& group_name,
|
||||
const std::string& host,
|
||||
int port,
|
||||
int priority,
|
||||
CompletionCallback* callback) {
|
||||
ResetInternal(true);
|
||||
Reset();
|
||||
group_name_ = group_name;
|
||||
user_callback_ = callback;
|
||||
return pool_->RequestSocket(
|
||||
group_name, host, port, priority, this, &callback_);
|
||||
return pool_->RequestSocket(this, priority, callback);
|
||||
}
|
||||
|
||||
void ClientSocketHandle::Reset() {
|
||||
ResetInternal(true);
|
||||
}
|
||||
|
||||
void ClientSocketHandle::ResetInternal(bool cancel) {
|
||||
if (group_name_.empty()) // Was Init called?
|
||||
return;
|
||||
if (socket_.get()) {
|
||||
// If we've still got a socket, release it back to the ClientSocketPool so
|
||||
// it can be deleted or reused.
|
||||
pool_->ReleaseSocket(group_name_, release_socket());
|
||||
} else if (cancel) {
|
||||
// If we did not get initialized yet, so we've got a socket request pending.
|
||||
// Cancel it.
|
||||
pool_->CancelRequest(group_name_, this);
|
||||
if (socket_) {
|
||||
pool_->ReleaseSocket(this);
|
||||
socket_ = NULL;
|
||||
} else {
|
||||
pool_->CancelRequest(this);
|
||||
}
|
||||
group_name_.clear();
|
||||
is_reused_ = false;
|
||||
user_callback_ = NULL;
|
||||
}
|
||||
|
||||
LoadState ClientSocketHandle::GetLoadState() const {
|
||||
DCHECK(!is_initialized());
|
||||
DCHECK(!group_name_.empty());
|
||||
return pool_->GetLoadState(group_name_, this);
|
||||
}
|
||||
|
||||
void ClientSocketHandle::OnIOComplete(int result) {
|
||||
DCHECK_NE(ERR_IO_PENDING, result);
|
||||
CompletionCallback* callback = user_callback_;
|
||||
user_callback_ = NULL;
|
||||
if (result != OK)
|
||||
ResetInternal(false); // The request failed, so there's nothing to cancel.
|
||||
callback->Run(result);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
|
@ -11,43 +11,40 @@
|
||||
#include "base/scoped_ptr.h"
|
||||
#include "net/base/client_socket.h"
|
||||
#include "net/base/completion_callback.h"
|
||||
#include "net/base/load_states.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
class ClientSocketPool;
|
||||
|
||||
// A container for a ClientSocket.
|
||||
// A container for a connected ClientSocket.
|
||||
//
|
||||
// The handle's |group_name| uniquely identifies the origin and type of the
|
||||
// connection. It is used by the ClientSocketPool to group similar connected
|
||||
// client socket objects.
|
||||
//
|
||||
// A handle is initialized with a null socket. It is the consumer's job to
|
||||
// initialize a ClientSocket object and set it on the handle.
|
||||
//
|
||||
class ClientSocketHandle {
|
||||
public:
|
||||
explicit ClientSocketHandle(ClientSocketPool* pool);
|
||||
~ClientSocketHandle();
|
||||
|
||||
// Initializes a ClientSocketHandle object, which involves talking to the
|
||||
// ClientSocketPool to obtain a connected socket, possibly reusing one. This
|
||||
// method returns either OK or ERR_IO_PENDING. On ERR_IO_PENDING, |priority|
|
||||
// is used to determine the placement in ClientSocketPool's wait list.
|
||||
// ClientSocketPool to locate a socket to possibly reuse. This method
|
||||
// returns either OK or ERR_IO_PENDING. On ERR_IO_PENDING, |priority| is
|
||||
// used to determine the placement in ClientSocketPool's wait list.
|
||||
//
|
||||
// If this method succeeds, then the socket member will be set to an existing
|
||||
// connected socket if an existing connected socket was available to reuse,
|
||||
// otherwise it will be set to a new connected socket. Consumers can then
|
||||
// call is_reused() to see if the socket was reused. If not reusing an
|
||||
// existing socket, ClientSocketPool may need to establish a new
|
||||
// connection to the |host| |port| pair.
|
||||
// socket if an existing socket was available to reuse. Otherwise, the
|
||||
// consumer should set the socket member of this handle.
|
||||
//
|
||||
// This method returns ERR_IO_PENDING if it cannot complete synchronously, in
|
||||
// which case the consumer will be notified of completion via |callback|.
|
||||
// which case the consumer should wait for the completion callback to run.
|
||||
//
|
||||
// Init may be called multiple times.
|
||||
//
|
||||
int Init(const std::string& group_name,
|
||||
const std::string& host,
|
||||
int port,
|
||||
int priority,
|
||||
CompletionCallback* callback);
|
||||
|
||||
@ -57,40 +54,25 @@ class ClientSocketHandle {
|
||||
// the socket may be kept alive for use by a subsequent ClientSocketHandle.
|
||||
//
|
||||
// NOTE: To prevent the socket from being kept alive, be sure to call its
|
||||
// Disconnect method. This will result in the ClientSocketPool deleting the
|
||||
// ClientSocket.
|
||||
// Disconnect method.
|
||||
//
|
||||
void Reset();
|
||||
|
||||
// Used after Init() is called, but before the ClientSocketPool has
|
||||
// initialized the ClientSocketHandle.
|
||||
LoadState GetLoadState() const;
|
||||
|
||||
// Returns true when Init() has completed successfully.
|
||||
// Returns true when Init has completed successfully.
|
||||
bool is_initialized() const { return socket_ != NULL; }
|
||||
|
||||
// Used by ClientSocketPool to initialize the ClientSocketHandle.
|
||||
void set_is_reused(bool is_reused) { is_reused_ = is_reused; }
|
||||
void set_socket(ClientSocket* s) { socket_.reset(s); }
|
||||
|
||||
// These may only be used if is_initialized() is true.
|
||||
const std::string& group_name() const { return group_name_; }
|
||||
ClientSocket* socket() { return socket_.get(); }
|
||||
ClientSocket* release_socket() { return socket_.release(); }
|
||||
bool is_reused() const { return is_reused_; }
|
||||
ClientSocket* socket() { return socket_->get(); }
|
||||
ClientSocket* release_socket() { return socket_->release(); }
|
||||
void set_socket(ClientSocket* s) { socket_->reset(s); }
|
||||
|
||||
private:
|
||||
void OnIOComplete(int result);
|
||||
|
||||
// Resets the state of the ClientSocketHandle. |cancel| indicates whether or
|
||||
// not to try to cancel the request with the ClientSocketPool.
|
||||
void ResetInternal(bool cancel);
|
||||
friend class ClientSocketPool;
|
||||
|
||||
scoped_refptr<ClientSocketPool> pool_;
|
||||
scoped_ptr<ClientSocket> socket_;
|
||||
scoped_ptr<ClientSocket>* socket_;
|
||||
std::string group_name_;
|
||||
bool is_reused_;
|
||||
CompletionCallbackImpl<ClientSocketHandle> callback_;
|
||||
CompletionCallback* user_callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientSocketHandle);
|
||||
};
|
||||
|
@ -4,16 +4,10 @@
|
||||
|
||||
#include "net/base/client_socket_pool.h"
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/field_trial.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/time.h"
|
||||
#include "base/stl_util-inl.h"
|
||||
#include "net/base/client_socket_factory.h"
|
||||
#include "net/base/client_socket.h"
|
||||
#include "net/base/client_socket_handle.h"
|
||||
#include "net/base/dns_resolution_observer.h"
|
||||
#include "net/base/net_errors.h"
|
||||
#include "net/base/tcp_client_socket.h"
|
||||
|
||||
using base::TimeDelta;
|
||||
|
||||
@ -34,123 +28,8 @@ const int kIdleTimeout = 300; // 5 minutes.
|
||||
|
||||
namespace net {
|
||||
|
||||
ClientSocketPool::ConnectingSocket::ConnectingSocket(
|
||||
const std::string& group_name,
|
||||
const ClientSocketHandle* handle,
|
||||
ClientSocketFactory* client_socket_factory,
|
||||
ClientSocketPool* pool)
|
||||
: group_name_(group_name),
|
||||
handle_(handle),
|
||||
client_socket_factory_(client_socket_factory),
|
||||
ALLOW_THIS_IN_INITIALIZER_LIST(
|
||||
callback_(this,
|
||||
&ClientSocketPool::ConnectingSocket::OnIOComplete)),
|
||||
pool_(pool) {}
|
||||
|
||||
ClientSocketPool::ConnectingSocket::~ConnectingSocket() {}
|
||||
|
||||
int ClientSocketPool::ConnectingSocket::Connect(
|
||||
const std::string& host,
|
||||
int port,
|
||||
CompletionCallback* callback) {
|
||||
DidStartDnsResolution(host, this);
|
||||
int rv = resolver_.Resolve(host, port, &addresses_, &callback_);
|
||||
if (rv == OK) {
|
||||
// TODO(willchan): This code is broken. It should be fixed, but the code
|
||||
// path is impossible in the current implementation since the host resolver
|
||||
// always dumps the request to a worker pool, so it cannot complete
|
||||
// synchronously.
|
||||
connect_start_time_ = base::Time::Now();
|
||||
rv = socket_->Connect(&callback_);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
ClientSocket* ClientSocketPool::ConnectingSocket::ReleaseSocket() {
|
||||
return socket_.release();
|
||||
}
|
||||
|
||||
void ClientSocketPool::ConnectingSocket::OnIOComplete(int result) {
|
||||
DCHECK_NE(result, ERR_IO_PENDING);
|
||||
|
||||
GroupMap::iterator group_it = pool_->group_map_.find(group_name_);
|
||||
if (group_it == pool_->group_map_.end()) {
|
||||
// The request corresponding to this ConnectingSocket has been canceled.
|
||||
// Stop bothering with it.
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
Group& group = group_it->second;
|
||||
|
||||
RequestMap* request_map = &group.connecting_requests;
|
||||
RequestMap::iterator it = request_map->find(handle_);
|
||||
if (it == request_map->end()) {
|
||||
// The request corresponding to this ConnectingSocket has been canceled.
|
||||
// Stop bothering with it.
|
||||
group.active_socket_count--;
|
||||
|
||||
// Delete group if no longer needed.
|
||||
if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
|
||||
DCHECK(group.pending_requests.empty());
|
||||
DCHECK(group.connecting_requests.empty());
|
||||
pool_->group_map_.erase(group_it);
|
||||
}
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == OK) {
|
||||
if (it->second.load_state == LOAD_STATE_RESOLVING_HOST) {
|
||||
it->second.load_state = LOAD_STATE_CONNECTING;
|
||||
socket_.reset(client_socket_factory_->CreateTCPClientSocket(addresses_));
|
||||
connect_start_time_ = base::Time::Now();
|
||||
result = socket_->Connect(&callback_);
|
||||
if (result == ERR_IO_PENDING)
|
||||
return;
|
||||
} else {
|
||||
DCHECK(connect_start_time_ != base::Time());
|
||||
base::TimeDelta connect_duration =
|
||||
base::Time::Now() - connect_start_time_;
|
||||
|
||||
UMA_HISTOGRAM_CLIPPED_TIMES(
|
||||
FieldTrial::MakeName(
|
||||
"Net.TCP_Connection_Latency", "DnsImpact").data(),
|
||||
connect_duration,
|
||||
base::TimeDelta::FromMilliseconds(1),
|
||||
base::TimeDelta::FromMinutes(10),
|
||||
100);
|
||||
}
|
||||
}
|
||||
|
||||
// Now, we either succeeded at Connect()'ing, or we failed at host resolution
|
||||
// or Connect()'ing. Either way, we'll run the callback to alert the client.
|
||||
|
||||
Request request = it->second;
|
||||
request_map->erase(it);
|
||||
|
||||
if (result == OK) {
|
||||
request.handle->set_socket(socket_.release());
|
||||
request.handle->set_is_reused(false);
|
||||
} else {
|
||||
group.active_socket_count--;
|
||||
|
||||
// Delete group if no longer needed.
|
||||
if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
|
||||
DCHECK(group.pending_requests.empty());
|
||||
DCHECK(group.connecting_requests.empty());
|
||||
pool_->group_map_.erase(group_it);
|
||||
}
|
||||
}
|
||||
|
||||
request.callback->Run(result);
|
||||
delete this;
|
||||
}
|
||||
|
||||
ClientSocketPool::ClientSocketPool(int max_sockets_per_group,
|
||||
ClientSocketFactory* client_socket_factory)
|
||||
: client_socket_factory_(client_socket_factory),
|
||||
idle_socket_count_(0),
|
||||
ClientSocketPool::ClientSocketPool(int max_sockets_per_group)
|
||||
: idle_socket_count_(0),
|
||||
max_sockets_per_group_(max_sockets_per_group) {
|
||||
}
|
||||
|
||||
@ -175,15 +54,10 @@ void ClientSocketPool::InsertRequestIntoQueue(const Request& r,
|
||||
pending_requests->insert(it, r);
|
||||
}
|
||||
|
||||
int ClientSocketPool::RequestSocket(const std::string& group_name,
|
||||
const std::string& host,
|
||||
int port,
|
||||
int ClientSocketPool::RequestSocket(ClientSocketHandle* handle,
|
||||
int priority,
|
||||
ClientSocketHandle* handle,
|
||||
CompletionCallback* callback) {
|
||||
DCHECK(!host.empty());
|
||||
DCHECK_GE(priority, 0);
|
||||
Group& group = group_map_[group_name];
|
||||
Group& group = group_map_[handle->group_name_];
|
||||
|
||||
// Can we make another active socket now?
|
||||
if (group.active_socket_count == max_sockets_per_group_) {
|
||||
@ -192,9 +66,6 @@ int ClientSocketPool::RequestSocket(const std::string& group_name,
|
||||
DCHECK(callback);
|
||||
r.callback = callback;
|
||||
r.priority = priority;
|
||||
r.host = host;
|
||||
r.port = port;
|
||||
r.load_state = LOAD_STATE_IDLE;
|
||||
InsertRequestIntoQueue(r, &group.pending_requests);
|
||||
return ERR_IO_PENDING;
|
||||
}
|
||||
@ -202,91 +73,49 @@ int ClientSocketPool::RequestSocket(const std::string& group_name,
|
||||
// OK, we are going to activate one.
|
||||
group.active_socket_count++;
|
||||
|
||||
// Use idle sockets in LIFO order because they're more likely to be
|
||||
// still reusable.
|
||||
while (!group.idle_sockets.empty()) {
|
||||
IdleSocket idle_socket = group.idle_sockets.back();
|
||||
group.idle_sockets.pop_back();
|
||||
DecrementIdleCount();
|
||||
if (idle_socket.socket->IsConnectedAndIdle()) {
|
||||
if ((*idle_socket.ptr)->IsConnectedAndIdle()) {
|
||||
// We found one we can reuse!
|
||||
handle->set_socket(idle_socket.socket);
|
||||
handle->set_is_reused(true);
|
||||
handle->socket_ = idle_socket.ptr;
|
||||
return OK;
|
||||
}
|
||||
delete idle_socket.socket;
|
||||
delete idle_socket.ptr;
|
||||
}
|
||||
|
||||
// We couldn't find a socket to reuse, so allocate and connect a new one.
|
||||
scoped_ptr<ConnectingSocket> connecting_socket(
|
||||
new ConnectingSocket(group_name, handle, client_socket_factory_, this));
|
||||
int rv = connecting_socket->Connect(host, port, callback);
|
||||
if (rv == OK) {
|
||||
handle->set_socket(connecting_socket->ReleaseSocket());
|
||||
handle->set_is_reused(false);
|
||||
} else if (rv == ERR_IO_PENDING) {
|
||||
// The ConnectingSocket will delete itself.
|
||||
connecting_socket.release();
|
||||
Request r;
|
||||
r.handle = handle;
|
||||
DCHECK(callback);
|
||||
r.callback = callback;
|
||||
r.priority = priority;
|
||||
r.host = host;
|
||||
r.port = port;
|
||||
r.load_state = LOAD_STATE_RESOLVING_HOST;
|
||||
group_map_[group_name].connecting_requests[handle] = r;
|
||||
} else {
|
||||
group.active_socket_count--;
|
||||
|
||||
// Delete group if no longer needed.
|
||||
if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
|
||||
DCHECK(group.pending_requests.empty());
|
||||
DCHECK(group.connecting_requests.empty());
|
||||
group_map_.erase(group_name);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
handle->socket_ = new ClientSocketPtr();
|
||||
return OK;
|
||||
}
|
||||
|
||||
void ClientSocketPool::CancelRequest(const std::string& group_name,
|
||||
const ClientSocketHandle* handle) {
|
||||
DCHECK(ContainsKey(group_map_, group_name));
|
||||
void ClientSocketPool::CancelRequest(ClientSocketHandle* handle) {
|
||||
Group& group = group_map_[handle->group_name_];
|
||||
|
||||
Group& group = group_map_[group_name];
|
||||
// In order for us to be canceling a pending request, we must have active
|
||||
// sockets equaling the limit. NOTE: The correctness of the code doesn't
|
||||
// require this assertion.
|
||||
DCHECK(group.active_socket_count == max_sockets_per_group_);
|
||||
|
||||
// Search pending_requests for matching handle.
|
||||
RequestQueue::iterator it = group.pending_requests.begin();
|
||||
std::deque<Request>::iterator it = group.pending_requests.begin();
|
||||
for (; it != group.pending_requests.end(); ++it) {
|
||||
if (it->handle == handle) {
|
||||
group.pending_requests.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// It's invalid to cancel a non-existent request.
|
||||
DCHECK(ContainsKey(group.connecting_requests, handle));
|
||||
|
||||
RequestMap::iterator map_it = group.connecting_requests.find(handle);
|
||||
if (map_it != group.connecting_requests.end()) {
|
||||
group.connecting_requests.erase(map_it);
|
||||
group.active_socket_count--;
|
||||
|
||||
// Delete group if no longer needed.
|
||||
if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
|
||||
DCHECK(group.pending_requests.empty());
|
||||
DCHECK(group.connecting_requests.empty());
|
||||
group_map_.erase(group_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientSocketPool::ReleaseSocket(const std::string& group_name,
|
||||
ClientSocket* socket) {
|
||||
void ClientSocketPool::ReleaseSocket(ClientSocketHandle* handle) {
|
||||
// Run this asynchronously to allow the caller to finish before we let
|
||||
// another to begin doing work. This also avoids nasty recursion issues.
|
||||
// NOTE: We cannot refer to the handle argument after this method returns.
|
||||
MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
|
||||
this, &ClientSocketPool::DoReleaseSocket, group_name, socket));
|
||||
this, &ClientSocketPool::DoReleaseSocket, handle->group_name_,
|
||||
handle->socket_));
|
||||
}
|
||||
|
||||
void ClientSocketPool::CloseIdleSockets() {
|
||||
@ -301,42 +130,10 @@ int ClientSocketPool::IdleSocketCountInGroup(
|
||||
return i->second.idle_sockets.size();
|
||||
}
|
||||
|
||||
LoadState ClientSocketPool::GetLoadState(
|
||||
const std::string& group_name,
|
||||
const ClientSocketHandle* handle) const {
|
||||
DCHECK(ContainsKey(group_map_, group_name)) << group_name;
|
||||
|
||||
// Can't use operator[] since it is non-const.
|
||||
const Group& group = group_map_.find(group_name)->second;
|
||||
|
||||
// Search connecting_requests for matching handle.
|
||||
RequestMap::const_iterator map_it = group.connecting_requests.find(handle);
|
||||
if (map_it != group.connecting_requests.end()) {
|
||||
const LoadState load_state = map_it->second.load_state;
|
||||
DCHECK(load_state == LOAD_STATE_RESOLVING_HOST ||
|
||||
load_state == LOAD_STATE_CONNECTING);
|
||||
return load_state;
|
||||
}
|
||||
|
||||
// Search pending_requests for matching handle.
|
||||
RequestQueue::const_iterator it = group.pending_requests.begin();
|
||||
for (; it != group.pending_requests.end(); ++it) {
|
||||
if (it->handle == handle) {
|
||||
DCHECK_EQ(LOAD_STATE_IDLE, it->load_state);
|
||||
// TODO(wtc): Add a state for being on the wait list.
|
||||
// See http://www.crbug.com/5077.
|
||||
return LOAD_STATE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
NOTREACHED();
|
||||
return LOAD_STATE_IDLE;
|
||||
}
|
||||
|
||||
bool ClientSocketPool::IdleSocket::ShouldCleanup(base::TimeTicks now) const {
|
||||
bool timed_out = (now - start_time) >=
|
||||
base::TimeDelta::FromSeconds(kIdleTimeout);
|
||||
return timed_out || !socket->IsConnectedAndIdle();
|
||||
return timed_out || !(*ptr)->IsConnectedAndIdle();
|
||||
}
|
||||
|
||||
void ClientSocketPool::CleanupIdleSockets(bool force) {
|
||||
@ -354,7 +151,7 @@ void ClientSocketPool::CleanupIdleSockets(bool force) {
|
||||
std::deque<IdleSocket>::iterator j = group.idle_sockets.begin();
|
||||
while (j != group.idle_sockets.end()) {
|
||||
if (force || j->ShouldCleanup(now)) {
|
||||
delete j->socket;
|
||||
delete j->ptr;
|
||||
j = group.idle_sockets.erase(j);
|
||||
DecrementIdleCount();
|
||||
} else {
|
||||
@ -365,7 +162,6 @@ void ClientSocketPool::CleanupIdleSockets(bool force) {
|
||||
// Delete group if no longer needed.
|
||||
if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
|
||||
DCHECK(group.pending_requests.empty());
|
||||
DCHECK(group.connecting_requests.empty());
|
||||
group_map_.erase(i++);
|
||||
} else {
|
||||
++i;
|
||||
@ -385,43 +181,40 @@ void ClientSocketPool::DecrementIdleCount() {
|
||||
}
|
||||
|
||||
void ClientSocketPool::DoReleaseSocket(const std::string& group_name,
|
||||
ClientSocket* socket) {
|
||||
ClientSocketPtr* ptr) {
|
||||
GroupMap::iterator i = group_map_.find(group_name);
|
||||
DCHECK(i != group_map_.end());
|
||||
|
||||
Group& group = i->second;
|
||||
|
||||
DCHECK_GT(group.active_socket_count, 0);
|
||||
DCHECK(group.active_socket_count > 0);
|
||||
group.active_socket_count--;
|
||||
|
||||
const bool can_reuse = socket->IsConnectedAndIdle();
|
||||
bool can_reuse = ptr->get() && (*ptr)->IsConnectedAndIdle();
|
||||
if (can_reuse) {
|
||||
IdleSocket idle_socket;
|
||||
idle_socket.socket = socket;
|
||||
idle_socket.ptr = ptr;
|
||||
idle_socket.start_time = base::TimeTicks::Now();
|
||||
|
||||
group.idle_sockets.push_back(idle_socket);
|
||||
IncrementIdleCount();
|
||||
} else {
|
||||
delete socket;
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
// Process one pending request.
|
||||
if (!group.pending_requests.empty()) {
|
||||
Request r = group.pending_requests.front();
|
||||
group.pending_requests.pop_front();
|
||||
|
||||
int rv = RequestSocket(
|
||||
group_name, r.host, r.port, r.priority, r.handle, r.callback);
|
||||
if (rv != ERR_IO_PENDING)
|
||||
r.callback->Run(rv);
|
||||
int rv = RequestSocket(r.handle, r.priority, NULL);
|
||||
DCHECK(rv == OK);
|
||||
r.callback->Run(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete group if no longer needed.
|
||||
if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
|
||||
DCHECK(group.pending_requests.empty());
|
||||
DCHECK(group.connecting_requests.empty());
|
||||
group_map_.erase(i);
|
||||
}
|
||||
}
|
||||
|
@ -12,66 +12,58 @@
|
||||
#include "base/ref_counted.h"
|
||||
#include "base/scoped_ptr.h"
|
||||
#include "base/timer.h"
|
||||
#include "net/base/address_list.h"
|
||||
#include "net/base/completion_callback.h"
|
||||
#include "net/base/host_resolver.h"
|
||||
#include "net/base/load_states.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
class ClientSocket;
|
||||
class ClientSocketFactory;
|
||||
class ClientSocketHandle;
|
||||
|
||||
// A ClientSocketPool is used to restrict the number of sockets open at a time.
|
||||
// It also maintains a list of idle persistent sockets.
|
||||
//
|
||||
// The ClientSocketPool allocates scoped_ptr<ClientSocket> objects, but it is
|
||||
// not responsible for allocating the associated ClientSocket objects. The
|
||||
// consumer must do so if it gets a scoped_ptr<ClientSocket> with a null value.
|
||||
//
|
||||
class ClientSocketPool : public base::RefCounted<ClientSocketPool> {
|
||||
public:
|
||||
ClientSocketPool(int max_sockets_per_group,
|
||||
ClientSocketFactory* client_socket_factory);
|
||||
explicit ClientSocketPool(int max_sockets_per_group);
|
||||
|
||||
// Requests a connected socket for a group_name.
|
||||
//
|
||||
// There are four possible results from calling this function:
|
||||
// 1) RequestSocket returns OK and initializes |handle| with a reused socket.
|
||||
// 2) RequestSocket returns OK with a newly connected socket.
|
||||
// 3) RequestSocket returns ERR_IO_PENDING. The handle will be added to a
|
||||
// wait list until a socket is available to reuse or a new socket finishes
|
||||
// connecting. |priority| will determine the placement into the wait list.
|
||||
// 4) An error occurred early on, so RequestSocket returns an error code.
|
||||
// Called to request a socket for the given handle. There are three possible
|
||||
// results: 1) the handle will be initialized with a socket to reuse, 2) the
|
||||
// handle will be initialized without a socket such that the consumer needs
|
||||
// to supply a socket, or 3) the handle will be added to a wait list until a
|
||||
// socket is available to reuse or the opportunity to create a new socket
|
||||
// arises. The completion callback is notified in the 3rd case. |priority|
|
||||
// will determine the placement into the wait list.
|
||||
//
|
||||
// If this function returns OK, then |handle| is initialized upon return.
|
||||
// The |handle|'s is_initialized method will return true in this case. If a
|
||||
// ClientSocket was reused, then ClientSocketPool will call
|
||||
// |handle|->set_reused(true). In either case, the socket will have been
|
||||
// allocated and will be connected. A client might want to know whether or
|
||||
// not the socket is reused in order to know whether or not he needs to
|
||||
// perform SSL connection or tunnel setup or to request a new socket if he
|
||||
// encounters an error with the reused socket.
|
||||
// ClientSocket was reused, then |handle|'s socket member will be non-NULL.
|
||||
// Otherwise, the consumer will need to supply |handle| with a socket by
|
||||
// allocating a new ClientSocket object and calling the |handle|'s set_socket
|
||||
// method.
|
||||
//
|
||||
// If ERR_IO_PENDING is returned, then the callback will be used to notify the
|
||||
// client of completion.
|
||||
// If ERR_IO_PENDING is returned, then the completion callback will be called
|
||||
// when |handle| has been initialized.
|
||||
//
|
||||
int RequestSocket(const std::string& group_name,
|
||||
const std::string& host,
|
||||
int port,
|
||||
int RequestSocket(ClientSocketHandle* handle,
|
||||
int priority,
|
||||
ClientSocketHandle* handle,
|
||||
CompletionCallback* callback);
|
||||
|
||||
// Called to cancel a RequestSocket call that returned ERR_IO_PENDING. The
|
||||
// same handle parameter must be passed to this method as was passed to the
|
||||
// RequestSocket call being cancelled. The associated CompletionCallback is
|
||||
// not run.
|
||||
void CancelRequest(const std::string& group_name,
|
||||
const ClientSocketHandle* handle);
|
||||
void CancelRequest(ClientSocketHandle* handle);
|
||||
|
||||
// Called to release a socket once the socket is no longer needed. If the
|
||||
// socket still has an established connection, then it will be added to the
|
||||
// set of idle sockets to be used to satisfy future RequestSocket calls.
|
||||
// Otherwise, the ClientSocket is destroyed.
|
||||
void ReleaseSocket(const std::string& group_name, ClientSocket* socket);
|
||||
// Called to release the socket member of an initialized ClientSocketHandle
|
||||
// once the socket is no longer needed. If the socket member is non-null and
|
||||
// still has an established connection, then it will be added to the idle set
|
||||
// of sockets to be used to satisfy future RequestSocket calls. Otherwise,
|
||||
// the ClientSocket is destroyed.
|
||||
void ReleaseSocket(ClientSocketHandle* handle);
|
||||
|
||||
// Called to close any idle connections held by the connection manager.
|
||||
void CloseIdleSockets();
|
||||
@ -84,27 +76,22 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> {
|
||||
// The total number of idle sockets in a connection group.
|
||||
int IdleSocketCountInGroup(const std::string& group_name) const;
|
||||
|
||||
// Determine the LoadState of a connecting ClientSocketHandle.
|
||||
LoadState GetLoadState(const std::string& group_name,
|
||||
const ClientSocketHandle* handle) const;
|
||||
|
||||
private:
|
||||
friend class base::RefCounted<ClientSocketPool>;
|
||||
|
||||
typedef scoped_ptr<ClientSocket> ClientSocketPtr;
|
||||
|
||||
// A Request is allocated per call to RequestSocket that results in
|
||||
// ERR_IO_PENDING.
|
||||
struct Request {
|
||||
ClientSocketHandle* handle;
|
||||
CompletionCallback* callback;
|
||||
int priority;
|
||||
std::string host;
|
||||
int port;
|
||||
LoadState load_state;
|
||||
};
|
||||
|
||||
// Entry for a persistent socket which became idle at time |start_time|.
|
||||
struct IdleSocket {
|
||||
ClientSocket* socket;
|
||||
ClientSocketPtr* ptr;
|
||||
base::TimeTicks start_time;
|
||||
|
||||
// An idle socket should be removed if it can't be reused, or has been idle
|
||||
@ -118,7 +105,6 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> {
|
||||
};
|
||||
|
||||
typedef std::deque<Request> RequestQueue;
|
||||
typedef std::map<const ClientSocketHandle*, Request> RequestMap;
|
||||
|
||||
// A Group is allocated per group_name when there are idle sockets or pending
|
||||
// requests. Otherwise, the Group object is removed from the map.
|
||||
@ -126,57 +112,11 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> {
|
||||
Group() : active_socket_count(0) {}
|
||||
std::deque<IdleSocket> idle_sockets;
|
||||
RequestQueue pending_requests;
|
||||
RequestMap connecting_requests;
|
||||
int active_socket_count;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, Group> GroupMap;
|
||||
|
||||
// ConnectingSocket handles the host resolution necessary for socket creation
|
||||
// and the Connect().
|
||||
class ConnectingSocket {
|
||||
public:
|
||||
enum State {
|
||||
STATE_RESOLVE_HOST,
|
||||
STATE_CONNECT
|
||||
};
|
||||
|
||||
ConnectingSocket(const std::string& group_name,
|
||||
const ClientSocketHandle* handle,
|
||||
ClientSocketFactory* client_socket_factory,
|
||||
ClientSocketPool* pool);
|
||||
~ConnectingSocket();
|
||||
|
||||
// Begins the host resolution and the TCP connect. Returns OK on success,
|
||||
// in which case |callback| is not called. On pending IO, Connect returns
|
||||
// ERR_IO_PENDING and runs |callback| on completion.
|
||||
int Connect(const std::string& host,
|
||||
int port,
|
||||
CompletionCallback* callback);
|
||||
|
||||
// If Connect() returns OK, ClientSocketPool may invoke this method to get
|
||||
// the ConnectingSocket to release |socket_| to be set into the
|
||||
// ClientSocketHandle immediately.
|
||||
ClientSocket* ReleaseSocket();
|
||||
|
||||
private:
|
||||
void OnIOComplete(int result);
|
||||
|
||||
const std::string group_name_;
|
||||
const ClientSocketHandle* const handle_;
|
||||
ClientSocketFactory* const client_socket_factory_;
|
||||
CompletionCallbackImpl<ConnectingSocket> callback_;
|
||||
scoped_ptr<ClientSocket> socket_;
|
||||
scoped_refptr<ClientSocketPool> pool_;
|
||||
HostResolver resolver_;
|
||||
AddressList addresses_;
|
||||
|
||||
// The time the Connect() method was called (if it got called).
|
||||
base::Time connect_start_time_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ConnectingSocket);
|
||||
};
|
||||
|
||||
~ClientSocketPool();
|
||||
|
||||
static void InsertRequestIntoQueue(const Request& r,
|
||||
@ -191,7 +131,7 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> {
|
||||
void DecrementIdleCount();
|
||||
|
||||
// Called via PostTask by ReleaseSocket.
|
||||
void DoReleaseSocket(const std::string& group_name, ClientSocket* socket);
|
||||
void DoReleaseSocket(const std::string& group_name, ClientSocketPtr* ptr);
|
||||
|
||||
// Called when timer_ fires. This method scans the idle sockets removing
|
||||
// sockets that timed out or can't be reused.
|
||||
@ -199,8 +139,6 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> {
|
||||
CleanupIdleSockets(false);
|
||||
}
|
||||
|
||||
ClientSocketFactory* const client_socket_factory_;
|
||||
|
||||
GroupMap group_map_;
|
||||
|
||||
// Timer used to periodically prune idle sockets that timed out or can't be
|
||||
@ -211,7 +149,7 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> {
|
||||
int idle_socket_count_;
|
||||
|
||||
// The maximum number of sockets kept per group.
|
||||
const int max_sockets_per_group_;
|
||||
int max_sockets_per_group_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientSocketPool);
|
||||
};
|
||||
|
@ -4,16 +4,11 @@
|
||||
|
||||
#include "base/message_loop.h"
|
||||
#include "net/base/client_socket.h"
|
||||
#include "net/base/client_socket_factory.h"
|
||||
#include "net/base/client_socket_handle.h"
|
||||
#include "net/base/client_socket_pool.h"
|
||||
#include "net/base/host_resolver_unittest.h"
|
||||
#include "net/base/net_errors.h"
|
||||
#include "net/base/test_completion_callback.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
namespace {
|
||||
|
||||
const int kMaxSocketsPerGroup = 6;
|
||||
@ -26,16 +21,16 @@ const int kPriorities[10] = { 1, 7, 9, 5, 6, 2, 8, 3, 4, 1 };
|
||||
// available sockets in the socket group.
|
||||
const int kNumPendingRequests = arraysize(kPriorities);
|
||||
|
||||
const int kNumRequests = kMaxSocketsPerGroup + kNumPendingRequests;
|
||||
|
||||
class MockClientSocket : public ClientSocket {
|
||||
class MockClientSocket : public net::ClientSocket {
|
||||
public:
|
||||
MockClientSocket() : connected_(false) {}
|
||||
MockClientSocket() : connected_(false) {
|
||||
allocation_count++;
|
||||
}
|
||||
|
||||
// ClientSocket methods:
|
||||
virtual int Connect(CompletionCallback* callback) {
|
||||
virtual int Connect(net::CompletionCallback* callback) {
|
||||
connected_ = true;
|
||||
return OK;
|
||||
return net::OK;
|
||||
}
|
||||
virtual void Disconnect() {
|
||||
connected_ = false;
|
||||
@ -48,115 +43,51 @@ class MockClientSocket : public ClientSocket {
|
||||
}
|
||||
|
||||
// Socket methods:
|
||||
virtual int Read(IOBuffer* buf, int buf_len,
|
||||
CompletionCallback* callback) {
|
||||
return ERR_FAILED;
|
||||
virtual int Read(net::IOBuffer* buf, int buf_len,
|
||||
net::CompletionCallback* callback) {
|
||||
return net::ERR_FAILED;
|
||||
}
|
||||
virtual int Write(IOBuffer* buf, int buf_len,
|
||||
CompletionCallback* callback) {
|
||||
return ERR_FAILED;
|
||||
virtual int Write(net::IOBuffer* buf, int buf_len,
|
||||
net::CompletionCallback* callback) {
|
||||
return net::ERR_FAILED;
|
||||
}
|
||||
|
||||
static int allocation_count;
|
||||
|
||||
private:
|
||||
bool connected_;
|
||||
};
|
||||
|
||||
class MockFailingClientSocket : public ClientSocket {
|
||||
public:
|
||||
MockFailingClientSocket() {}
|
||||
|
||||
// ClientSocket methods:
|
||||
virtual int Connect(CompletionCallback* callback) {
|
||||
return ERR_CONNECTION_FAILED;
|
||||
}
|
||||
|
||||
virtual void Disconnect() {}
|
||||
|
||||
virtual bool IsConnected() const {
|
||||
return false;
|
||||
}
|
||||
virtual bool IsConnectedAndIdle() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Socket methods:
|
||||
virtual int Read(IOBuffer* buf, int buf_len,
|
||||
CompletionCallback* callback) {
|
||||
return ERR_FAILED;
|
||||
}
|
||||
|
||||
virtual int Write(IOBuffer* buf, int buf_len,
|
||||
CompletionCallback* callback) {
|
||||
return ERR_FAILED;
|
||||
}
|
||||
};
|
||||
|
||||
class MockClientSocketFactory : public ClientSocketFactory {
|
||||
public:
|
||||
enum ClientSocketType {
|
||||
MOCK_CLIENT_SOCKET,
|
||||
MOCK_FAILING_CLIENT_SOCKET,
|
||||
};
|
||||
|
||||
MockClientSocketFactory()
|
||||
: allocation_count_(0), client_socket_type_(MOCK_CLIENT_SOCKET) {}
|
||||
|
||||
virtual ClientSocket* CreateTCPClientSocket(const AddressList& addresses) {
|
||||
allocation_count_++;
|
||||
switch (client_socket_type_) {
|
||||
case MOCK_CLIENT_SOCKET:
|
||||
return new MockClientSocket();
|
||||
case MOCK_FAILING_CLIENT_SOCKET:
|
||||
return new MockFailingClientSocket();
|
||||
default:
|
||||
NOTREACHED();
|
||||
return new MockClientSocket();
|
||||
}
|
||||
}
|
||||
|
||||
virtual SSLClientSocket* CreateSSLClientSocket(
|
||||
ClientSocket* transport_socket,
|
||||
const std::string& hostname,
|
||||
const SSLConfig& ssl_config) {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int allocation_count() const { return allocation_count_; }
|
||||
|
||||
void set_client_socket_type(ClientSocketType type) {
|
||||
client_socket_type_ = type;
|
||||
}
|
||||
|
||||
private:
|
||||
int allocation_count_;
|
||||
ClientSocketType client_socket_type_;
|
||||
};
|
||||
int MockClientSocket::allocation_count = 0;
|
||||
|
||||
class TestSocketRequest : public CallbackRunner< Tuple1<int> > {
|
||||
public:
|
||||
TestSocketRequest(
|
||||
ClientSocketPool* pool,
|
||||
net::ClientSocketPool* pool,
|
||||
std::vector<TestSocketRequest*>* request_order)
|
||||
: handle(pool), request_order_(request_order) {}
|
||||
|
||||
ClientSocketHandle handle;
|
||||
net::ClientSocketHandle handle;
|
||||
|
||||
int WaitForResult() {
|
||||
return callback_.WaitForResult();
|
||||
void EnsureSocket() {
|
||||
DCHECK(handle.is_initialized());
|
||||
request_order_->push_back(this);
|
||||
if (!handle.socket()) {
|
||||
handle.set_socket(new MockClientSocket());
|
||||
handle.socket()->Connect(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void RunWithParams(const Tuple1<int>& params) {
|
||||
callback_.RunWithParams(params);
|
||||
DCHECK(params.a == net::OK);
|
||||
completion_count++;
|
||||
request_order_->push_back(this);
|
||||
EnsureSocket();
|
||||
}
|
||||
|
||||
static int completion_count;
|
||||
|
||||
private:
|
||||
std::vector<TestSocketRequest*>* request_order_;
|
||||
TestCompletionCallback callback_;
|
||||
};
|
||||
|
||||
int TestSocketRequest::completion_count = 0;
|
||||
@ -164,76 +95,68 @@ int TestSocketRequest::completion_count = 0;
|
||||
class ClientSocketPoolTest : public testing::Test {
|
||||
protected:
|
||||
ClientSocketPoolTest()
|
||||
: pool_(new ClientSocketPool(kMaxSocketsPerGroup,
|
||||
&client_socket_factory_)) {}
|
||||
: pool_(new net::ClientSocketPool(kMaxSocketsPerGroup)) {}
|
||||
|
||||
virtual void SetUp() {
|
||||
MockClientSocket::allocation_count = 0;
|
||||
TestSocketRequest::completion_count = 0;
|
||||
}
|
||||
|
||||
MockClientSocketFactory client_socket_factory_;
|
||||
scoped_refptr<ClientSocketPool> pool_;
|
||||
scoped_refptr<net::ClientSocketPool> pool_;
|
||||
std::vector<TestSocketRequest*> request_order_;
|
||||
};
|
||||
|
||||
TEST_F(ClientSocketPoolTest, Basic) {
|
||||
TestCompletionCallback callback;
|
||||
ClientSocketHandle handle(pool_.get());
|
||||
int rv = handle.Init("a", "www.google.com", 80, 0, &callback);
|
||||
EXPECT_EQ(ERR_IO_PENDING, rv);
|
||||
EXPECT_FALSE(handle.is_initialized());
|
||||
EXPECT_FALSE(handle.socket());
|
||||
TestSocketRequest r(pool_.get(), &request_order_);
|
||||
int rv;
|
||||
|
||||
EXPECT_EQ(OK, callback.WaitForResult());
|
||||
EXPECT_TRUE(handle.is_initialized());
|
||||
EXPECT_TRUE(handle.socket());
|
||||
rv = r.handle.Init("a", 0, &r);
|
||||
EXPECT_EQ(net::OK, rv);
|
||||
EXPECT_TRUE(r.handle.is_initialized());
|
||||
|
||||
handle.Reset();
|
||||
r.handle.Reset();
|
||||
|
||||
// The handle's Reset method may have posted a task.
|
||||
MessageLoop::current()->RunAllPending();
|
||||
}
|
||||
|
||||
TEST_F(ClientSocketPoolTest, InitHostResolutionFailure) {
|
||||
RuleBasedHostMapper* host_mapper = new RuleBasedHostMapper;
|
||||
host_mapper->AddSimulatedFailure("unresolvable.host.name");
|
||||
ScopedHostMapper scoped_host_mapper(host_mapper);
|
||||
TestSocketRequest req(pool_.get(), &request_order_);
|
||||
EXPECT_EQ(ERR_IO_PENDING,
|
||||
req.handle.Init("a", "unresolvable.host.name", 80, 5, &req));
|
||||
EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req.WaitForResult());
|
||||
}
|
||||
TEST_F(ClientSocketPoolTest, WithIdleConnection) {
|
||||
TestSocketRequest r(pool_.get(), &request_order_);
|
||||
int rv;
|
||||
|
||||
TEST_F(ClientSocketPoolTest, InitConnectionFailure) {
|
||||
client_socket_factory_.set_client_socket_type(
|
||||
MockClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET);
|
||||
TestSocketRequest req(pool_.get(), &request_order_);
|
||||
EXPECT_EQ(ERR_IO_PENDING,
|
||||
req.handle.Init("a", "unresolvable.host.name", 80, 5, &req));
|
||||
EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult());
|
||||
rv = r.handle.Init("a", 0, &r);
|
||||
EXPECT_EQ(net::OK, rv);
|
||||
EXPECT_TRUE(r.handle.is_initialized());
|
||||
|
||||
// Create a socket.
|
||||
r.EnsureSocket();
|
||||
|
||||
// Release the socket. It should find its way into the idle list. We're
|
||||
// testing that this does not trigger a crash.
|
||||
r.handle.Reset();
|
||||
|
||||
// The handle's Reset method may have posted a task.
|
||||
MessageLoop::current()->RunAllPending();
|
||||
}
|
||||
|
||||
TEST_F(ClientSocketPoolTest, PendingRequests) {
|
||||
int rv;
|
||||
|
||||
scoped_ptr<TestSocketRequest> reqs[kNumRequests];
|
||||
scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + kNumPendingRequests];
|
||||
|
||||
for (size_t i = 0; i < arraysize(reqs); ++i)
|
||||
reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
|
||||
|
||||
// Create connections or queue up requests.
|
||||
for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
|
||||
EXPECT_EQ(
|
||||
ERR_IO_PENDING,
|
||||
reqs[i]->handle.Init("a", "www.google.com", 80, 5, reqs[i].get()));
|
||||
EXPECT_EQ(OK, reqs[i]->WaitForResult());
|
||||
rv = reqs[i]->handle.Init("a", 5, reqs[i].get());
|
||||
EXPECT_EQ(net::OK, rv);
|
||||
reqs[i]->EnsureSocket();
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumPendingRequests; ++i) {
|
||||
rv = reqs[kMaxSocketsPerGroup + i]->handle.Init(
|
||||
"a", "www.google.com", 80, kPriorities[i],
|
||||
reqs[kMaxSocketsPerGroup + i].get());
|
||||
EXPECT_EQ(ERR_IO_PENDING, rv);
|
||||
"a", kPriorities[i], reqs[kMaxSocketsPerGroup + i].get());
|
||||
EXPECT_EQ(net::ERR_IO_PENDING, rv);
|
||||
}
|
||||
|
||||
// Release any connections until we have no connections.
|
||||
@ -249,8 +172,8 @@ TEST_F(ClientSocketPoolTest, PendingRequests) {
|
||||
}
|
||||
} while (released_one);
|
||||
|
||||
EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count());
|
||||
EXPECT_EQ(kNumRequests, TestSocketRequest::completion_count);
|
||||
EXPECT_EQ(kMaxSocketsPerGroup, MockClientSocket::allocation_count);
|
||||
EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count);
|
||||
|
||||
for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
|
||||
EXPECT_EQ(request_order_[i], reqs[i].get()) <<
|
||||
@ -271,77 +194,58 @@ TEST_F(ClientSocketPoolTest, PendingRequests) {
|
||||
}
|
||||
|
||||
TEST_F(ClientSocketPoolTest, PendingRequests_NoKeepAlive) {
|
||||
scoped_ptr<TestSocketRequest> reqs[kNumRequests];
|
||||
int rv;
|
||||
|
||||
scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + kNumPendingRequests];
|
||||
for (size_t i = 0; i < arraysize(reqs); ++i)
|
||||
reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
|
||||
|
||||
// Create connections or queue up requests.
|
||||
for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
|
||||
EXPECT_EQ(
|
||||
ERR_IO_PENDING,
|
||||
reqs[i]->handle.Init("a", "www.google.com", 80, 0, reqs[i].get()));
|
||||
EXPECT_EQ(OK, reqs[i]->WaitForResult());
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumPendingRequests; ++i) {
|
||||
EXPECT_EQ(ERR_IO_PENDING, reqs[kMaxSocketsPerGroup + i]->handle.Init(
|
||||
"a", "www.google.com", 80, 0, reqs[kMaxSocketsPerGroup + i].get()));
|
||||
for (size_t i = 0; i < arraysize(reqs); ++i) {
|
||||
rv = reqs[i]->handle.Init("a", 0, reqs[i].get());
|
||||
if (rv != net::ERR_IO_PENDING) {
|
||||
EXPECT_EQ(net::OK, rv);
|
||||
reqs[i]->EnsureSocket();
|
||||
}
|
||||
}
|
||||
|
||||
// Release any connections until we have no connections.
|
||||
|
||||
while (TestSocketRequest::completion_count < kNumRequests) {
|
||||
int num_released = 0;
|
||||
bool released_one;
|
||||
do {
|
||||
released_one = false;
|
||||
for (size_t i = 0; i < arraysize(reqs); ++i) {
|
||||
if (reqs[i]->handle.is_initialized()) {
|
||||
reqs[i]->handle.socket()->Disconnect();
|
||||
reqs[i]->handle.Reset();
|
||||
num_released++;
|
||||
MessageLoop::current()->RunAllPending();
|
||||
released_one = true;
|
||||
}
|
||||
}
|
||||
int curr_num_completed = TestSocketRequest::completion_count;
|
||||
for (int i = 0;
|
||||
(i < num_released) && (i + curr_num_completed < kNumRequests); ++i) {
|
||||
EXPECT_EQ(OK, reqs[i + curr_num_completed]->WaitForResult());
|
||||
}
|
||||
}
|
||||
} while (released_one);
|
||||
|
||||
EXPECT_EQ(kNumRequests, client_socket_factory_.allocation_count());
|
||||
EXPECT_EQ(kNumRequests, TestSocketRequest::completion_count);
|
||||
}
|
||||
|
||||
// This test will start up a RequestSocket() and then immediately Cancel() it.
|
||||
// The pending host resolution will eventually complete, and destroy the
|
||||
// ClientSocketPool which will crash if the group was not cleared properly.
|
||||
TEST_F(ClientSocketPoolTest, CancelRequestClearGroup) {
|
||||
TestSocketRequest req(pool_.get(), &request_order_);
|
||||
EXPECT_EQ(ERR_IO_PENDING,
|
||||
req.handle.Init("a", "www.google.com", 80, 5, &req));
|
||||
req.handle.Reset();
|
||||
// There is a race condition here. If the worker pool doesn't post the task
|
||||
// before we get here, then this might not run ConnectingSocket::IOComplete
|
||||
// and therefore leak the canceled ConnectingSocket.
|
||||
MessageLoop::current()->RunAllPending();
|
||||
EXPECT_EQ(kMaxSocketsPerGroup + kNumPendingRequests,
|
||||
MockClientSocket::allocation_count);
|
||||
EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count);
|
||||
}
|
||||
|
||||
TEST_F(ClientSocketPoolTest, CancelRequest) {
|
||||
scoped_ptr<TestSocketRequest> reqs[kNumRequests];
|
||||
int rv;
|
||||
|
||||
scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + kNumPendingRequests];
|
||||
|
||||
for (size_t i = 0; i < arraysize(reqs); ++i)
|
||||
reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
|
||||
|
||||
// Create connections or queue up requests.
|
||||
for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
|
||||
EXPECT_EQ(
|
||||
ERR_IO_PENDING,
|
||||
reqs[i]->handle.Init("a", "www.google.com", 80, 5, reqs[i].get()));
|
||||
EXPECT_EQ(OK, reqs[i]->WaitForResult());
|
||||
rv = reqs[i]->handle.Init("a", 5, reqs[i].get());
|
||||
EXPECT_EQ(net::OK, rv);
|
||||
reqs[i]->EnsureSocket();
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumPendingRequests; ++i) {
|
||||
EXPECT_EQ(ERR_IO_PENDING, reqs[kMaxSocketsPerGroup + i]->handle.Init(
|
||||
"a", "www.google.com", 80, kPriorities[i],
|
||||
reqs[kMaxSocketsPerGroup + i].get()));
|
||||
rv = reqs[kMaxSocketsPerGroup + i]->handle.Init(
|
||||
"a", kPriorities[i], reqs[kMaxSocketsPerGroup + i].get());
|
||||
EXPECT_EQ(net::ERR_IO_PENDING, rv);
|
||||
}
|
||||
|
||||
// Cancel a request.
|
||||
@ -362,8 +266,8 @@ TEST_F(ClientSocketPoolTest, CancelRequest) {
|
||||
}
|
||||
} while (released_one);
|
||||
|
||||
EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count());
|
||||
EXPECT_EQ(kNumRequests - 1, TestSocketRequest::completion_count);
|
||||
EXPECT_EQ(kMaxSocketsPerGroup, MockClientSocket::allocation_count);
|
||||
EXPECT_EQ(kNumPendingRequests - 1, TestSocketRequest::completion_count);
|
||||
for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
|
||||
EXPECT_EQ(request_order_[i], reqs[i].get()) <<
|
||||
"Request " << i << " was not in order.";
|
||||
@ -386,5 +290,3 @@ TEST_F(ClientSocketPoolTest, CancelRequest) {
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace net
|
||||
|
@ -38,6 +38,7 @@ class TestCompletionCallback : public CallbackRunner< Tuple1<int> > {
|
||||
return result_;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void RunWithParams(const Tuple1<int>& params) {
|
||||
result_ = params.a;
|
||||
have_result_ = true;
|
||||
@ -45,7 +46,6 @@ class TestCompletionCallback : public CallbackRunner< Tuple1<int> > {
|
||||
MessageLoop::current()->Quit();
|
||||
}
|
||||
|
||||
private:
|
||||
int result_;
|
||||
bool have_result_;
|
||||
bool waiting_for_result_;
|
||||
|
@ -66,8 +66,7 @@ void HttpNetworkLayer::Suspend(bool suspend) {
|
||||
HttpNetworkSession* HttpNetworkLayer::GetSession() {
|
||||
if (!session_) {
|
||||
DCHECK(proxy_service_);
|
||||
session_ = new HttpNetworkSession(proxy_service_,
|
||||
ClientSocketFactory::GetDefaultFactory());
|
||||
session_ = new HttpNetworkSession(proxy_service_);
|
||||
}
|
||||
return session_;
|
||||
}
|
||||
|
@ -12,16 +12,13 @@
|
||||
|
||||
namespace net {
|
||||
|
||||
class ClientSocketFactory;
|
||||
class ProxyService;
|
||||
|
||||
// This class holds session objects used by HttpNetworkTransaction objects.
|
||||
class HttpNetworkSession : public base::RefCounted<HttpNetworkSession> {
|
||||
public:
|
||||
HttpNetworkSession(ProxyService* proxy_service,
|
||||
ClientSocketFactory* client_socket_factory)
|
||||
: connection_pool_(new ClientSocketPool(
|
||||
max_sockets_per_group_, client_socket_factory)),
|
||||
explicit HttpNetworkSession(ProxyService* proxy_service)
|
||||
: connection_pool_(new ClientSocketPool(max_sockets_per_group_)),
|
||||
proxy_service_(proxy_service) {
|
||||
DCHECK(proxy_service);
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ int HttpNetworkTransaction::RestartIgnoringLastError(
|
||||
if (connection_.socket()->IsConnected()) {
|
||||
next_state_ = STATE_WRITE_HEADERS;
|
||||
} else {
|
||||
connection_.socket()->Disconnect();
|
||||
connection_.set_socket(NULL);
|
||||
connection_.Reset();
|
||||
next_state_ = STATE_INIT_CONNECTION;
|
||||
}
|
||||
@ -300,7 +300,7 @@ void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
|
||||
reused_socket_ = true;
|
||||
} else {
|
||||
next_state_ = STATE_INIT_CONNECTION;
|
||||
connection_.socket()->Disconnect();
|
||||
connection_.set_socket(NULL);
|
||||
connection_.Reset();
|
||||
}
|
||||
|
||||
@ -350,8 +350,10 @@ LoadState HttpNetworkTransaction::GetLoadState() const {
|
||||
switch (next_state_) {
|
||||
case STATE_RESOLVE_PROXY_COMPLETE:
|
||||
return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
|
||||
case STATE_INIT_CONNECTION_COMPLETE:
|
||||
return connection_.GetLoadState();
|
||||
case STATE_RESOLVE_HOST_COMPLETE:
|
||||
return LOAD_STATE_RESOLVING_HOST;
|
||||
case STATE_TCP_CONNECT_COMPLETE:
|
||||
return LOAD_STATE_CONNECTING;
|
||||
case STATE_WRITE_HEADERS_COMPLETE:
|
||||
case STATE_WRITE_BODY_COMPLETE:
|
||||
return LOAD_STATE_SENDING_REQUEST;
|
||||
@ -372,10 +374,10 @@ uint64 HttpNetworkTransaction::GetUploadProgress() const {
|
||||
}
|
||||
|
||||
HttpNetworkTransaction::~HttpNetworkTransaction() {
|
||||
// If we still have an open socket, then make sure to disconnect it so we
|
||||
// don't try to reuse it later on.
|
||||
// If we still have an open socket, then make sure to close it so we don't
|
||||
// try to reuse it later on.
|
||||
if (connection_.is_initialized())
|
||||
connection_.socket()->Disconnect();
|
||||
connection_.set_socket(NULL);
|
||||
|
||||
if (pac_request_)
|
||||
session_->proxy_service()->CancelPacRequest(pac_request_);
|
||||
@ -423,6 +425,24 @@ int HttpNetworkTransaction::DoLoop(int result) {
|
||||
rv = DoInitConnectionComplete(rv);
|
||||
TRACE_EVENT_END("http.init_conn", request_, request_->url.spec());
|
||||
break;
|
||||
case STATE_RESOLVE_HOST:
|
||||
DCHECK_EQ(OK, rv);
|
||||
TRACE_EVENT_BEGIN("http.resolve_host", request_, request_->url.spec());
|
||||
rv = DoResolveHost();
|
||||
break;
|
||||
case STATE_RESOLVE_HOST_COMPLETE:
|
||||
rv = DoResolveHostComplete(rv);
|
||||
TRACE_EVENT_END("http.resolve_host", request_, request_->url.spec());
|
||||
break;
|
||||
case STATE_TCP_CONNECT:
|
||||
DCHECK_EQ(OK, rv);
|
||||
TRACE_EVENT_BEGIN("http.connect", request_, request_->url.spec());
|
||||
rv = DoTCPConnect();
|
||||
break;
|
||||
case STATE_TCP_CONNECT_COMPLETE:
|
||||
rv = DoTCPConnectComplete(rv);
|
||||
TRACE_EVENT_END("http.connect", request_, request_->url.spec());
|
||||
break;
|
||||
case STATE_SSL_CONNECT:
|
||||
DCHECK_EQ(OK, rv);
|
||||
TRACE_EVENT_BEGIN("http.ssl_connect", request_, request_->url.spec());
|
||||
@ -532,41 +552,83 @@ int HttpNetworkTransaction::DoInitConnection() {
|
||||
|
||||
// Build the string used to uniquely identify connections of this type.
|
||||
std::string connection_group;
|
||||
std::string host;
|
||||
int port;
|
||||
if (using_proxy_ || using_tunnel_) {
|
||||
ProxyServer proxy_server = proxy_info_.proxy_server();
|
||||
connection_group = "proxy/" + proxy_server.ToURI() + "/";
|
||||
host = proxy_server.HostNoBrackets();
|
||||
port = proxy_server.port();
|
||||
} else {
|
||||
host = request_->url.HostNoBrackets();
|
||||
port = request_->url.EffectiveIntPort();
|
||||
}
|
||||
if (using_proxy_ || using_tunnel_)
|
||||
connection_group = "proxy/" + proxy_info_.proxy_server().ToURI() + "/";
|
||||
if (!using_proxy_)
|
||||
connection_group.append(request_->url.GetOrigin().spec());
|
||||
|
||||
DCHECK(!connection_group.empty());
|
||||
int rv = connection_.Init(connection_group, host, port, request_->priority,
|
||||
&io_callback_);
|
||||
return rv;
|
||||
return connection_.Init(connection_group, request_->priority, &io_callback_);
|
||||
}
|
||||
|
||||
int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
|
||||
if (result < 0)
|
||||
return ReconsiderProxyAfterError(result);
|
||||
return result;
|
||||
|
||||
DCHECK(connection_.is_initialized());
|
||||
|
||||
// Set the reused_socket_ flag to indicate that we are using a keep-alive
|
||||
// connection. This flag is used to handle errors that occur while we are
|
||||
// trying to reuse a keep-alive connection.
|
||||
reused_socket_ = connection_.is_reused();
|
||||
reused_socket_ = (connection_.socket() != NULL);
|
||||
if (reused_socket_) {
|
||||
next_state_ = STATE_WRITE_HEADERS;
|
||||
} else {
|
||||
// Now we have a TCP connected socket. Perform other connection setup as
|
||||
// needed.
|
||||
next_state_ = STATE_RESOLVE_HOST;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int HttpNetworkTransaction::DoResolveHost() {
|
||||
next_state_ = STATE_RESOLVE_HOST_COMPLETE;
|
||||
|
||||
std::string host;
|
||||
int port;
|
||||
|
||||
// Determine the host and port to connect to.
|
||||
if (using_proxy_ || using_tunnel_) {
|
||||
ProxyServer proxy_server = proxy_info_.proxy_server();
|
||||
host = proxy_server.HostNoBrackets();
|
||||
port = proxy_server.port();
|
||||
} else {
|
||||
// Direct connection
|
||||
host = request_->url.HostNoBrackets();
|
||||
port = request_->url.EffectiveIntPort();
|
||||
}
|
||||
|
||||
host_resolution_start_time_ = base::Time::Now();
|
||||
|
||||
DidStartDnsResolution(host, this);
|
||||
return resolver_.Resolve(host, port, &addresses_, &io_callback_);
|
||||
}
|
||||
|
||||
int HttpNetworkTransaction::DoResolveHostComplete(int result) {
|
||||
bool ok = (result == OK);
|
||||
DidFinishDnsResolutionWithStatus(ok, request_->referrer, this);
|
||||
if (ok) {
|
||||
next_state_ = STATE_TCP_CONNECT;
|
||||
} else {
|
||||
result = ReconsiderProxyAfterError(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int HttpNetworkTransaction::DoTCPConnect() {
|
||||
next_state_ = STATE_TCP_CONNECT_COMPLETE;
|
||||
|
||||
DCHECK(!connection_.socket());
|
||||
|
||||
connect_start_time_ = base::Time::Now();
|
||||
|
||||
ClientSocket* s = socket_factory_->CreateTCPClientSocket(addresses_);
|
||||
connection_.set_socket(s);
|
||||
return connection_.socket()->Connect(&io_callback_);
|
||||
}
|
||||
|
||||
int HttpNetworkTransaction::DoTCPConnectComplete(int result) {
|
||||
// If we are using a direct SSL connection, then go ahead and establish the
|
||||
// SSL connection, now. Otherwise, we need to first issue a CONNECT request.
|
||||
if (result == OK) {
|
||||
LogTCPConnectedMetrics();
|
||||
if (using_ssl_ && !using_tunnel_) {
|
||||
next_state_ = STATE_SSL_CONNECT;
|
||||
@ -575,8 +637,10 @@ int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
|
||||
if (using_tunnel_)
|
||||
establishing_tunnel_ = true;
|
||||
}
|
||||
} else {
|
||||
result = ReconsiderProxyAfterError(result);
|
||||
}
|
||||
return OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
int HttpNetworkTransaction::DoSSLConnect() {
|
||||
@ -877,7 +941,7 @@ int HttpNetworkTransaction::DoReadBodyComplete(int result) {
|
||||
if (done) {
|
||||
LogTransactionMetrics();
|
||||
if (!keep_alive)
|
||||
connection_.socket()->Disconnect();
|
||||
connection_.set_socket(NULL);
|
||||
connection_.Reset();
|
||||
// The next Read call will return 0 (EOF).
|
||||
}
|
||||
@ -949,6 +1013,15 @@ int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
|
||||
}
|
||||
|
||||
void HttpNetworkTransaction::LogTCPConnectedMetrics() const {
|
||||
DCHECK(connect_start_time_ != base::Time());
|
||||
base::TimeDelta connect_duration =
|
||||
base::Time::Now() - connect_start_time_;
|
||||
|
||||
UMA_HISTOGRAM_CLIPPED_TIMES(FieldTrial::MakeName(
|
||||
"Net.TCP_Connection_Latency", "DnsImpact").data(), connect_duration,
|
||||
base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
|
||||
100);
|
||||
|
||||
base::TimeDelta host_resolution_and_tcp_connection_latency =
|
||||
base::Time::Now() - host_resolution_start_time_;
|
||||
|
||||
@ -1221,7 +1294,7 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
|
||||
// This could be a TLS-intolerant server or an SSL 3.0 server that
|
||||
// chose a TLS-only cipher suite. Turn off TLS 1.0 and retry.
|
||||
ssl_config_.tls1_enabled = false;
|
||||
connection_.socket()->Disconnect();
|
||||
connection_.set_socket(NULL);
|
||||
connection_.Reset();
|
||||
next_state_ = STATE_INIT_CONNECTION;
|
||||
error = OK;
|
||||
@ -1284,7 +1357,7 @@ bool HttpNetworkTransaction::ShouldResendRequest() const {
|
||||
}
|
||||
|
||||
void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
|
||||
connection_.socket()->Disconnect();
|
||||
connection_.set_socket(NULL);
|
||||
connection_.Reset();
|
||||
// There are two reasons we need to clear request_headers_. 1) It contains
|
||||
// the real request headers, but we may need to resend the CONNECT request
|
||||
@ -1329,7 +1402,7 @@ int HttpNetworkTransaction::ReconsiderProxyAfterError(int error) {
|
||||
int rv = session_->proxy_service()->ReconsiderProxyAfterError(
|
||||
request_->url, &proxy_info_, &io_callback_, &pac_request_);
|
||||
if (rv == OK || rv == ERR_IO_PENDING) {
|
||||
connection_.socket()->Disconnect();
|
||||
connection_.set_socket(NULL);
|
||||
connection_.Reset();
|
||||
DCHECK(!request_headers_bytes_sent_);
|
||||
next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
|
||||
|
@ -12,10 +12,7 @@
|
||||
#include "base/time.h"
|
||||
#include "net/base/address_list.h"
|
||||
#include "net/base/client_socket_handle.h"
|
||||
#include "net/base/client_socket_pool.h"
|
||||
#include "net/base/host_resolver.h"
|
||||
#include "net/base/load_flags.h"
|
||||
#include "net/base/load_states.h"
|
||||
#include "net/base/ssl_config_service.h"
|
||||
#include "net/http/http_auth.h"
|
||||
#include "net/http/http_auth_handler.h"
|
||||
@ -90,26 +87,6 @@ class HttpNetworkTransaction : public HttpTransaction {
|
||||
scoped_ptr_malloc<char> headers_;
|
||||
};
|
||||
|
||||
enum State {
|
||||
STATE_RESOLVE_PROXY,
|
||||
STATE_RESOLVE_PROXY_COMPLETE,
|
||||
STATE_INIT_CONNECTION,
|
||||
STATE_INIT_CONNECTION_COMPLETE,
|
||||
STATE_SSL_CONNECT,
|
||||
STATE_SSL_CONNECT_COMPLETE,
|
||||
STATE_WRITE_HEADERS,
|
||||
STATE_WRITE_HEADERS_COMPLETE,
|
||||
STATE_WRITE_BODY,
|
||||
STATE_WRITE_BODY_COMPLETE,
|
||||
STATE_READ_HEADERS,
|
||||
STATE_READ_HEADERS_COMPLETE,
|
||||
STATE_READ_BODY,
|
||||
STATE_READ_BODY_COMPLETE,
|
||||
STATE_DRAIN_BODY_FOR_AUTH_RESTART,
|
||||
STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE,
|
||||
STATE_NONE
|
||||
};
|
||||
|
||||
void DoCallback(int result);
|
||||
void OnIOComplete(int result);
|
||||
|
||||
@ -124,6 +101,10 @@ class HttpNetworkTransaction : public HttpTransaction {
|
||||
int DoResolveProxyComplete(int result);
|
||||
int DoInitConnection();
|
||||
int DoInitConnectionComplete(int result);
|
||||
int DoResolveHost();
|
||||
int DoResolveHostComplete(int result);
|
||||
int DoTCPConnect();
|
||||
int DoTCPConnectComplete(int result);
|
||||
int DoSSLConnect();
|
||||
int DoSSLConnectComplete(int result);
|
||||
int DoWriteHeaders();
|
||||
@ -381,7 +362,29 @@ class HttpNetworkTransaction : public HttpTransaction {
|
||||
// The time the host resolution started (if it indeed got started).
|
||||
base::Time host_resolution_start_time_;
|
||||
|
||||
// The next state in the state machine.
|
||||
enum State {
|
||||
STATE_RESOLVE_PROXY,
|
||||
STATE_RESOLVE_PROXY_COMPLETE,
|
||||
STATE_INIT_CONNECTION,
|
||||
STATE_INIT_CONNECTION_COMPLETE,
|
||||
STATE_RESOLVE_HOST,
|
||||
STATE_RESOLVE_HOST_COMPLETE,
|
||||
STATE_TCP_CONNECT,
|
||||
STATE_TCP_CONNECT_COMPLETE,
|
||||
STATE_SSL_CONNECT,
|
||||
STATE_SSL_CONNECT_COMPLETE,
|
||||
STATE_WRITE_HEADERS,
|
||||
STATE_WRITE_HEADERS_COMPLETE,
|
||||
STATE_WRITE_BODY,
|
||||
STATE_WRITE_BODY_COMPLETE,
|
||||
STATE_READ_HEADERS,
|
||||
STATE_READ_HEADERS_COMPLETE,
|
||||
STATE_READ_BODY,
|
||||
STATE_READ_BODY_COMPLETE,
|
||||
STATE_DRAIN_BODY_FOR_AUTH_RESTART,
|
||||
STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE,
|
||||
STATE_NONE
|
||||
};
|
||||
State next_state_;
|
||||
};
|
||||
|
||||
|
@ -351,9 +351,8 @@ ProxyService* CreateFixedProxyService(const std::string& proxy) {
|
||||
}
|
||||
|
||||
|
||||
HttpNetworkSession* CreateSession(ProxyService* proxy_service,
|
||||
ClientSocketFactory* client_socket_factory) {
|
||||
return new HttpNetworkSession(proxy_service, client_socket_factory);
|
||||
HttpNetworkSession* CreateSession(ProxyService* proxy_service) {
|
||||
return new HttpNetworkSession(proxy_service);
|
||||
}
|
||||
|
||||
class HttpNetworkTransactionTest : public PlatformTest {
|
||||
@ -385,10 +384,8 @@ SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
|
||||
SimpleGetHelperResult out;
|
||||
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -469,10 +466,8 @@ std::string MockGetHostName() {
|
||||
|
||||
TEST_F(HttpNetworkTransactionTest, Basic) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
}
|
||||
|
||||
TEST_F(HttpNetworkTransactionTest, SimpleGET) {
|
||||
@ -582,10 +577,8 @@ TEST_F(HttpNetworkTransactionTest, StopsReading204) {
|
||||
// message body (since HEAD has none).
|
||||
TEST_F(HttpNetworkTransactionTest, Head) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "HEAD";
|
||||
@ -647,7 +640,7 @@ TEST_F(HttpNetworkTransactionTest, Head) {
|
||||
TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_refptr<HttpNetworkSession> session =
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory);
|
||||
CreateSession(proxy_service.get());
|
||||
|
||||
MockRead data_reads[] = {
|
||||
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
|
||||
@ -697,10 +690,8 @@ TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
|
||||
|
||||
TEST_F(HttpNetworkTransactionTest, Ignores100) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "POST";
|
||||
@ -745,10 +736,8 @@ TEST_F(HttpNetworkTransactionTest, Ignores100) {
|
||||
// HTTP/1.1.
|
||||
TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -792,7 +781,7 @@ void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
|
||||
const MockRead& read_failure) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_refptr<HttpNetworkSession> session =
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory);
|
||||
CreateSession(proxy_service.get());
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -858,10 +847,8 @@ TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
|
||||
|
||||
TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -915,10 +902,8 @@ TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
|
||||
// (basic auth is the easiest to mock, because it has no randomness).
|
||||
TEST_F(HttpNetworkTransactionTest, BasicAuth) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -1007,10 +992,8 @@ TEST_F(HttpNetworkTransactionTest, BasicAuth) {
|
||||
// connection.
|
||||
TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -1086,10 +1069,8 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
|
||||
// connection and with no response body to drain.
|
||||
TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -1168,10 +1149,8 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
|
||||
// connection and with a large response body to drain.
|
||||
TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -1257,7 +1236,7 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
|
||||
CreateFixedProxyService("myproxy:70"));
|
||||
|
||||
scoped_refptr<HttpNetworkSession> session(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory));
|
||||
CreateSession(proxy_service.get()));
|
||||
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
session.get(), &mock_socket_factory));
|
||||
@ -1358,7 +1337,7 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
|
||||
CreateFixedProxyService("myproxy:70"));
|
||||
|
||||
scoped_refptr<HttpNetworkSession> session(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory));
|
||||
CreateSession(proxy_service.get()));
|
||||
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
session.get(), &mock_socket_factory));
|
||||
@ -1416,7 +1395,7 @@ static void ConnectStatusHelperWithExpectedStatus(
|
||||
CreateFixedProxyService("myproxy:70"));
|
||||
|
||||
scoped_refptr<HttpNetworkSession> session(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory));
|
||||
CreateSession(proxy_service.get()));
|
||||
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
session.get(), &mock_socket_factory));
|
||||
@ -1632,7 +1611,7 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
|
||||
|
||||
// Configure against proxy server "myproxy:70".
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
CreateSession(proxy_service.get()),
|
||||
&mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
@ -1770,10 +1749,8 @@ TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
|
||||
MockGetHostName);
|
||||
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -1899,10 +1876,8 @@ TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
|
||||
MockGetHostName);
|
||||
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -2108,10 +2083,8 @@ TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
|
||||
// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
|
||||
TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -2154,7 +2127,7 @@ TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
|
||||
CreateFixedProxyService("myproxy:70"));
|
||||
|
||||
scoped_refptr<HttpNetworkSession> session(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory));
|
||||
CreateSession(proxy_service.get()));
|
||||
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
session.get(), &mock_socket_factory));
|
||||
@ -2213,7 +2186,7 @@ TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
|
||||
TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_refptr<HttpNetworkSession> session(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory));
|
||||
CreateSession(proxy_service.get()));
|
||||
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
session.get(), &mock_socket_factory));
|
||||
@ -2273,7 +2246,7 @@ TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
|
||||
TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_refptr<HttpNetworkSession> session(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory));
|
||||
CreateSession(proxy_service.get()));
|
||||
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
session.get(), &mock_socket_factory));
|
||||
@ -2348,7 +2321,7 @@ TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
|
||||
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_refptr<HttpNetworkSession> session =
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory);
|
||||
CreateSession(proxy_service.get());
|
||||
|
||||
// The first socket is used for transaction 1 and the first attempt of
|
||||
// transaction 2.
|
||||
@ -2425,10 +2398,8 @@ TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
|
||||
// it fails the identity from the URL is used to answer the challenge.
|
||||
TEST_F(HttpNetworkTransactionTest, AuthIdentityInUrl) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -2506,7 +2477,7 @@ TEST_F(HttpNetworkTransactionTest, AuthIdentityInUrl) {
|
||||
TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_refptr<HttpNetworkSession> session =
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory);
|
||||
CreateSession(proxy_service.get());
|
||||
|
||||
// Transaction 1: authenticate (foo, bar) on MyRealm1
|
||||
{
|
||||
@ -2924,10 +2895,8 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
|
||||
TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
|
||||
// Create a transaction (the dependencies aren't important).
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpNetworkTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
// Setup some state (which we expect ResetStateForRestart() will clear).
|
||||
trans->header_buf_->Realloc(10);
|
||||
@ -2984,10 +2953,8 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
|
||||
// Test HTTPS connections to a site with a bad certificate
|
||||
TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -3096,10 +3063,8 @@ TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
|
||||
mock_sockets_index = 0;
|
||||
mock_ssl_sockets_index = 0;
|
||||
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
int rv = trans->Start(&request, &callback);
|
||||
EXPECT_EQ(ERR_IO_PENDING, rv);
|
||||
@ -3122,10 +3087,8 @@ TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
|
||||
|
||||
TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -3164,10 +3127,8 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
|
||||
|
||||
TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -3207,10 +3168,8 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
|
||||
|
||||
TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "POST";
|
||||
@ -3248,10 +3207,8 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
|
||||
|
||||
TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "PUT";
|
||||
@ -3289,10 +3246,8 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
|
||||
|
||||
TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "HEAD";
|
||||
@ -3330,10 +3285,8 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
|
||||
|
||||
TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -3374,10 +3327,8 @@ TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
|
||||
TEST_F(HttpNetworkTransactionTest,
|
||||
BuildRequest_CacheControlValidateCache) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
@ -3416,10 +3367,8 @@ TEST_F(HttpNetworkTransactionTest,
|
||||
|
||||
TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
|
||||
scoped_ptr<ProxyService> proxy_service(CreateNullProxyService());
|
||||
scoped_ptr<HttpTransaction> trans(
|
||||
new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get(), &mock_socket_factory),
|
||||
&mock_socket_factory));
|
||||
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
|
||||
CreateSession(proxy_service.get()), &mock_socket_factory));
|
||||
|
||||
HttpRequestInfo request;
|
||||
request.method = "GET";
|
||||
|
Reference in New Issue
Block a user