summaryrefslogtreecommitdiffstats
path: root/chromium/net/http
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/net/http
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/net/http')
-rw-r--r--chromium/net/http/disk_cache_based_quic_server_info.cc295
-rw-r--r--chromium/net/http/disk_cache_based_quic_server_info.h106
-rw-r--r--chromium/net/http/disk_cache_based_quic_server_info_unittest.cc282
-rw-r--r--chromium/net/http/failing_http_transaction_factory.cc191
-rw-r--r--chromium/net/http/failing_http_transaction_factory.h42
-rw-r--r--chromium/net/http/http_auth.cc53
-rw-r--r--chromium/net/http/http_auth.h42
-rw-r--r--chromium/net/http/http_auth_cache.cc41
-rw-r--r--chromium/net/http/http_auth_cache.h6
-rw-r--r--chromium/net/http/http_auth_cache_unittest.cc6
-rw-r--r--chromium/net/http/http_auth_challenge_tokenizer.cc61
-rw-r--r--chromium/net/http/http_auth_challenge_tokenizer.h61
-rw-r--r--chromium/net/http/http_auth_challenge_tokenizer_unittest.cc177
-rw-r--r--chromium/net/http/http_auth_controller_unittest.cc5
-rw-r--r--chromium/net/http/http_auth_filter_win.h10
-rw-r--r--chromium/net/http/http_auth_gssapi_posix.cc3
-rw-r--r--chromium/net/http/http_auth_gssapi_posix.h4
-rw-r--r--chromium/net/http/http_auth_gssapi_posix_unittest.cc33
-rw-r--r--chromium/net/http/http_auth_handler.cc3
-rw-r--r--chromium/net/http/http_auth_handler.h7
-rw-r--r--chromium/net/http/http_auth_handler_basic.cc22
-rw-r--r--chromium/net/http/http_auth_handler_basic.h8
-rw-r--r--chromium/net/http/http_auth_handler_basic_unittest.cc9
-rw-r--r--chromium/net/http/http_auth_handler_digest.cc21
-rw-r--r--chromium/net/http/http_auth_handler_digest.h8
-rw-r--r--chromium/net/http/http_auth_handler_digest_unittest.cc24
-rw-r--r--chromium/net/http/http_auth_handler_factory.cc7
-rw-r--r--chromium/net/http/http_auth_handler_factory.h5
-rw-r--r--chromium/net/http/http_auth_handler_factory_unittest.cc2
-rw-r--r--chromium/net/http/http_auth_handler_mock.cc7
-rw-r--r--chromium/net/http/http_auth_handler_mock.h6
-rw-r--r--chromium/net/http/http_auth_handler_negotiate.cc6
-rw-r--r--chromium/net/http/http_auth_handler_negotiate.h6
-rw-r--r--chromium/net/http/http_auth_handler_ntlm.cc7
-rw-r--r--chromium/net/http/http_auth_handler_ntlm.h8
-rw-r--r--chromium/net/http/http_auth_handler_ntlm_portable.cc24
-rw-r--r--chromium/net/http/http_auth_handler_ntlm_win.cc2
-rw-r--r--chromium/net/http/http_auth_handler_unittest.cc6
-rw-r--r--chromium/net/http/http_auth_sspi_win.cc3
-rw-r--r--chromium/net/http/http_auth_sspi_win.h4
-rw-r--r--chromium/net/http/http_auth_sspi_win_unittest.cc33
-rw-r--r--chromium/net/http/http_auth_unittest.cc170
-rw-r--r--chromium/net/http/http_basic_stream.cc8
-rw-r--r--chromium/net/http/http_basic_stream.h2
-rw-r--r--chromium/net/http/http_byte_range.h4
-rw-r--r--chromium/net/http/http_cache.cc86
-rw-r--r--chromium/net/http/http_cache.h43
-rw-r--r--chromium/net/http/http_cache_transaction.cc182
-rw-r--r--chromium/net/http/http_cache_transaction.h27
-rw-r--r--chromium/net/http/http_cache_unittest.cc682
-rw-r--r--chromium/net/http/http_chunked_decoder.h3
-rw-r--r--chromium/net/http/http_content_disposition.cc44
-rw-r--r--chromium/net/http/http_content_disposition_unittest.cc4
-rw-r--r--chromium/net/http/http_log_util.cc81
-rw-r--r--chromium/net/http/http_log_util.h24
-rw-r--r--chromium/net/http/http_log_util_unittest.cc76
-rw-r--r--chromium/net/http/http_network_layer.cc3
-rw-r--r--chromium/net/http/http_network_layer.h3
-rw-r--r--chromium/net/http/http_network_layer_unittest.cc427
-rw-r--r--chromium/net/http/http_network_session.cc86
-rw-r--r--chromium/net/http/http_network_session.h54
-rw-r--r--chromium/net/http/http_network_transaction.cc264
-rw-r--r--chromium/net/http/http_network_transaction.h29
-rw-r--r--chromium/net/http/http_network_transaction_unittest.cc1236
-rw-r--r--chromium/net/http/http_pipelined_connection.h93
-rw-r--r--chromium/net/http/http_pipelined_connection_impl.cc845
-rw-r--r--chromium/net/http/http_pipelined_connection_impl.h330
-rw-r--r--chromium/net/http/http_pipelined_connection_impl_unittest.cc1597
-rw-r--r--chromium/net/http/http_pipelined_host.cc17
-rw-r--r--chromium/net/http/http_pipelined_host.h102
-rw-r--r--chromium/net/http/http_pipelined_host_capability.h23
-rw-r--r--chromium/net/http/http_pipelined_host_forced.cc103
-rw-r--r--chromium/net/http/http_pipelined_host_forced.h83
-rw-r--r--chromium/net/http/http_pipelined_host_forced_unittest.cc106
-rw-r--r--chromium/net/http/http_pipelined_host_impl.cc210
-rw-r--r--chromium/net/http/http_pipelined_host_impl.h117
-rw-r--r--chromium/net/http/http_pipelined_host_impl_unittest.cc308
-rw-r--r--chromium/net/http/http_pipelined_host_pool.cc145
-rw-r--r--chromium/net/http/http_pipelined_host_pool.h102
-rw-r--r--chromium/net/http/http_pipelined_host_pool_unittest.cc262
-rw-r--r--chromium/net/http/http_pipelined_host_test_util.cc33
-rw-r--r--chromium/net/http/http_pipelined_host_test_util.h70
-rw-r--r--chromium/net/http/http_pipelined_network_transaction_unittest.cc1035
-rw-r--r--chromium/net/http/http_pipelined_stream.cc153
-rw-r--r--chromium/net/http/http_pipelined_stream.h115
-rw-r--r--chromium/net/http/http_proxy_client_socket.cc6
-rw-r--r--chromium/net/http/http_proxy_client_socket.h4
-rw-r--r--chromium/net/http/http_proxy_client_socket_pool.cc21
-rw-r--r--chromium/net/http/http_proxy_client_socket_pool_unittest.cc15
-rw-r--r--chromium/net/http/http_request_headers.cc21
-rw-r--r--chromium/net/http/http_request_info.cc2
-rw-r--r--chromium/net/http/http_response_body_drainer.cc25
-rw-r--r--chromium/net/http/http_response_body_drainer.h4
-rw-r--r--chromium/net/http/http_response_body_drainer_unittest.cc19
-rw-r--r--chromium/net/http/http_response_headers.cc118
-rw-r--r--chromium/net/http/http_response_headers.h42
-rw-r--r--chromium/net/http/http_response_headers_unittest.cc211
-rw-r--r--chromium/net/http/http_response_info.cc20
-rw-r--r--chromium/net/http/http_response_info.h11
-rw-r--r--chromium/net/http/http_security_headers.cc2
-rw-r--r--chromium/net/http/http_security_headers_unittest.cc261
-rw-r--r--chromium/net/http/http_server_properties.cc35
-rw-r--r--chromium/net/http/http_server_properties.h101
-rw-r--r--chromium/net/http/http_server_properties_impl.cc330
-rw-r--r--chromium/net/http/http_server_properties_impl.h104
-rw-r--r--chromium/net/http/http_server_properties_impl_unittest.cc231
-rw-r--r--chromium/net/http/http_stream.h10
-rw-r--r--chromium/net/http/http_stream_base.h27
-rw-r--r--chromium/net/http/http_stream_factory.cc360
-rw-r--r--chromium/net/http/http_stream_factory.h84
-rw-r--r--chromium/net/http/http_stream_factory_impl.cc76
-rw-r--r--chromium/net/http/http_stream_factory_impl.h24
-rw-r--r--chromium/net/http/http_stream_factory_impl_job.cc402
-rw-r--r--chromium/net/http/http_stream_factory_impl_job.h31
-rw-r--r--chromium/net/http/http_stream_factory_impl_request.cc118
-rw-r--r--chromium/net/http/http_stream_factory_impl_request.h14
-rw-r--r--chromium/net/http/http_stream_factory_impl_request_unittest.cc3
-rw-r--r--chromium/net/http/http_stream_factory_impl_unittest.cc112
-rw-r--r--chromium/net/http/http_stream_parser.cc436
-rw-r--r--chromium/net/http/http_stream_parser.h44
-rw-r--r--chromium/net/http/http_stream_parser_unittest.cc57
-rw-r--r--chromium/net/http/http_transaction.h19
-rw-r--r--chromium/net/http/http_transaction_delegate.h26
-rw-r--r--chromium/net/http/http_transaction_factory.h10
-rw-r--r--chromium/net/http/http_transaction_test_util.cc (renamed from chromium/net/http/http_transaction_unittest.cc)160
-rw-r--r--chromium/net/http/http_transaction_test_util.h (renamed from chromium/net/http/http_transaction_unittest.h)26
-rw-r--r--chromium/net/http/http_util.cc105
-rw-r--r--chromium/net/http/http_util.h4
-rw-r--r--chromium/net/http/mock_http_cache.cc4
-rw-r--r--chromium/net/http/mock_http_cache.h5
-rw-r--r--chromium/net/http/partial_data.cc36
-rw-r--r--chromium/net/http/proxy_connect_redirect_http_stream.cc6
-rw-r--r--chromium/net/http/proxy_connect_redirect_http_stream.h1
-rw-r--r--chromium/net/http/transport_security_persister.cc104
-rw-r--r--chromium/net/http/transport_security_persister_unittest.cc63
-rw-r--r--chromium/net/http/transport_security_state.cc261
-rw-r--r--chromium/net/http/transport_security_state.h165
-rw-r--r--chromium/net/http/transport_security_state_static.h115
-rw-r--r--chromium/net/http/transport_security_state_static.json118
-rw-r--r--chromium/net/http/transport_security_state_unittest.cc624
-rw-r--r--chromium/net/http/url_security_manager_win.cc2
141 files changed, 6439 insertions, 9829 deletions
diff --git a/chromium/net/http/disk_cache_based_quic_server_info.cc b/chromium/net/http/disk_cache_based_quic_server_info.cc
new file mode 100644
index 00000000000..4cf036de3ba
--- /dev/null
+++ b/chromium/net/http/disk_cache_based_quic_server_info.cc
@@ -0,0 +1,295 @@
+// Copyright 2014 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.
+
+#include "net/http/disk_cache_based_quic_server_info.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_cache.h"
+#include "net/http/http_network_session.h"
+#include "net/quic/quic_server_id.h"
+
+namespace net {
+
+// Some APIs inside disk_cache take a handle that the caller must keep alive
+// until the API has finished its asynchronous execution.
+//
+// Unfortunately, DiskCacheBasedQuicServerInfo may be deleted before the
+// operation completes causing a use-after-free.
+//
+// This data shim struct is meant to provide a location for the disk_cache
+// APIs to write into even if the originating DiskCacheBasedQuicServerInfo
+// object has been deleted. The lifetime for instances of this struct
+// should be bound to the CompletionCallback that is passed to the disk_cache
+// API. We do this by binding an instance of this struct to an unused
+// parameter for OnIOComplete() using base::Owned().
+//
+// This is a hack. A better fix is to make it so that the disk_cache APIs
+// take a Callback to a mutator for setting the output value rather than
+// writing into a raw handle. Then the caller can just pass in a Callback
+// bound to WeakPtr for itself. This callback would correctly "no-op" itself
+// when the DiskCacheBasedQuicServerInfo object is deleted.
+//
+// TODO(ajwong): Change disk_cache's API to return results via Callback.
+struct DiskCacheBasedQuicServerInfo::CacheOperationDataShim {
+ CacheOperationDataShim() : backend(NULL), entry(NULL) {}
+
+ disk_cache::Backend* backend;
+ disk_cache::Entry* entry;
+};
+
+DiskCacheBasedQuicServerInfo::DiskCacheBasedQuicServerInfo(
+ const QuicServerId& server_id,
+ HttpCache* http_cache)
+ : QuicServerInfo(server_id),
+ weak_factory_(this),
+ data_shim_(new CacheOperationDataShim()),
+ io_callback_(
+ base::Bind(&DiskCacheBasedQuicServerInfo::OnIOComplete,
+ weak_factory_.GetWeakPtr(),
+ base::Owned(data_shim_))), // Ownership assigned.
+ state_(GET_BACKEND),
+ ready_(false),
+ found_entry_(false),
+ server_id_(server_id),
+ http_cache_(http_cache),
+ backend_(NULL),
+ entry_(NULL) {
+}
+
+void DiskCacheBasedQuicServerInfo::Start() {
+ DCHECK(CalledOnValidThread());
+ DCHECK_EQ(GET_BACKEND, state_);
+ DoLoop(OK);
+}
+
+int DiskCacheBasedQuicServerInfo::WaitForDataReady(
+ const CompletionCallback& callback) {
+ DCHECK(CalledOnValidThread());
+ DCHECK_NE(GET_BACKEND, state_);
+
+ if (ready_)
+ return OK;
+
+ if (!callback.is_null()) {
+ // Prevent a new callback for WaitForDataReady overwriting an existing
+ // pending callback (|user_callback_|).
+ if (!user_callback_.is_null())
+ return ERR_INVALID_ARGUMENT;
+ user_callback_ = callback;
+ }
+
+ return ERR_IO_PENDING;
+}
+
+bool DiskCacheBasedQuicServerInfo::IsDataReady() {
+ return ready_;
+}
+
+bool DiskCacheBasedQuicServerInfo::IsReadyToPersist() {
+ // The data can be persisted if it has been loaded from the disk cache
+ // and there are no pending writes.
+ return ready_ && new_data_.empty();
+}
+
+void DiskCacheBasedQuicServerInfo::Persist() {
+ DCHECK(CalledOnValidThread());
+ DCHECK_NE(GET_BACKEND, state_);
+
+ DCHECK(new_data_.empty());
+ CHECK(ready_);
+ DCHECK(user_callback_.is_null());
+ new_data_ = Serialize();
+
+ if (!backend_)
+ return;
+
+ state_ = CREATE_OR_OPEN;
+ DoLoop(OK);
+}
+
+DiskCacheBasedQuicServerInfo::~DiskCacheBasedQuicServerInfo() {
+ DCHECK(user_callback_.is_null());
+ if (entry_)
+ entry_->Close();
+}
+
+std::string DiskCacheBasedQuicServerInfo::key() const {
+ return "quicserverinfo:" + server_id_.ToString();
+}
+
+void DiskCacheBasedQuicServerInfo::OnIOComplete(CacheOperationDataShim* unused,
+ int rv) {
+ DCHECK_NE(NONE, state_);
+ rv = DoLoop(rv);
+ if (rv != ERR_IO_PENDING && !user_callback_.is_null()) {
+ CompletionCallback callback = user_callback_;
+ user_callback_.Reset();
+ callback.Run(rv);
+ }
+}
+
+int DiskCacheBasedQuicServerInfo::DoLoop(int rv) {
+ do {
+ switch (state_) {
+ case GET_BACKEND:
+ rv = DoGetBackend();
+ break;
+ case GET_BACKEND_COMPLETE:
+ rv = DoGetBackendComplete(rv);
+ break;
+ case OPEN:
+ rv = DoOpen();
+ break;
+ case OPEN_COMPLETE:
+ rv = DoOpenComplete(rv);
+ break;
+ case READ:
+ rv = DoRead();
+ break;
+ case READ_COMPLETE:
+ rv = DoReadComplete(rv);
+ break;
+ case WAIT_FOR_DATA_READY_DONE:
+ rv = DoWaitForDataReadyDone();
+ break;
+ case CREATE_OR_OPEN:
+ rv = DoCreateOrOpen();
+ break;
+ case CREATE_OR_OPEN_COMPLETE:
+ rv = DoCreateOrOpenComplete(rv);
+ break;
+ case WRITE:
+ rv = DoWrite();
+ break;
+ case WRITE_COMPLETE:
+ rv = DoWriteComplete(rv);
+ break;
+ case SET_DONE:
+ rv = DoSetDone();
+ break;
+ default:
+ rv = OK;
+ NOTREACHED();
+ }
+ } while (rv != ERR_IO_PENDING && state_ != NONE);
+
+ return rv;
+}
+
+int DiskCacheBasedQuicServerInfo::DoGetBackendComplete(int rv) {
+ if (rv == OK) {
+ backend_ = data_shim_->backend;
+ state_ = OPEN;
+ } else {
+ state_ = WAIT_FOR_DATA_READY_DONE;
+ }
+ return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoOpenComplete(int rv) {
+ if (rv == OK) {
+ entry_ = data_shim_->entry;
+ state_ = READ;
+ found_entry_ = true;
+ } else {
+ state_ = WAIT_FOR_DATA_READY_DONE;
+ }
+
+ return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoReadComplete(int rv) {
+ if (rv > 0)
+ data_.assign(read_buffer_->data(), rv);
+
+ state_ = WAIT_FOR_DATA_READY_DONE;
+ return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoWriteComplete(int rv) {
+ state_ = SET_DONE;
+ return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoCreateOrOpenComplete(int rv) {
+ if (rv != OK) {
+ state_ = SET_DONE;
+ } else {
+ entry_ = data_shim_->entry;
+ state_ = WRITE;
+ }
+ return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoGetBackend() {
+ state_ = GET_BACKEND_COMPLETE;
+ return http_cache_->GetBackend(&data_shim_->backend, io_callback_);
+}
+
+int DiskCacheBasedQuicServerInfo::DoOpen() {
+ state_ = OPEN_COMPLETE;
+ return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_);
+}
+
+int DiskCacheBasedQuicServerInfo::DoRead() {
+ const int32 size = entry_->GetDataSize(0 /* index */);
+ if (!size) {
+ state_ = WAIT_FOR_DATA_READY_DONE;
+ return OK;
+ }
+
+ read_buffer_ = new IOBuffer(size);
+ state_ = READ_COMPLETE;
+ return entry_->ReadData(
+ 0 /* index */, 0 /* offset */, read_buffer_, size, io_callback_);
+}
+
+int DiskCacheBasedQuicServerInfo::DoWrite() {
+ write_buffer_ = new IOBuffer(new_data_.size());
+ memcpy(write_buffer_->data(), new_data_.data(), new_data_.size());
+ state_ = WRITE_COMPLETE;
+
+ return entry_->WriteData(
+ 0 /* index */, 0 /* offset */, write_buffer_, new_data_.size(),
+ io_callback_, true /* truncate */);
+}
+
+int DiskCacheBasedQuicServerInfo::DoCreateOrOpen() {
+ DCHECK(entry_ == NULL);
+ state_ = CREATE_OR_OPEN_COMPLETE;
+ if (found_entry_) {
+ return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_);
+ }
+
+ return backend_->CreateEntry(key(), &data_shim_->entry, io_callback_);
+}
+
+int DiskCacheBasedQuicServerInfo::DoWaitForDataReadyDone() {
+ DCHECK(!ready_);
+ state_ = NONE;
+ ready_ = true;
+ // We close the entry because, if we shutdown before ::Persist is called,
+ // then we might leak a cache reference, which causes a DCHECK on shutdown.
+ if (entry_)
+ entry_->Close();
+ entry_ = NULL;
+ Parse(data_);
+ return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoSetDone() {
+ if (entry_)
+ entry_->Close();
+ entry_ = NULL;
+ new_data_.clear();
+ state_ = NONE;
+ return OK;
+}
+
+} // namespace net
diff --git a/chromium/net/http/disk_cache_based_quic_server_info.h b/chromium/net/http/disk_cache_based_quic_server_info.h
new file mode 100644
index 00000000000..2a18ef5abc8
--- /dev/null
+++ b/chromium/net/http/disk_cache_based_quic_server_info.h
@@ -0,0 +1,106 @@
+// Copyright 2014 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_HTTP_DISK_CACHE_BASED_QUIC_SERVER_INFO_H_
+#define NET_HTTP_DISK_CACHE_BASED_QUIC_SERVER_INFO_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/non_thread_safe.h"
+#include "net/base/completion_callback.h"
+#include "net/disk_cache/disk_cache.h"
+#include "net/quic/crypto/quic_server_info.h"
+
+namespace net {
+
+class HttpCache;
+class IOBuffer;
+class QuicServerId;
+
+// DiskCacheBasedQuicServerInfo fetches information about a QUIC server from
+// our standard disk cache. Since the information is defined to be
+// non-sensitive, it's ok for us to keep it on disk.
+class NET_EXPORT_PRIVATE DiskCacheBasedQuicServerInfo
+ : public QuicServerInfo,
+ public NON_EXPORTED_BASE(base::NonThreadSafe) {
+ public:
+ DiskCacheBasedQuicServerInfo(const QuicServerId& server_id,
+ HttpCache* http_cache);
+
+ // QuicServerInfo implementation.
+ virtual void Start() OVERRIDE;
+ virtual int WaitForDataReady(const CompletionCallback& callback) OVERRIDE;
+ virtual bool IsDataReady() OVERRIDE;
+ virtual bool IsReadyToPersist() OVERRIDE;
+ virtual void Persist() OVERRIDE;
+
+ private:
+ struct CacheOperationDataShim;
+ enum State {
+ GET_BACKEND,
+ GET_BACKEND_COMPLETE,
+ OPEN,
+ OPEN_COMPLETE,
+ READ,
+ READ_COMPLETE,
+ WAIT_FOR_DATA_READY_DONE,
+ CREATE_OR_OPEN,
+ CREATE_OR_OPEN_COMPLETE,
+ WRITE,
+ WRITE_COMPLETE,
+ SET_DONE,
+ NONE,
+ };
+
+ virtual ~DiskCacheBasedQuicServerInfo();
+
+ std::string key() const;
+
+ // The |unused| parameter is a small hack so that we can have the
+ // CacheOperationDataShim object owned by the Callback that is created for
+ // this method. See comment above CacheOperationDataShim for details.
+ void OnIOComplete(CacheOperationDataShim* unused, int rv);
+
+ int DoLoop(int rv);
+
+ int DoGetBackendComplete(int rv);
+ int DoOpenComplete(int rv);
+ int DoReadComplete(int rv);
+ int DoWriteComplete(int rv);
+ int DoCreateOrOpenComplete(int rv);
+
+ int DoGetBackend();
+ int DoOpen();
+ int DoRead();
+ int DoWrite();
+ int DoCreateOrOpen();
+
+ // DoWaitForDataReadyDone is the terminal state of the read operation.
+ int DoWaitForDataReadyDone();
+
+ // DoSetDone is the terminal state of the write operation.
+ int DoSetDone();
+
+ base::WeakPtrFactory<DiskCacheBasedQuicServerInfo> weak_factory_;
+ CacheOperationDataShim* data_shim_; // Owned by |io_callback_|.
+ CompletionCallback io_callback_;
+ State state_;
+ bool ready_;
+ bool found_entry_; // Controls the behavior of DoCreateOrOpen.
+ std::string new_data_;
+ const QuicServerId server_id_;
+ HttpCache* const http_cache_;
+ disk_cache::Backend* backend_;
+ disk_cache::Entry* entry_;
+ CompletionCallback user_callback_;
+ scoped_refptr<IOBuffer> read_buffer_;
+ scoped_refptr<IOBuffer> write_buffer_;
+ std::string data_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP_DISK_CACHE_BASED_QUIC_SERVER_INFO_H_
diff --git a/chromium/net/http/disk_cache_based_quic_server_info_unittest.cc b/chromium/net/http/disk_cache_based_quic_server_info_unittest.cc
new file mode 100644
index 00000000000..52b832dbbda
--- /dev/null
+++ b/chromium/net/http/disk_cache_based_quic_server_info_unittest.cc
@@ -0,0 +1,282 @@
+// Copyright 2014 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.
+
+#include "net/http/disk_cache_based_quic_server_info.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/compiler_specific.h"
+#include "base/message_loop/message_loop.h"
+#include "net/base/net_errors.h"
+#include "net/http/mock_http_cache.h"
+#include "net/quic/crypto/quic_server_info.h"
+#include "net/quic/quic_server_id.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace {
+
+// This is an empty transaction, needed to register the URL and the test mode.
+const MockTransaction kHostInfoTransaction1 = {
+ "quicserverinfo:https://www.google.com:443",
+ "",
+ base::Time(),
+ "",
+ LOAD_NORMAL,
+ "",
+ "",
+ base::Time(),
+ "",
+ TEST_MODE_NORMAL,
+ NULL,
+ 0
+};
+
+const MockTransaction kHostInfoTransaction2 = {
+ "quicserverinfo:http://www.google.com:80",
+ "",
+ base::Time(),
+ "",
+ LOAD_NORMAL,
+ "",
+ "",
+ base::Time(),
+ "",
+ TEST_MODE_NORMAL,
+ NULL,
+ 0
+};
+
+} // namespace
+
+// Tests that we can delete a DiskCacheBasedQuicServerInfo object in a
+// completion callback for DiskCacheBasedQuicServerInfo::WaitForDataReady.
+TEST(DiskCacheBasedQuicServerInfo, DeleteInCallback) {
+ // Use the blocking mock backend factory to force asynchronous completion
+ // of quic_server_info->WaitForDataReady(), so that the callback will run.
+ MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
+ MockHttpCache cache(factory);
+ QuicServerId server_id("www.verisign.com", 443, true, PRIVACY_MODE_DISABLED);
+ scoped_ptr<QuicServerInfo> quic_server_info(
+ new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+ quic_server_info->Start();
+ TestCompletionCallback callback;
+ int rv = quic_server_info->WaitForDataReady(callback.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ // Now complete the backend creation and let the callback run.
+ factory->FinishCreation();
+ EXPECT_EQ(OK, callback.GetResult(rv));
+}
+
+// Tests the basic logic of storing, retrieving and updating data.
+TEST(DiskCacheBasedQuicServerInfo, Update) {
+ MockHttpCache cache;
+ AddMockTransaction(&kHostInfoTransaction1);
+ TestCompletionCallback callback;
+
+ QuicServerId server_id("www.google.com", 443, true, PRIVACY_MODE_DISABLED);
+ scoped_ptr<QuicServerInfo> quic_server_info(
+ new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+ quic_server_info->Start();
+ int rv = quic_server_info->WaitForDataReady(callback.callback());
+ EXPECT_EQ(OK, callback.GetResult(rv));
+
+ QuicServerInfo::State* state = quic_server_info->mutable_state();
+ EXPECT_TRUE(state->certs.empty());
+ const string server_config_a = "server_config_a";
+ const string source_address_token_a = "source_address_token_a";
+ const string server_config_sig_a = "server_config_sig_a";
+ const string cert_a = "cert_a";
+ const string cert_b = "cert_b";
+
+ state->server_config = server_config_a;
+ state->source_address_token = source_address_token_a;
+ state->server_config_sig = server_config_sig_a;
+ state->certs.push_back(cert_a);
+ quic_server_info->Persist();
+
+ // Wait until Persist() does the work.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Open the stored QuicServerInfo.
+ quic_server_info.reset(
+ new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+ quic_server_info->Start();
+ rv = quic_server_info->WaitForDataReady(callback.callback());
+ EXPECT_EQ(OK, callback.GetResult(rv));
+
+ // And now update the data.
+ state = quic_server_info->mutable_state();
+ state->certs.push_back(cert_b);
+
+ // Fail instead of DCHECKing double creates.
+ cache.disk_cache()->set_double_create_check(false);
+ quic_server_info->Persist();
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Verify that the state was updated.
+ quic_server_info.reset(
+ new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+ quic_server_info->Start();
+ rv = quic_server_info->WaitForDataReady(callback.callback());
+ EXPECT_EQ(OK, callback.GetResult(rv));
+ EXPECT_TRUE(quic_server_info->IsDataReady());
+
+ const QuicServerInfo::State& state1 = quic_server_info->state();
+ EXPECT_EQ(server_config_a, state1.server_config);
+ EXPECT_EQ(source_address_token_a, state1.source_address_token);
+ EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
+ EXPECT_EQ(2U, state1.certs.size());
+ EXPECT_EQ(cert_a, state1.certs[0]);
+ EXPECT_EQ(cert_b, state1.certs[1]);
+
+ RemoveMockTransaction(&kHostInfoTransaction1);
+}
+
+// Test that demonstrates different info is returned when the ports differ.
+TEST(DiskCacheBasedQuicServerInfo, UpdateDifferentPorts) {
+ MockHttpCache cache;
+ AddMockTransaction(&kHostInfoTransaction1);
+ AddMockTransaction(&kHostInfoTransaction2);
+ TestCompletionCallback callback;
+
+ // Persist data for port 443.
+ QuicServerId server_id1("www.google.com", 443, true, PRIVACY_MODE_DISABLED);
+ scoped_ptr<QuicServerInfo> quic_server_info1(
+ new DiskCacheBasedQuicServerInfo(server_id1, cache.http_cache()));
+ quic_server_info1->Start();
+ int rv = quic_server_info1->WaitForDataReady(callback.callback());
+ EXPECT_EQ(OK, callback.GetResult(rv));
+
+ QuicServerInfo::State* state1 = quic_server_info1->mutable_state();
+ EXPECT_TRUE(state1->certs.empty());
+ const string server_config_a = "server_config_a";
+ const string source_address_token_a = "source_address_token_a";
+ const string server_config_sig_a = "server_config_sig_a";
+ const string cert_a = "cert_a";
+
+ state1->server_config = server_config_a;
+ state1->source_address_token = source_address_token_a;
+ state1->server_config_sig = server_config_sig_a;
+ state1->certs.push_back(cert_a);
+ quic_server_info1->Persist();
+
+ // Wait until Persist() does the work.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Persist data for port 80.
+ QuicServerId server_id2("www.google.com", 80, false, PRIVACY_MODE_DISABLED);
+ scoped_ptr<QuicServerInfo> quic_server_info2(
+ new DiskCacheBasedQuicServerInfo(server_id2, cache.http_cache()));
+ quic_server_info2->Start();
+ rv = quic_server_info2->WaitForDataReady(callback.callback());
+ EXPECT_EQ(OK, callback.GetResult(rv));
+
+ QuicServerInfo::State* state2 = quic_server_info2->mutable_state();
+ EXPECT_TRUE(state2->certs.empty());
+ const string server_config_b = "server_config_b";
+ const string source_address_token_b = "source_address_token_b";
+ const string server_config_sig_b = "server_config_sig_b";
+ const string cert_b = "cert_b";
+
+ state2->server_config = server_config_b;
+ state2->source_address_token = source_address_token_b;
+ state2->server_config_sig = server_config_sig_b;
+ state2->certs.push_back(cert_b);
+ quic_server_info2->Persist();
+
+ // Wait until Persist() does the work.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Verify the stored QuicServerInfo for port 443.
+ scoped_ptr<QuicServerInfo> quic_server_info(
+ new DiskCacheBasedQuicServerInfo(server_id1, cache.http_cache()));
+ quic_server_info->Start();
+ rv = quic_server_info->WaitForDataReady(callback.callback());
+ EXPECT_EQ(OK, callback.GetResult(rv));
+ EXPECT_TRUE(quic_server_info->IsDataReady());
+
+ const QuicServerInfo::State& state_a = quic_server_info->state();
+ EXPECT_EQ(server_config_a, state_a.server_config);
+ EXPECT_EQ(source_address_token_a, state_a.source_address_token);
+ EXPECT_EQ(server_config_sig_a, state_a.server_config_sig);
+ EXPECT_EQ(1U, state_a.certs.size());
+ EXPECT_EQ(cert_a, state_a.certs[0]);
+
+ // Verify the stored QuicServerInfo for port 80.
+ quic_server_info.reset(
+ new DiskCacheBasedQuicServerInfo(server_id2, cache.http_cache()));
+ quic_server_info->Start();
+ rv = quic_server_info->WaitForDataReady(callback.callback());
+ EXPECT_EQ(OK, callback.GetResult(rv));
+ EXPECT_TRUE(quic_server_info->IsDataReady());
+
+ const QuicServerInfo::State& state_b = quic_server_info->state();
+ EXPECT_EQ(server_config_b, state_b.server_config);
+ EXPECT_EQ(source_address_token_b, state_b.source_address_token);
+ EXPECT_EQ(server_config_sig_b, state_b.server_config_sig);
+ EXPECT_EQ(1U, state_b.certs.size());
+ EXPECT_EQ(cert_b, state_b.certs[0]);
+
+ RemoveMockTransaction(&kHostInfoTransaction2);
+ RemoveMockTransaction(&kHostInfoTransaction1);
+}
+
+// Test IsReadyToPersist when there is a pending write.
+TEST(DiskCacheBasedQuicServerInfo, IsReadyToPersist) {
+ MockHttpCache cache;
+ AddMockTransaction(&kHostInfoTransaction1);
+ TestCompletionCallback callback;
+
+ QuicServerId server_id("www.google.com", 443, true, PRIVACY_MODE_DISABLED);
+ scoped_ptr<QuicServerInfo> quic_server_info(
+ new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+ EXPECT_FALSE(quic_server_info->IsDataReady());
+ quic_server_info->Start();
+ int rv = quic_server_info->WaitForDataReady(callback.callback());
+ EXPECT_EQ(OK, callback.GetResult(rv));
+ EXPECT_TRUE(quic_server_info->IsDataReady());
+
+ QuicServerInfo::State* state = quic_server_info->mutable_state();
+ EXPECT_TRUE(state->certs.empty());
+ const string server_config_a = "server_config_a";
+ const string source_address_token_a = "source_address_token_a";
+ const string server_config_sig_a = "server_config_sig_a";
+ const string cert_a = "cert_a";
+
+ state->server_config = server_config_a;
+ state->source_address_token = source_address_token_a;
+ state->server_config_sig = server_config_sig_a;
+ state->certs.push_back(cert_a);
+ EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+ quic_server_info->Persist();
+
+ // Once we call Persist, IsReadyToPersist should return false until Persist
+ // has completed.
+ EXPECT_FALSE(quic_server_info->IsReadyToPersist());
+
+ // Wait until Persist() does the work.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+
+ // Verify that the state was updated.
+ quic_server_info.reset(
+ new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+ quic_server_info->Start();
+ rv = quic_server_info->WaitForDataReady(callback.callback());
+ EXPECT_EQ(OK, callback.GetResult(rv));
+ EXPECT_TRUE(quic_server_info->IsDataReady());
+
+ const QuicServerInfo::State& state1 = quic_server_info->state();
+ EXPECT_EQ(server_config_a, state1.server_config);
+ EXPECT_EQ(source_address_token_a, state1.source_address_token);
+ EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
+ EXPECT_EQ(1U, state1.certs.size());
+ EXPECT_EQ(cert_a, state1.certs[0]);
+
+ RemoveMockTransaction(&kHostInfoTransaction1);
+}
+
+} // namespace net
diff --git a/chromium/net/http/failing_http_transaction_factory.cc b/chromium/net/http/failing_http_transaction_factory.cc
new file mode 100644
index 00000000000..d1d1612966d
--- /dev/null
+++ b/chromium/net/http/failing_http_transaction_factory.cc
@@ -0,0 +1,191 @@
+// Copyright 2014 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.
+
+#include "net/http/failing_http_transaction_factory.h"
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "net/base/load_timing_info.h"
+#include "net/base/upload_progress.h"
+
+namespace net {
+
+class AuthCredentials;
+class BoundNetLog;
+class HttpRequestHeaders;
+class IOBuffer;
+class X509Certificate;
+
+struct HttpRequestInfo;
+
+namespace {
+
+// A simple class to interpose between the cache and network http layers.
+// These transactions can be generated by the FailingHttpTransactionFactory
+// to test interactions between cache and network.
+class FailingHttpTransaction : public HttpTransaction {
+ public:
+ explicit FailingHttpTransaction(Error error);
+ virtual ~FailingHttpTransaction();
+
+ // HttpTransaction
+ virtual int Start(const HttpRequestInfo* request_info,
+ const CompletionCallback& callback,
+ const BoundNetLog& net_log) OVERRIDE;
+ virtual int RestartIgnoringLastError(
+ const CompletionCallback& callback) OVERRIDE;
+ virtual int RestartWithCertificate(
+ X509Certificate* client_cert,
+ const CompletionCallback& callback) OVERRIDE;
+ virtual int RestartWithAuth(
+ const AuthCredentials& credentials,
+ const CompletionCallback& callback) OVERRIDE;
+ virtual bool IsReadyToRestartForAuth() OVERRIDE;
+ virtual int Read(IOBuffer* buf, int buf_len,
+ const CompletionCallback& callback) OVERRIDE;
+ virtual void StopCaching() OVERRIDE;
+ virtual bool GetFullRequestHeaders(
+ HttpRequestHeaders* headers) const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
+ virtual void DoneReading() OVERRIDE;
+ virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE;
+ virtual LoadState GetLoadState() const OVERRIDE;
+ virtual UploadProgress GetUploadProgress() const OVERRIDE;
+ virtual void SetQuicServerInfo(
+ net::QuicServerInfo* quic_server_info) OVERRIDE;
+ virtual bool GetLoadTimingInfo(
+ LoadTimingInfo* load_timing_info) const OVERRIDE;
+ virtual void SetPriority(RequestPriority priority) OVERRIDE;
+ virtual void SetWebSocketHandshakeStreamCreateHelper(
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper) OVERRIDE;
+ virtual void SetBeforeNetworkStartCallback(
+ const BeforeNetworkStartCallback& callback) OVERRIDE;
+ virtual int ResumeNetworkStart() OVERRIDE;
+
+ private:
+ Error error_;
+};
+
+FailingHttpTransaction::FailingHttpTransaction(Error error) : error_(error) {
+ DCHECK_LT(error, OK);
+}
+
+FailingHttpTransaction::~FailingHttpTransaction() {}
+
+int FailingHttpTransaction::Start(const HttpRequestInfo* request_info,
+ const CompletionCallback& callback,
+ const BoundNetLog& net_log) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, error_));
+ return ERR_IO_PENDING;
+}
+
+int FailingHttpTransaction::RestartIgnoringLastError(
+ const CompletionCallback& callback) {
+ return ERR_FAILED;
+}
+
+int FailingHttpTransaction::RestartWithCertificate(
+ X509Certificate* client_cert,
+ const CompletionCallback& callback) {
+ return ERR_FAILED;
+}
+
+int FailingHttpTransaction::RestartWithAuth(
+ const AuthCredentials& credentials,
+ const CompletionCallback& callback) {
+ return ERR_FAILED;
+}
+
+bool FailingHttpTransaction::IsReadyToRestartForAuth() {
+ return false;
+}
+
+int FailingHttpTransaction::Read(IOBuffer* buf, int buf_len,
+ const CompletionCallback& callback) {
+ NOTREACHED();
+ return ERR_FAILED;
+}
+
+void FailingHttpTransaction::StopCaching() {}
+
+bool FailingHttpTransaction::GetFullRequestHeaders(
+ HttpRequestHeaders* headers) const {
+ return false;
+}
+
+int64 FailingHttpTransaction::GetTotalReceivedBytes() const {
+ return 0;
+}
+
+void FailingHttpTransaction::DoneReading() {
+ NOTREACHED();
+}
+
+const HttpResponseInfo* FailingHttpTransaction::GetResponseInfo() const {
+ return NULL;
+}
+
+LoadState FailingHttpTransaction::GetLoadState() const {
+ return LOAD_STATE_IDLE;
+}
+
+UploadProgress FailingHttpTransaction::GetUploadProgress() const {
+ return UploadProgress();
+}
+
+void FailingHttpTransaction::SetQuicServerInfo(
+ net::QuicServerInfo* quic_server_info) {}
+
+bool FailingHttpTransaction::GetLoadTimingInfo(
+ LoadTimingInfo* load_timing_info) const {
+ return false;
+}
+
+void FailingHttpTransaction::SetPriority(RequestPriority priority) {}
+
+void FailingHttpTransaction::SetWebSocketHandshakeStreamCreateHelper(
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
+ NOTREACHED();
+}
+
+void FailingHttpTransaction::SetBeforeNetworkStartCallback(
+ const BeforeNetworkStartCallback& callback) {
+}
+
+int FailingHttpTransaction::ResumeNetworkStart() {
+ NOTREACHED();
+ return ERR_FAILED;
+}
+
+} // namespace
+
+FailingHttpTransactionFactory::FailingHttpTransactionFactory(
+ HttpNetworkSession* session,
+ Error error) : session_(session), error_(error) {
+ DCHECK_LT(error, OK);
+}
+
+FailingHttpTransactionFactory::~FailingHttpTransactionFactory() {}
+
+// HttpTransactionFactory:
+int FailingHttpTransactionFactory::CreateTransaction(
+ RequestPriority priority,
+ scoped_ptr<HttpTransaction>* trans) {
+ trans->reset(new FailingHttpTransaction(error_));
+ return OK;
+}
+
+HttpCache* FailingHttpTransactionFactory::GetCache() {
+ return NULL;
+}
+
+HttpNetworkSession* FailingHttpTransactionFactory::GetSession() {
+ return session_;
+}
+
+} // namespace net
+
diff --git a/chromium/net/http/failing_http_transaction_factory.h b/chromium/net/http/failing_http_transaction_factory.h
new file mode 100644
index 00000000000..84d87a7a3d3
--- /dev/null
+++ b/chromium/net/http/failing_http_transaction_factory.h
@@ -0,0 +1,42 @@
+// Copyright 2014 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_FAILING_HTTP_TRANSACTION_FACTORY_H_
+#define NET_FAILING_HTTP_TRANSACTION_FACTORY_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "net/base/net_errors.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_transaction.h"
+#include "net/http/http_transaction_factory.h"
+
+namespace net {
+
+class HttpCache;
+class HttpNetworkSession;
+
+// Creates transactions that always (asynchronously) return a specified
+// error. The error is returned asynchronously, just after the transaction is
+// started.
+class NET_EXPORT FailingHttpTransactionFactory : public HttpTransactionFactory {
+ public:
+ // The caller must guarantee that |session| outlives this object.
+ FailingHttpTransactionFactory(HttpNetworkSession* session, Error error);
+ virtual ~FailingHttpTransactionFactory();
+
+ // HttpTransactionFactory:
+ virtual int CreateTransaction(
+ RequestPriority priority,
+ scoped_ptr<HttpTransaction>* trans) OVERRIDE;
+ virtual HttpCache* GetCache() OVERRIDE;
+ virtual HttpNetworkSession* GetSession() OVERRIDE;
+
+ private:
+ HttpNetworkSession* session_;
+ Error error_;
+};
+
+} // namespace net
+
+#endif // NET_FAILING_HTTP_TRANSACTION_FACTORY_H_
diff --git a/chromium/net/http/http_auth.cc b/chromium/net/http/http_auth.cc
index 3cc9db1a122..4c6d3e8dda3 100644
--- a/chromium/net/http/http_auth.cc
+++ b/chromium/net/http/http_auth.cc
@@ -10,6 +10,7 @@
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "net/base/net_errors.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_handler.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_request_headers.h"
@@ -74,7 +75,7 @@ HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
HttpAuth::AuthorizationResult authorization_result =
HttpAuth::AUTHORIZATION_RESULT_INVALID;
while (headers->EnumerateHeader(&iter, header_name, &challenge)) {
- HttpAuth::ChallengeTokenizer props(challenge.begin(), challenge.end());
+ HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
if (!LowerCaseEqualsASCII(props.scheme(), current_scheme_name.c_str()))
continue;
authorization_result = handler->HandleAnotherChallenge(&props);
@@ -87,56 +88,6 @@ HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
return HttpAuth::AUTHORIZATION_RESULT_REJECT;
}
-HttpAuth::ChallengeTokenizer::ChallengeTokenizer(
- std::string::const_iterator begin,
- std::string::const_iterator end)
- : begin_(begin),
- end_(end),
- scheme_begin_(begin),
- scheme_end_(begin),
- params_begin_(end),
- params_end_(end) {
- Init(begin, end);
-}
-
-HttpUtil::NameValuePairsIterator HttpAuth::ChallengeTokenizer::param_pairs()
- const {
- return HttpUtil::NameValuePairsIterator(params_begin_, params_end_, ',');
-}
-
-std::string HttpAuth::ChallengeTokenizer::base64_param() const {
- // Strip off any padding.
- // (See https://bugzilla.mozilla.org/show_bug.cgi?id=230351.)
- //
- // Our base64 decoder requires that the length be a multiple of 4.
- int encoded_length = params_end_ - params_begin_;
- while (encoded_length > 0 && encoded_length % 4 != 0 &&
- params_begin_[encoded_length - 1] == '=') {
- --encoded_length;
- }
- return std::string(params_begin_, params_begin_ + encoded_length);
-}
-
-void HttpAuth::ChallengeTokenizer::Init(std::string::const_iterator begin,
- std::string::const_iterator end) {
- // The first space-separated token is the auth-scheme.
- // NOTE: we are more permissive than RFC 2617 which says auth-scheme
- // is separated by 1*SP.
- base::StringTokenizer tok(begin, end, HTTP_LWS);
- if (!tok.GetNext()) {
- // Default param and scheme iterators provide empty strings
- return;
- }
-
- // Save the scheme's position.
- scheme_begin_ = tok.token_begin();
- scheme_end_ = tok.token_end();
-
- params_begin_ = scheme_end_;
- params_end_ = end;
- HttpUtil::TrimLWS(&params_begin_, &params_end_);
-}
-
// static
std::string HttpAuth::GetChallengeHeaderName(Target target) {
switch (target) {
diff --git a/chromium/net/http/http_auth.h b/chromium/net/http/http_auth.h
index 1a03bb1fe1f..5a2c7ac6606 100644
--- a/chromium/net/http/http_auth.h
+++ b/chromium/net/http/http_auth.h
@@ -167,48 +167,6 @@ class NET_EXPORT_PRIVATE HttpAuth {
Target target,
const std::set<Scheme>& disabled_schemes,
std::string* challenge_used);
-
- // Breaks up a challenge string into the the auth scheme and parameter list,
- // according to RFC 2617 Sec 1.2:
- // challenge = auth-scheme 1*SP 1#auth-param
- //
- // Depending on the challenge scheme, it may be appropriate to interpret the
- // parameters as either a base-64 encoded string or a comma-delimited list
- // of name-value pairs. param_pairs() and base64_param() methods are provided
- // to support either usage.
- class NET_EXPORT_PRIVATE ChallengeTokenizer {
- public:
- ChallengeTokenizer(std::string::const_iterator begin,
- std::string::const_iterator end);
-
- // Get the original text.
- std::string challenge_text() const {
- return std::string(begin_, end_);
- }
-
- // Get the auth scheme of the challenge.
- std::string::const_iterator scheme_begin() const { return scheme_begin_; }
- std::string::const_iterator scheme_end() const { return scheme_end_; }
- std::string scheme() const {
- return std::string(scheme_begin_, scheme_end_);
- }
-
- HttpUtil::NameValuePairsIterator param_pairs() const;
- std::string base64_param() const;
-
- private:
- void Init(std::string::const_iterator begin,
- std::string::const_iterator end);
-
- std::string::const_iterator begin_;
- std::string::const_iterator end_;
-
- std::string::const_iterator scheme_begin_;
- std::string::const_iterator scheme_end_;
-
- std::string::const_iterator params_begin_;
- std::string::const_iterator params_end_;
- };
};
} // namespace net
diff --git a/chromium/net/http/http_auth_cache.cc b/chromium/net/http/http_auth_cache.cc
index 63bad076df1..d989830b2aa 100644
--- a/chromium/net/http/http_auth_cache.cc
+++ b/chromium/net/http/http_auth_cache.cc
@@ -5,6 +5,7 @@
#include "net/http/http_auth_cache.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
namespace {
@@ -57,6 +58,14 @@ struct IsEnclosedBy {
const std::string& path;
};
+void RecordLookupPosition(int position) {
+ UMA_HISTOGRAM_COUNTS_100("Net.HttpAuthCacheLookupPosition", position);
+}
+
+void RecordLookupByPathPosition(int position) {
+ UMA_HISTOGRAM_COUNTS_100("Net.HttpAuthCacheLookupByPathPosition", position);
+}
+
} // namespace
namespace net {
@@ -73,12 +82,18 @@ HttpAuthCache::Entry* HttpAuthCache::Lookup(const GURL& origin,
HttpAuth::Scheme scheme) {
CheckOriginIsValid(origin);
+ int entries_examined = 0;
// Linear scan through the realm entries.
for (EntryList::iterator it = entries_.begin(); it != entries_.end(); ++it) {
+ ++entries_examined;
if (it->origin() == origin && it->realm() == realm &&
- it->scheme() == scheme)
+ it->scheme() == scheme) {
+ it->last_use_time_ = base::TimeTicks::Now();
+ RecordLookupPosition(entries_examined);
return &(*it);
+ }
}
+ RecordLookupPosition(0);
return NULL; // No realm entry found.
}
@@ -89,6 +104,7 @@ HttpAuthCache::Entry* HttpAuthCache::LookupByPath(const GURL& origin,
const std::string& path) {
HttpAuthCache::Entry* best_match = NULL;
size_t best_match_length = 0;
+ int best_match_position = 0;
CheckOriginIsValid(origin);
CheckPathIsValid(path);
@@ -98,15 +114,21 @@ HttpAuthCache::Entry* HttpAuthCache::LookupByPath(const GURL& origin,
// within the protection space ...
std::string parent_dir = GetParentDirectory(path);
+ int entries_examined = 0;
// Linear scan through the realm entries.
for (EntryList::iterator it = entries_.begin(); it != entries_.end(); ++it) {
+ ++entries_examined;
size_t len = 0;
if (it->origin() == origin && it->HasEnclosingPath(parent_dir, &len) &&
(!best_match || len > best_match_length)) {
- best_match_length = len;
best_match = &(*it);
+ best_match_length = len;
+ best_match_position = entries_examined;
}
}
+ if (best_match)
+ best_match->last_use_time_ = base::TimeTicks::Now();
+ RecordLookupByPathPosition(best_match_position);
return best_match;
}
@@ -119,20 +141,30 @@ HttpAuthCache::Entry* HttpAuthCache::Add(const GURL& origin,
CheckOriginIsValid(origin);
CheckPathIsValid(path);
+ base::TimeTicks now = base::TimeTicks::Now();
+
// Check for existing entry (we will re-use it if present).
HttpAuthCache::Entry* entry = Lookup(origin, realm, scheme);
if (!entry) {
+ bool evicted = false;
// Failsafe to prevent unbounded memory growth of the cache.
if (entries_.size() >= kMaxNumRealmEntries) {
LOG(WARNING) << "Num auth cache entries reached limit -- evicting";
+ UMA_HISTOGRAM_LONG_TIMES("Net.HttpAuthCacheAddEvictedCreation",
+ now - entries_.back().creation_time_);
+ UMA_HISTOGRAM_LONG_TIMES("Net.HttpAuthCacheAddEvictedLastUse",
+ now - entries_.back().last_use_time_);
entries_.pop_back();
+ evicted = true;
}
+ UMA_HISTOGRAM_BOOLEAN("Net.HttpAuthCacheAddEvicted", evicted);
entries_.push_front(Entry());
entry = &entries_.front();
entry->origin_ = origin;
entry->realm_ = realm;
entry->scheme_ = scheme;
+ entry->creation_time_ = now;
}
DCHECK_EQ(origin, entry->origin_);
DCHECK_EQ(realm, entry->realm_);
@@ -142,6 +174,7 @@ HttpAuthCache::Entry* HttpAuthCache::Add(const GURL& origin,
entry->credentials_ = credentials;
entry->nonce_count_ = 1;
entry->AddPath(path);
+ entry->last_use_time_ = now;
return entry;
}
@@ -166,12 +199,15 @@ void HttpAuthCache::Entry::AddPath(const std::string& path) {
// Remove any entries that have been subsumed by the new entry.
paths_.remove_if(IsEnclosedBy(parent_dir));
+ bool evicted = false;
// Failsafe to prevent unbounded memory growth of the cache.
if (paths_.size() >= kMaxNumPathsPerRealmEntry) {
LOG(WARNING) << "Num path entries for " << origin()
<< " has grown too large -- evicting";
paths_.pop_back();
+ evicted = true;
}
+ UMA_HISTOGRAM_BOOLEAN("Net.HttpAuthCacheAddPathEvicted", evicted);
// Add new path.
paths_.push_front(parent_dir);
@@ -221,6 +257,7 @@ bool HttpAuthCache::UpdateStaleChallenge(const GURL& origin,
if (!entry)
return false;
entry->UpdateStaleChallenge(auth_challenge);
+ entry->last_use_time_ = base::TimeTicks::Now();
return true;
}
diff --git a/chromium/net/http/http_auth_cache.h b/chromium/net/http/http_auth_cache.h
index 75b379f25bd..707a571db96 100644
--- a/chromium/net/http/http_auth_cache.h
+++ b/chromium/net/http/http_auth_cache.h
@@ -10,6 +10,7 @@
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
#include "net/base/net_export.h"
#include "net/http/http_auth.h"
#include "url/gurl.h"
@@ -96,6 +97,11 @@ class NET_EXPORT_PRIVATE HttpAuthCache {
// List of paths that define the realm's protection space.
PathList paths_;
+
+ // Times the entry was created and last used (by looking up, adding a path,
+ // or updating the challenge.)
+ base::TimeTicks creation_time_;
+ base::TimeTicks last_use_time_;
};
// Prevent unbounded memory growth. These are safeguards for abuse; it is
diff --git a/chromium/net/http/http_auth_cache_unittest.cc b/chromium/net/http/http_auth_cache_unittest.cc
index a4ea1c6da03..e925c714316 100644
--- a/chromium/net/http/http_auth_cache_unittest.cc
+++ b/chromium/net/http/http_auth_cache_unittest.cc
@@ -13,6 +13,8 @@
#include "net/http/http_auth_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::ASCIIToUTF16;
+
namespace net {
namespace {
@@ -31,12 +33,12 @@ class MockAuthHandler : public HttpAuthHandler {
}
virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) OVERRIDE {
+ HttpAuthChallengeTokenizer* challenge) OVERRIDE {
return HttpAuth::AUTHORIZATION_RESULT_REJECT;
}
protected:
- virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) OVERRIDE {
+ virtual bool Init(HttpAuthChallengeTokenizer* challenge) OVERRIDE {
return false; // Unused.
}
diff --git a/chromium/net/http/http_auth_challenge_tokenizer.cc b/chromium/net/http/http_auth_challenge_tokenizer.cc
new file mode 100644
index 00000000000..528566c8664
--- /dev/null
+++ b/chromium/net/http/http_auth_challenge_tokenizer.cc
@@ -0,0 +1,61 @@
+// Copyright 2014 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.
+
+#include "net/http/http_auth_challenge_tokenizer.h"
+
+#include "base/strings/string_tokenizer.h"
+
+namespace net {
+
+HttpAuthChallengeTokenizer::HttpAuthChallengeTokenizer(
+ std::string::const_iterator begin,
+ std::string::const_iterator end)
+ : begin_(begin),
+ end_(end),
+ scheme_begin_(begin),
+ scheme_end_(begin),
+ params_begin_(end),
+ params_end_(end) {
+ Init(begin, end);
+}
+
+HttpUtil::NameValuePairsIterator HttpAuthChallengeTokenizer::param_pairs()
+ const {
+ return HttpUtil::NameValuePairsIterator(params_begin_, params_end_, ',');
+}
+
+std::string HttpAuthChallengeTokenizer::base64_param() const {
+ // Strip off any padding.
+ // (See https://bugzilla.mozilla.org/show_bug.cgi?id=230351.)
+ //
+ // Our base64 decoder requires that the length be a multiple of 4.
+ int encoded_length = params_end_ - params_begin_;
+ while (encoded_length > 0 && encoded_length % 4 != 0 &&
+ params_begin_[encoded_length - 1] == '=') {
+ --encoded_length;
+ }
+ return std::string(params_begin_, params_begin_ + encoded_length);
+}
+
+void HttpAuthChallengeTokenizer::Init(std::string::const_iterator begin,
+ std::string::const_iterator end) {
+ // The first space-separated token is the auth-scheme.
+ // NOTE: we are more permissive than RFC 2617 which says auth-scheme
+ // is separated by 1*SP.
+ base::StringTokenizer tok(begin, end, HTTP_LWS);
+ if (!tok.GetNext()) {
+ // Default param and scheme iterators provide empty strings
+ return;
+ }
+
+ // Save the scheme's position.
+ scheme_begin_ = tok.token_begin();
+ scheme_end_ = tok.token_end();
+
+ params_begin_ = scheme_end_;
+ params_end_ = end;
+ HttpUtil::TrimLWS(&params_begin_, &params_end_);
+}
+
+} // namespace net
diff --git a/chromium/net/http/http_auth_challenge_tokenizer.h b/chromium/net/http/http_auth_challenge_tokenizer.h
new file mode 100644
index 00000000000..a73f19205b6
--- /dev/null
+++ b/chromium/net/http/http_auth_challenge_tokenizer.h
@@ -0,0 +1,61 @@
+// Copyright 2014 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_HTTP_HTTP_AUTH_CHALLENGE_TOKENIZER_
+#define NET_HTTP_HTTP_AUTH_CHALLENGE_TOKENIZER_
+
+#include <string>
+
+#include "net/base/net_export.h"
+#include "net/http/http_util.h"
+
+namespace net {
+
+// Breaks up a challenge string into the the auth scheme and parameter list,
+// according to RFC 2617 Sec 1.2:
+// challenge = auth-scheme 1*SP 1#auth-param
+//
+// Depending on the challenge scheme, it may be appropriate to interpret the
+// parameters as either a base-64 encoded string or a comma-delimited list
+// of name-value pairs. param_pairs() and base64_param() methods are provided
+// to support either usage.
+class NET_EXPORT_PRIVATE HttpAuthChallengeTokenizer {
+ public:
+ HttpAuthChallengeTokenizer(std::string::const_iterator begin,
+ std::string::const_iterator end);
+
+ // Get the original text.
+ std::string challenge_text() const {
+ return std::string(begin_, end_);
+ }
+
+ // Get the auth scheme of the challenge.
+ std::string::const_iterator scheme_begin() const { return scheme_begin_; }
+ std::string::const_iterator scheme_end() const { return scheme_end_; }
+ std::string scheme() const {
+ return std::string(scheme_begin_, scheme_end_);
+ }
+
+ std::string::const_iterator params_begin() const { return params_begin_; }
+ std::string::const_iterator params_end() const { return params_end_; }
+ HttpUtil::NameValuePairsIterator param_pairs() const;
+ std::string base64_param() const;
+
+ private:
+ void Init(std::string::const_iterator begin,
+ std::string::const_iterator end);
+
+ std::string::const_iterator begin_;
+ std::string::const_iterator end_;
+
+ std::string::const_iterator scheme_begin_;
+ std::string::const_iterator scheme_end_;
+
+ std::string::const_iterator params_begin_;
+ std::string::const_iterator params_end_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP_HTTP_AUTH_CHALLENGE_TOKENIZER_
diff --git a/chromium/net/http/http_auth_challenge_tokenizer_unittest.cc b/chromium/net/http/http_auth_challenge_tokenizer_unittest.cc
new file mode 100644
index 00000000000..2cf657a17f5
--- /dev/null
+++ b/chromium/net/http/http_auth_challenge_tokenizer_unittest.cc
@@ -0,0 +1,177 @@
+// Copyright 2014 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.
+
+#include "net/http/http_auth_challenge_tokenizer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+TEST(HttpAuthChallengeTokenizerTest, Basic) {
+ std::string challenge_str = "Basic realm=\"foobar\"";
+ HttpAuthChallengeTokenizer challenge(challenge_str.begin(),
+ challenge_str.end());
+ HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
+
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("Basic"), challenge.scheme());
+ EXPECT_TRUE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("realm"), parameters.name());
+ EXPECT_EQ(std::string("foobar"), parameters.value());
+ EXPECT_FALSE(parameters.GetNext());
+}
+
+// Use a name=value property with no quote marks.
+TEST(HttpAuthChallengeTokenizerTest, NoQuotes) {
+ std::string challenge_str = "Basic realm=foobar@baz.com";
+ HttpAuthChallengeTokenizer challenge(challenge_str.begin(),
+ challenge_str.end());
+ HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
+
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("Basic"), challenge.scheme());
+ EXPECT_TRUE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("realm"), parameters.name());
+ EXPECT_EQ(std::string("foobar@baz.com"), parameters.value());
+ EXPECT_FALSE(parameters.GetNext());
+}
+
+// Use a name=value property with mismatching quote marks.
+TEST(HttpAuthChallengeTokenizerTest, MismatchedQuotes) {
+ std::string challenge_str = "Basic realm=\"foobar@baz.com";
+ HttpAuthChallengeTokenizer challenge(challenge_str.begin(),
+ challenge_str.end());
+ HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
+
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("Basic"), challenge.scheme());
+ EXPECT_TRUE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("realm"), parameters.name());
+ EXPECT_EQ(std::string("foobar@baz.com"), parameters.value());
+ EXPECT_FALSE(parameters.GetNext());
+}
+
+// Use a name= property without a value and with mismatching quote marks.
+TEST(HttpAuthChallengeTokenizerTest, MismatchedQuotesNoValue) {
+ std::string challenge_str = "Basic realm=\"";
+ HttpAuthChallengeTokenizer challenge(challenge_str.begin(),
+ challenge_str.end());
+ HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
+
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("Basic"), challenge.scheme());
+ EXPECT_TRUE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("realm"), parameters.name());
+ EXPECT_EQ(std::string(), parameters.value());
+ EXPECT_FALSE(parameters.GetNext());
+}
+
+// Use a name=value property with mismatching quote marks and spaces in the
+// value.
+TEST(HttpAuthChallengeTokenizerTest, MismatchedQuotesSpaces) {
+ std::string challenge_str = "Basic realm=\"foo bar";
+ HttpAuthChallengeTokenizer challenge(challenge_str.begin(),
+ challenge_str.end());
+ HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
+
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("Basic"), challenge.scheme());
+ EXPECT_TRUE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("realm"), parameters.name());
+ EXPECT_EQ(std::string("foo bar"), parameters.value());
+ EXPECT_FALSE(parameters.GetNext());
+}
+
+// Use multiple name=value properties with mismatching quote marks in the last
+// value.
+TEST(HttpAuthChallengeTokenizerTest, MismatchedQuotesMultiple) {
+ std::string challenge_str = "Digest qop=auth-int, algorithm=md5, realm=\"foo";
+ HttpAuthChallengeTokenizer challenge(challenge_str.begin(),
+ challenge_str.end());
+ HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
+
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("Digest"), challenge.scheme());
+ EXPECT_TRUE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("qop"), parameters.name());
+ EXPECT_EQ(std::string("auth-int"), parameters.value());
+ EXPECT_TRUE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("algorithm"), parameters.name());
+ EXPECT_EQ(std::string("md5"), parameters.value());
+ EXPECT_TRUE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("realm"), parameters.name());
+ EXPECT_EQ(std::string("foo"), parameters.value());
+ EXPECT_FALSE(parameters.GetNext());
+}
+
+// Use a name= property which has no value.
+TEST(HttpAuthChallengeTokenizerTest, NoValue) {
+ std::string challenge_str = "Digest qop=";
+ HttpAuthChallengeTokenizer challenge(
+ challenge_str.begin(), challenge_str.end());
+ HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
+
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("Digest"), challenge.scheme());
+ EXPECT_FALSE(parameters.GetNext());
+ EXPECT_FALSE(parameters.valid());
+}
+
+// Specify multiple properties, comma separated.
+TEST(HttpAuthChallengeTokenizerTest, Multiple) {
+ std::string challenge_str =
+ "Digest algorithm=md5, realm=\"Oblivion\", qop=auth-int";
+ HttpAuthChallengeTokenizer challenge(challenge_str.begin(),
+ challenge_str.end());
+ HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
+
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("Digest"), challenge.scheme());
+ EXPECT_TRUE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("algorithm"), parameters.name());
+ EXPECT_EQ(std::string("md5"), parameters.value());
+ EXPECT_TRUE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("realm"), parameters.name());
+ EXPECT_EQ(std::string("Oblivion"), parameters.value());
+ EXPECT_TRUE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("qop"), parameters.name());
+ EXPECT_EQ(std::string("auth-int"), parameters.value());
+ EXPECT_FALSE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
+}
+
+// Use a challenge which has no property.
+TEST(HttpAuthChallengeTokenizerTest, NoProperty) {
+ std::string challenge_str = "NTLM";
+ HttpAuthChallengeTokenizer challenge(
+ challenge_str.begin(), challenge_str.end());
+ HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
+
+ EXPECT_TRUE(parameters.valid());
+ EXPECT_EQ(std::string("NTLM"), challenge.scheme());
+ EXPECT_FALSE(parameters.GetNext());
+}
+
+// Use a challenge with Base64 encoded token.
+TEST(HttpAuthChallengeTokenizerTest, Base64) {
+ std::string challenge_str = "NTLM SGVsbG8sIFdvcmxkCg===";
+ HttpAuthChallengeTokenizer challenge(challenge_str.begin(),
+ challenge_str.end());
+
+ EXPECT_EQ(std::string("NTLM"), challenge.scheme());
+ // Notice the two equal statements below due to padding removal.
+ EXPECT_EQ(std::string("SGVsbG8sIFdvcmxkCg=="), challenge.base64_param());
+}
+
+} // namespace net
diff --git a/chromium/net/http/http_auth_controller_unittest.cc b/chromium/net/http/http_auth_controller_unittest.cc
index 2a18369c1f7..1a59b8d4f68 100644
--- a/chromium/net/http/http_auth_controller_unittest.cc
+++ b/chromium/net/http/http_auth_controller_unittest.cc
@@ -9,6 +9,7 @@
#include "net/base/net_log.h"
#include "net/base/test_completion_callback.h"
#include "net/http/http_auth_cache.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_handler_mock.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
@@ -127,7 +128,7 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) {
}
protected:
- virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) OVERRIDE {
+ virtual bool Init(HttpAuthChallengeTokenizer* challenge) OVERRIDE {
HttpAuthHandlerMock::Init(challenge);
set_allows_default_credentials(true);
set_allows_explicit_credentials(false);
@@ -224,7 +225,7 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) {
ASSERT_EQ(OK,
controller->HandleAuthChallenge(headers, false, false, dummy_log));
ASSERT_TRUE(controller->HaveAuthHandler());
- controller->ResetAuth(AuthCredentials(ASCIIToUTF16("Hello"),
+ controller->ResetAuth(AuthCredentials(base::ASCIIToUTF16("Hello"),
base::string16()));
EXPECT_TRUE(controller->HaveAuth());
EXPECT_TRUE(controller->IsAuthSchemeDisabled(HttpAuth::AUTH_SCHEME_MOCK));
diff --git a/chromium/net/http/http_auth_filter_win.h b/chromium/net/http/http_auth_filter_win.h
index 24305b511ec..d2c0af4a09d 100644
--- a/chromium/net/http/http_auth_filter_win.h
+++ b/chromium/net/http/http_auth_filter_win.h
@@ -20,13 +20,13 @@ enum RegistryHiveType {
namespace http_auth {
// The common path to all the registry keys containing domain zone information.
-extern const char16 kRegistryInternetSettings[];
-extern const char16 kSettingsMachineOnly[];
-extern const char16* kRegistryEntries[3]; // L"http", L"https", and L"*"
+extern const base::char16 kRegistryInternetSettings[];
+extern const base::char16 kSettingsMachineOnly[];
+extern const base::char16* kRegistryEntries[3]; // L"http", L"https", and L"*"
-extern const char16* GetRegistryWhitelistKey();
+extern const base::char16* GetRegistryWhitelistKey();
// Override the whitelist key. Passing in NULL restores the default value.
-extern void SetRegistryWhitelistKey(const char16* new_whitelist_key);
+extern void SetRegistryWhitelistKey(const base::char16* new_whitelist_key);
extern bool UseOnlyMachineSettings();
} // namespace http_auth
diff --git a/chromium/net/http/http_auth_gssapi_posix.cc b/chromium/net/http/http_auth_gssapi_posix.cc
index 41cbcdbcdc0..a4b8c0cd839 100644
--- a/chromium/net/http/http_auth_gssapi_posix.cc
+++ b/chromium/net/http/http_auth_gssapi_posix.cc
@@ -16,6 +16,7 @@
#include "base/threading/thread_restrictions.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
// These are defined for the GSSAPI library:
// Paraphrasing the comments from gssapi.h:
@@ -684,7 +685,7 @@ void HttpAuthGSSAPI::Delegate() {
}
HttpAuth::AuthorizationResult HttpAuthGSSAPI::ParseChallenge(
- HttpAuth::ChallengeTokenizer* tok) {
+ HttpAuthChallengeTokenizer* tok) {
// Verify the challenge's auth-scheme.
if (!LowerCaseEqualsASCII(tok->scheme(), StringToLowerASCII(scheme_).c_str()))
return HttpAuth::AUTHORIZATION_RESULT_INVALID;
diff --git a/chromium/net/http/http_auth_gssapi_posix.h b/chromium/net/http/http_auth_gssapi_posix.h
index db603f65da8..ddaf518736b 100644
--- a/chromium/net/http/http_auth_gssapi_posix.h
+++ b/chromium/net/http/http_auth_gssapi_posix.h
@@ -22,6 +22,8 @@
namespace net {
+class HttpAuthChallengeTokenizer;
+
// Mechanism OID for GSSAPI. We always use SPNEGO.
NET_EXPORT_PRIVATE extern gss_OID CHROME_GSS_SPNEGO_MECH_OID_DESC;
@@ -240,7 +242,7 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI {
bool AllowsExplicitCredentials() const;
HttpAuth::AuthorizationResult ParseChallenge(
- HttpAuth::ChallengeTokenizer* tok);
+ HttpAuthChallengeTokenizer* tok);
// Generates an authentication token.
// The return value is an error code. If it's not |OK|, the value of
diff --git a/chromium/net/http/http_auth_gssapi_posix_unittest.cc b/chromium/net/http/http_auth_gssapi_posix_unittest.cc
index 48d17a3ad64..6f933349d7e 100644
--- a/chromium/net/http/http_auth_gssapi_posix_unittest.cc
+++ b/chromium/net/http/http_auth_gssapi_posix_unittest.cc
@@ -9,6 +9,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/native_library.h"
#include "net/base/net_errors.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/mock_gssapi_library_posix.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -181,8 +182,8 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_FirstRound) {
HttpAuthGSSAPI auth_gssapi(&mock_library, "Negotiate",
CHROME_GSS_SPNEGO_MECH_OID_DESC);
std::string challenge_text = "Negotiate";
- HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
- challenge_text.end());
+ HttpAuthChallengeTokenizer challenge(challenge_text.begin(),
+ challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
auth_gssapi.ParseChallenge(&challenge));
}
@@ -194,8 +195,8 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_TwoRounds) {
HttpAuthGSSAPI auth_gssapi(&mock_library, "Negotiate",
CHROME_GSS_SPNEGO_MECH_OID_DESC);
std::string first_challenge_text = "Negotiate";
- HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(),
- first_challenge_text.end());
+ HttpAuthChallengeTokenizer first_challenge(first_challenge_text.begin(),
+ first_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
auth_gssapi.ParseChallenge(&first_challenge));
@@ -206,8 +207,8 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_TwoRounds) {
&auth_token));
std::string second_challenge_text = "Negotiate Zm9vYmFy";
- HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
- second_challenge_text.end());
+ HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
+ second_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
auth_gssapi.ParseChallenge(&second_challenge));
}
@@ -219,8 +220,8 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_UnexpectedTokenFirstRound) {
HttpAuthGSSAPI auth_gssapi(&mock_library, "Negotiate",
CHROME_GSS_SPNEGO_MECH_OID_DESC);
std::string challenge_text = "Negotiate Zm9vYmFy";
- HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
- challenge_text.end());
+ HttpAuthChallengeTokenizer challenge(challenge_text.begin(),
+ challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID,
auth_gssapi.ParseChallenge(&challenge));
}
@@ -232,8 +233,8 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_MissingTokenSecondRound) {
HttpAuthGSSAPI auth_gssapi(&mock_library, "Negotiate",
CHROME_GSS_SPNEGO_MECH_OID_DESC);
std::string first_challenge_text = "Negotiate";
- HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(),
- first_challenge_text.end());
+ HttpAuthChallengeTokenizer first_challenge(first_challenge_text.begin(),
+ first_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
auth_gssapi.ParseChallenge(&first_challenge));
@@ -242,8 +243,8 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_MissingTokenSecondRound) {
EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
&auth_token));
std::string second_challenge_text = "Negotiate";
- HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
- second_challenge_text.end());
+ HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
+ second_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT,
auth_gssapi.ParseChallenge(&second_challenge));
}
@@ -255,8 +256,8 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_NonBase64EncodedToken) {
HttpAuthGSSAPI auth_gssapi(&mock_library, "Negotiate",
CHROME_GSS_SPNEGO_MECH_OID_DESC);
std::string first_challenge_text = "Negotiate";
- HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(),
- first_challenge_text.end());
+ HttpAuthChallengeTokenizer first_challenge(first_challenge_text.begin(),
+ first_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
auth_gssapi.ParseChallenge(&first_challenge));
@@ -265,8 +266,8 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_NonBase64EncodedToken) {
EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
&auth_token));
std::string second_challenge_text = "Negotiate =happyjoy=";
- HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
- second_challenge_text.end());
+ HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
+ second_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID,
auth_gssapi.ParseChallenge(&second_challenge));
}
diff --git a/chromium/net/http/http_auth_handler.cc b/chromium/net/http/http_auth_handler.cc
index ab809faefae..7369ea5425f 100644
--- a/chromium/net/http/http_auth_handler.cc
+++ b/chromium/net/http/http_auth_handler.cc
@@ -8,6 +8,7 @@
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "net/base/net_errors.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
namespace net {
@@ -22,7 +23,7 @@ HttpAuthHandler::~HttpAuthHandler() {
}
bool HttpAuthHandler::InitFromChallenge(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
const BoundNetLog& net_log) {
diff --git a/chromium/net/http/http_auth_handler.h b/chromium/net/http/http_auth_handler.h
index 638bb44aed3..dfb50d43a60 100644
--- a/chromium/net/http/http_auth_handler.h
+++ b/chromium/net/http/http_auth_handler.h
@@ -14,6 +14,7 @@
namespace net {
+class HttpAuthChallengeTokenizer;
struct HttpRequestInfo;
// HttpAuthHandler is the interface for the authentication schemes
@@ -29,7 +30,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandler {
// authentication scheme, but none of the tokens occurring after the
// authentication scheme. |target| and |origin| are both stored
// for later use, and are not part of the initial challenge.
- bool InitFromChallenge(HttpAuth::ChallengeTokenizer* challenge,
+ bool InitFromChallenge(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
const BoundNetLog& net_log);
@@ -48,7 +49,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandler {
// authentication scheme, but none of the tokens occurring after the
// authentication scheme.
virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) = 0;
+ HttpAuthChallengeTokenizer* challenge) = 0;
// Generates an authentication token, potentially asynchronously.
//
@@ -151,7 +152,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandler {
// authentication scheme.
// Implementations are expected to initialize the following members:
// scheme_, realm_, score_, properties_
- virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) = 0;
+ virtual bool Init(HttpAuthChallengeTokenizer* challenge) = 0;
// |GenerateAuthTokenImpl()} is the auth-scheme specific implementation
// of generating the next auth token. Callers should use |GenerateAuthToken()|
diff --git a/chromium/net/http/http_auth_handler_basic.cc b/chromium/net/http/http_auth_handler_basic.cc
index e445c93100c..48371389d1a 100644
--- a/chromium/net/http/http_auth_handler_basic.cc
+++ b/chromium/net/http/http_auth_handler_basic.cc
@@ -7,11 +7,12 @@
#include <string>
#include "base/base64.h"
-#include "base/i18n/icu_string_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
+#include "net/base/net_string_util.h"
#include "net/http/http_auth.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
namespace net {
@@ -33,7 +34,7 @@ namespace {
//
// TODO(cbentzel): Realm may need to be decoded using RFC 2047 rules as
// well, see http://crbug.com/25790.
-bool ParseRealm(const HttpAuth::ChallengeTokenizer& tokenizer,
+bool ParseRealm(const HttpAuthChallengeTokenizer& tokenizer,
std::string* realm) {
CHECK(realm);
realm->clear();
@@ -42,16 +43,17 @@ bool ParseRealm(const HttpAuth::ChallengeTokenizer& tokenizer,
if (!LowerCaseEqualsASCII(parameters.name(), "realm"))
continue;
- if (!base::ConvertToUtf8AndNormalize(
- parameters.value(), base::kCodepageLatin1, realm))
+ if (!net::ConvertToUtf8AndNormalize(parameters.value(), kCharsetLatin1,
+ realm)) {
return false;
+ }
}
return parameters.valid();
}
} // namespace
-bool HttpAuthHandlerBasic::Init(HttpAuth::ChallengeTokenizer* challenge) {
+bool HttpAuthHandlerBasic::Init(HttpAuthChallengeTokenizer* challenge) {
auth_scheme_ = HttpAuth::AUTH_SCHEME_BASIC;
score_ = 1;
properties_ = 0;
@@ -59,7 +61,7 @@ bool HttpAuthHandlerBasic::Init(HttpAuth::ChallengeTokenizer* challenge) {
}
bool HttpAuthHandlerBasic::ParseChallenge(
- HttpAuth::ChallengeTokenizer* challenge) {
+ HttpAuthChallengeTokenizer* challenge) {
// Verify the challenge's auth-scheme.
if (!LowerCaseEqualsASCII(challenge->scheme(), "basic"))
return false;
@@ -73,7 +75,7 @@ bool HttpAuthHandlerBasic::ParseChallenge(
}
HttpAuth::AuthorizationResult HttpAuthHandlerBasic::HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) {
+ HttpAuthChallengeTokenizer* challenge) {
// Basic authentication is always a single round, so any responses
// should be treated as a rejection. However, if the new challenge
// is for a different realm, then indicate the realm change.
@@ -91,8 +93,8 @@ int HttpAuthHandlerBasic::GenerateAuthTokenImpl(
DCHECK(credentials);
// TODO(eroman): is this the right encoding of username/password?
std::string base64_username_password;
- base::Base64Encode(UTF16ToUTF8(credentials->username()) + ":" +
- UTF16ToUTF8(credentials->password()),
+ base::Base64Encode(base::UTF16ToUTF8(credentials->username()) + ":" +
+ base::UTF16ToUTF8(credentials->password()),
&base64_username_password);
*auth_token = "Basic " + base64_username_password;
return OK;
@@ -105,7 +107,7 @@ HttpAuthHandlerBasic::Factory::~Factory() {
}
int HttpAuthHandlerBasic::Factory::CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
diff --git a/chromium/net/http/http_auth_handler_basic.h b/chromium/net/http/http_auth_handler_basic.h
index ce56152b09f..5d786f9de86 100644
--- a/chromium/net/http/http_auth_handler_basic.h
+++ b/chromium/net/http/http_auth_handler_basic.h
@@ -22,7 +22,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerBasic : public HttpAuthHandler {
virtual ~Factory();
virtual int CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
@@ -32,10 +32,10 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerBasic : public HttpAuthHandler {
};
virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) OVERRIDE;
+ HttpAuthChallengeTokenizer* challenge) OVERRIDE;
protected:
- virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) OVERRIDE;
+ virtual bool Init(HttpAuthChallengeTokenizer* challenge) OVERRIDE;
virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
const HttpRequestInfo* request,
@@ -45,7 +45,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerBasic : public HttpAuthHandler {
private:
virtual ~HttpAuthHandlerBasic() {}
- bool ParseChallenge(HttpAuth::ChallengeTokenizer* challenge);
+ bool ParseChallenge(HttpAuthChallengeTokenizer* challenge);
};
} // namespace net
diff --git a/chromium/net/http/http_auth_handler_basic_unittest.cc b/chromium/net/http/http_auth_handler_basic_unittest.cc
index 5e05b76d8b5..6f112b1b32f 100644
--- a/chromium/net/http/http_auth_handler_basic_unittest.cc
+++ b/chromium/net/http/http_auth_handler_basic_unittest.cc
@@ -9,6 +9,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_handler_basic.h"
#include "net/http/http_request_info.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -36,8 +37,8 @@ TEST(HttpAuthHandlerBasicTest, GenerateAuthToken) {
scoped_ptr<HttpAuthHandler> basic;
EXPECT_EQ(OK, factory.CreateAuthHandlerFromString(
challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(), &basic));
- AuthCredentials credentials(ASCIIToUTF16(tests[i].username),
- ASCIIToUTF16(tests[i].password));
+ AuthCredentials credentials(base::ASCIIToUTF16(tests[i].username),
+ base::ASCIIToUTF16(tests[i].password));
HttpRequestInfo request_info;
std::string auth_token;
int rv = basic->GenerateAuthToken(&credentials, &request_info,
@@ -91,8 +92,8 @@ TEST(HttpAuthHandlerBasicTest, HandleAnotherChallenge) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
std::string challenge(tests[i].challenge);
- HttpAuth::ChallengeTokenizer tok(challenge.begin(),
- challenge.end());
+ HttpAuthChallengeTokenizer tok(challenge.begin(),
+ challenge.end());
EXPECT_EQ(tests[i].expected_rv, basic->HandleAnotherChallenge(&tok));
}
}
diff --git a/chromium/net/http/http_auth_handler_digest.cc b/chromium/net/http/http_auth_handler_digest.cc
index a8e301a02e8..7dee081ddbe 100644
--- a/chromium/net/http/http_auth_handler_digest.cc
+++ b/chromium/net/http/http_auth_handler_digest.cc
@@ -6,7 +6,6 @@
#include <string>
-#include "base/i18n/icu_string_conversions.h"
#include "base/logging.h"
#include "base/md5.h"
#include "base/rand_util.h"
@@ -14,8 +13,10 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
+#include "net/base/net_string_util.h"
#include "net/base/net_util.h"
#include "net/http/http_auth.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_request_info.h"
#include "net/http/http_util.h"
#include "url/gurl.h"
@@ -89,7 +90,7 @@ void HttpAuthHandlerDigest::Factory::set_nonce_generator(
}
int HttpAuthHandlerDigest::Factory::CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
@@ -107,7 +108,7 @@ int HttpAuthHandlerDigest::Factory::CreateAuthHandler(
}
HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) {
+ HttpAuthChallengeTokenizer* challenge) {
// Even though Digest is not connection based, a "second round" is parsed
// to differentiate between stale and rejected responses.
// Note that the state of the current handler is not mutated - this way if
@@ -133,7 +134,7 @@ HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
HttpAuth::AUTHORIZATION_RESULT_REJECT;
}
-bool HttpAuthHandlerDigest::Init(HttpAuth::ChallengeTokenizer* challenge) {
+bool HttpAuthHandlerDigest::Init(HttpAuthChallengeTokenizer* challenge) {
return ParseChallenge(challenge);
}
@@ -186,7 +187,7 @@ HttpAuthHandlerDigest::~HttpAuthHandlerDigest() {
// send the realm (See http://crbug.com/20984 for an instance where a
// webserver was not sending the realm with a BASIC challenge).
bool HttpAuthHandlerDigest::ParseChallenge(
- HttpAuth::ChallengeTokenizer* challenge) {
+ HttpAuthChallengeTokenizer* challenge) {
auth_scheme_ = HttpAuth::AUTH_SCHEME_DIGEST;
score_ = 2;
properties_ = ENCRYPTS_IDENTITY;
@@ -226,7 +227,7 @@ bool HttpAuthHandlerDigest::ParseChallengeProperty(const std::string& name,
const std::string& value) {
if (LowerCaseEqualsASCII(name, "realm")) {
std::string realm;
- if (!base::ConvertToUtf8AndNormalize(value, base::kCodepageLatin1, &realm))
+ if (!net::ConvertToUtf8AndNormalize(value, kCharsetLatin1, &realm))
return false;
realm_ = realm;
original_realm_ = value;
@@ -322,9 +323,9 @@ std::string HttpAuthHandlerDigest::AssembleResponseDigest(
const std::string& nc) const {
// ha1 = MD5(A1)
// TODO(eroman): is this the right encoding?
- std::string ha1 = base::MD5String(UTF16ToUTF8(credentials.username()) + ":" +
- original_realm_ + ":" +
- UTF16ToUTF8(credentials.password()));
+ std::string ha1 = base::MD5String(base::UTF16ToUTF8(credentials.username()) +
+ ":" + original_realm_ + ":" +
+ base::UTF16ToUTF8(credentials.password()));
if (algorithm_ == HttpAuthHandlerDigest::ALGORITHM_MD5_SESS)
ha1 = base::MD5String(ha1 + ":" + nonce_ + ":" + cnonce);
@@ -352,7 +353,7 @@ std::string HttpAuthHandlerDigest::AssembleCredentials(
// TODO(eroman): is this the right encoding?
std::string authorization = (std::string("Digest username=") +
HttpUtil::Quote(
- UTF16ToUTF8(credentials.username())));
+ base::UTF16ToUTF8(credentials.username())));
authorization += ", realm=" + HttpUtil::Quote(original_realm_);
authorization += ", nonce=" + HttpUtil::Quote(nonce_);
authorization += ", uri=" + HttpUtil::Quote(path);
diff --git a/chromium/net/http/http_auth_handler_digest.h b/chromium/net/http/http_auth_handler_digest.h
index 7edac166c6d..6a960d9cba7 100644
--- a/chromium/net/http/http_auth_handler_digest.h
+++ b/chromium/net/http/http_auth_handler_digest.h
@@ -65,7 +65,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerDigest : public HttpAuthHandler {
void set_nonce_generator(const NonceGenerator* nonce_generator);
virtual int CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
@@ -78,10 +78,10 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerDigest : public HttpAuthHandler {
};
virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) OVERRIDE;
+ HttpAuthChallengeTokenizer* challenge) OVERRIDE;
protected:
- virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) OVERRIDE;
+ virtual bool Init(HttpAuthChallengeTokenizer* challenge) OVERRIDE;
virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
const HttpRequestInfo* request,
@@ -124,7 +124,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerDigest : public HttpAuthHandler {
// Parse the challenge, saving the results into this instance.
// Returns true on success.
- bool ParseChallenge(HttpAuth::ChallengeTokenizer* challenge);
+ bool ParseChallenge(HttpAuthChallengeTokenizer* challenge);
// Parse an individual property. Returns true on success.
bool ParseChallengeProperty(const std::string& name,
diff --git a/chromium/net/http/http_auth_handler_digest_unittest.cc b/chromium/net/http/http_auth_handler_digest_unittest.cc
index dee44ebd5d0..5c3941c9efe 100644
--- a/chromium/net/http/http_auth_handler_digest_unittest.cc
+++ b/chromium/net/http/http_auth_handler_digest_unittest.cc
@@ -9,6 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_handler_digest.h"
#include "net/http/http_request_info.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -67,7 +68,8 @@ bool RespondToChallenge(HttpAuth::Target target,
TestCompletionCallback callback;
scoped_ptr<HttpRequestInfo> request(new HttpRequestInfo());
request->url = GURL(request_url);
- AuthCredentials credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
+ AuthCredentials credentials(base::ASCIIToUTF16("foo"),
+ base::ASCIIToUTF16("bar"));
int rv_generate = handler->GenerateAuthToken(
&credentials, request.get(), callback.callback(), token);
if (rv_generate != OK) {
@@ -530,8 +532,8 @@ TEST(HttpAuthHandlerDigestTest, AssembleCredentials) {
digest->AssembleCredentials(tests[i].req_method,
tests[i].req_path,
AuthCredentials(
- ASCIIToUTF16(tests[i].username),
- ASCIIToUTF16(tests[i].password)),
+ base::ASCIIToUTF16(tests[i].username),
+ base::ASCIIToUTF16(tests[i].password)),
tests[i].cnonce,
tests[i].nonce_count);
@@ -551,27 +553,27 @@ TEST(HttpAuthHandlerDigest, HandleAnotherChallenge) {
&handler);
EXPECT_EQ(OK, rv);
ASSERT_TRUE(handler.get() != NULL);
- HttpAuth::ChallengeTokenizer tok_default(default_challenge.begin(),
- default_challenge.end());
+ HttpAuthChallengeTokenizer tok_default(default_challenge.begin(),
+ default_challenge.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT,
handler->HandleAnotherChallenge(&tok_default));
std::string stale_challenge = default_challenge + ", stale=true";
- HttpAuth::ChallengeTokenizer tok_stale(stale_challenge.begin(),
- stale_challenge.end());
+ HttpAuthChallengeTokenizer tok_stale(stale_challenge.begin(),
+ stale_challenge.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_STALE,
handler->HandleAnotherChallenge(&tok_stale));
std::string stale_false_challenge = default_challenge + ", stale=false";
- HttpAuth::ChallengeTokenizer tok_stale_false(stale_false_challenge.begin(),
- stale_false_challenge.end());
+ HttpAuthChallengeTokenizer tok_stale_false(stale_false_challenge.begin(),
+ stale_false_challenge.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT,
handler->HandleAnotherChallenge(&tok_stale_false));
std::string realm_change_challenge =
"Digest realm=\"SomethingElse\", nonce=\"nonce-value2\"";
- HttpAuth::ChallengeTokenizer tok_realm_change(realm_change_challenge.begin(),
- realm_change_challenge.end());
+ HttpAuthChallengeTokenizer tok_realm_change(realm_change_challenge.begin(),
+ realm_change_challenge.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM,
handler->HandleAnotherChallenge(&tok_realm_change));
}
diff --git a/chromium/net/http/http_auth_handler_factory.cc b/chromium/net/http/http_auth_handler_factory.cc
index f94bd33d666..9867bb99c1b 100644
--- a/chromium/net/http/http_auth_handler_factory.cc
+++ b/chromium/net/http/http_auth_handler_factory.cc
@@ -7,6 +7,7 @@
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "net/base/net_errors.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_filter.h"
#include "net/http/http_auth_handler_basic.h"
#include "net/http/http_auth_handler_digest.h"
@@ -24,7 +25,7 @@ int HttpAuthHandlerFactory::CreateAuthHandlerFromString(
const GURL& origin,
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler) {
- HttpAuth::ChallengeTokenizer props(challenge.begin(), challenge.end());
+ HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
return CreateAuthHandler(&props, target, origin, CREATE_CHALLENGE, 1,
net_log, handler);
}
@@ -36,7 +37,7 @@ int HttpAuthHandlerFactory::CreatePreemptiveAuthHandlerFromString(
int digest_nonce_count,
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler) {
- HttpAuth::ChallengeTokenizer props(challenge.begin(), challenge.end());
+ HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
return CreateAuthHandler(&props, target, origin, CREATE_PREEMPTIVE,
digest_nonce_count, net_log, handler);
}
@@ -172,7 +173,7 @@ HttpAuthHandlerRegistryFactory* HttpAuthHandlerRegistryFactory::Create(
}
int HttpAuthHandlerRegistryFactory::CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
diff --git a/chromium/net/http/http_auth_handler_factory.h b/chromium/net/http/http_auth_handler_factory.h
index 27627514979..e712aafcb0a 100644
--- a/chromium/net/http/http_auth_handler_factory.h
+++ b/chromium/net/http/http_auth_handler_factory.h
@@ -20,6 +20,7 @@ namespace net {
class BoundNetLog;
class HostResolver;
+class HttpAuthChallengeTokenizer;
class HttpAuthHandler;
class HttpAuthHandlerRegistryFactory;
@@ -73,7 +74,7 @@ class NET_EXPORT HttpAuthHandlerFactory {
// NOTE: This will apply to ALL |origin| values if the filters are empty.
//
// |*challenge| should not be reused after a call to |CreateAuthHandler()|,
- virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
+ virtual int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason create_reason,
@@ -182,7 +183,7 @@ class NET_EXPORT HttpAuthHandlerRegistryFactory
// Creates an auth handler by dispatching out to the registered factories
// based on the first token in |challenge|.
- virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
+ virtual int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
diff --git a/chromium/net/http/http_auth_handler_factory_unittest.cc b/chromium/net/http/http_auth_handler_factory_unittest.cc
index 8e69919c0bf..06e8933f25a 100644
--- a/chromium/net/http/http_auth_handler_factory_unittest.cc
+++ b/chromium/net/http/http_auth_handler_factory_unittest.cc
@@ -21,7 +21,7 @@ class MockHttpAuthHandlerFactory : public HttpAuthHandlerFactory {
return_code_(return_code) {}
virtual ~MockHttpAuthHandlerFactory() {}
- virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
+ virtual int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
diff --git a/chromium/net/http/http_auth_handler_mock.cc b/chromium/net/http/http_auth_handler_mock.cc
index 826c3d6a12b..52990eef923 100644
--- a/chromium/net/http/http_auth_handler_mock.cc
+++ b/chromium/net/http/http_auth_handler_mock.cc
@@ -8,6 +8,7 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "net/base/net_errors.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_request_info.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -77,7 +78,7 @@ void HttpAuthHandlerMock::SetGenerateExpectation(bool async, int rv) {
}
HttpAuth::AuthorizationResult HttpAuthHandlerMock::HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) {
+ HttpAuthChallengeTokenizer* challenge) {
// If we receive an empty challenge for a connection based scheme, or a second
// challenge for a non connection based scheme, assume it's a rejection.
if (!is_connection_based() || challenge->base64_param().empty())
@@ -99,7 +100,7 @@ bool HttpAuthHandlerMock::AllowsExplicitCredentials() {
return allows_explicit_credentials_;
}
-bool HttpAuthHandlerMock::Init(HttpAuth::ChallengeTokenizer* challenge) {
+bool HttpAuthHandlerMock::Init(HttpAuthChallengeTokenizer* challenge) {
auth_scheme_ = HttpAuth::AUTH_SCHEME_MOCK;
score_ = 1;
properties_ = connection_based_ ? IS_CONNECTION_BASED : 0;
@@ -164,7 +165,7 @@ void HttpAuthHandlerMock::Factory::AddMockHandler(
}
int HttpAuthHandlerMock::Factory::CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
diff --git a/chromium/net/http/http_auth_handler_mock.h b/chromium/net/http/http_auth_handler_mock.h
index 7cc441a70cc..a4642dfe0f0 100644
--- a/chromium/net/http/http_auth_handler_mock.h
+++ b/chromium/net/http/http_auth_handler_mock.h
@@ -43,7 +43,7 @@ class HttpAuthHandlerMock : public HttpAuthHandler {
// HttpAuthHandlerFactory:
virtual int CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
@@ -88,13 +88,13 @@ class HttpAuthHandlerMock : public HttpAuthHandler {
// HttpAuthHandler:
virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) OVERRIDE;
+ HttpAuthChallengeTokenizer* challenge) OVERRIDE;
virtual bool NeedsIdentity() OVERRIDE;
virtual bool AllowsDefaultCredentials() OVERRIDE;
virtual bool AllowsExplicitCredentials() OVERRIDE;
protected:
- virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) OVERRIDE;
+ virtual bool Init(HttpAuthChallengeTokenizer* challenge) OVERRIDE;
virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
const HttpRequestInfo* request,
diff --git a/chromium/net/http/http_auth_handler_negotiate.cc b/chromium/net/http/http_auth_handler_negotiate.cc
index 788b06750b6..422ddd729a2 100644
--- a/chromium/net/http/http_auth_handler_negotiate.cc
+++ b/chromium/net/http/http_auth_handler_negotiate.cc
@@ -37,7 +37,7 @@ void HttpAuthHandlerNegotiate::Factory::set_host_resolver(
}
int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
@@ -161,7 +161,7 @@ std::string HttpAuthHandlerNegotiate::CreateSPN(
}
HttpAuth::AuthorizationResult HttpAuthHandlerNegotiate::HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) {
+ HttpAuthChallengeTokenizer* challenge) {
return auth_system_.ParseChallenge(challenge);
}
@@ -184,7 +184,7 @@ bool HttpAuthHandlerNegotiate::AllowsExplicitCredentials() {
// The Negotiate challenge header looks like:
// WWW-Authenticate: NEGOTIATE auth-data
-bool HttpAuthHandlerNegotiate::Init(HttpAuth::ChallengeTokenizer* challenge) {
+bool HttpAuthHandlerNegotiate::Init(HttpAuthChallengeTokenizer* challenge) {
#if defined(OS_POSIX)
if (!auth_system_.Init()) {
VLOG(1) << "can't initialize GSSAPI library";
diff --git a/chromium/net/http/http_auth_handler_negotiate.h b/chromium/net/http/http_auth_handler_negotiate.h
index d028178ed51..90bd16ce958 100644
--- a/chromium/net/http/http_auth_handler_negotiate.h
+++ b/chromium/net/http/http_auth_handler_negotiate.h
@@ -70,7 +70,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler {
}
virtual int CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
@@ -107,13 +107,13 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler {
// HttpAuthHandler:
virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) OVERRIDE;
+ HttpAuthChallengeTokenizer* challenge) OVERRIDE;
virtual bool NeedsIdentity() OVERRIDE;
virtual bool AllowsDefaultCredentials() OVERRIDE;
virtual bool AllowsExplicitCredentials() OVERRIDE;
protected:
- virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) OVERRIDE;
+ virtual bool Init(HttpAuthChallengeTokenizer* challenge) OVERRIDE;
virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
const HttpRequestInfo* request,
diff --git a/chromium/net/http/http_auth_handler_ntlm.cc b/chromium/net/http/http_auth_handler_ntlm.cc
index 922800c71e1..de0fe290a3c 100644
--- a/chromium/net/http/http_auth_handler_ntlm.cc
+++ b/chromium/net/http/http_auth_handler_ntlm.cc
@@ -12,15 +12,16 @@
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
namespace net {
HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) {
+ HttpAuthChallengeTokenizer* challenge) {
return ParseChallenge(challenge, false);
}
-bool HttpAuthHandlerNTLM::Init(HttpAuth::ChallengeTokenizer* tok) {
+bool HttpAuthHandlerNTLM::Init(HttpAuthChallengeTokenizer* tok) {
auth_scheme_ = HttpAuth::AUTH_SCHEME_NTLM;
score_ = 3;
properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
@@ -100,7 +101,7 @@ int HttpAuthHandlerNTLM::GenerateAuthTokenImpl(
// The NTLM challenge header looks like:
// WWW-Authenticate: NTLM auth-data
HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::ParseChallenge(
- HttpAuth::ChallengeTokenizer* tok, bool initial_challenge) {
+ HttpAuthChallengeTokenizer* tok, bool initial_challenge) {
#if defined(NTLM_SSPI)
// auth_sspi_ contains state for whether or not this is the initial challenge.
return auth_sspi_.ParseChallenge(tok);
diff --git a/chromium/net/http/http_auth_handler_ntlm.h b/chromium/net/http/http_auth_handler_ntlm.h
index 98bd362d543..9e2abc6254a 100644
--- a/chromium/net/http/http_auth_handler_ntlm.h
+++ b/chromium/net/http/http_auth_handler_ntlm.h
@@ -42,7 +42,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler {
virtual ~Factory();
virtual int CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
@@ -109,14 +109,14 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler {
virtual bool AllowsDefaultCredentials() OVERRIDE;
virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
- HttpAuth::ChallengeTokenizer* challenge) OVERRIDE;
+ HttpAuthChallengeTokenizer* challenge) OVERRIDE;
protected:
// This function acquires a credentials handle in the SSPI implementation.
// It does nothing in the portable implementation.
int InitializeBeforeFirstChallenge();
- virtual bool Init(HttpAuth::ChallengeTokenizer* tok) OVERRIDE;
+ virtual bool Init(HttpAuthChallengeTokenizer* tok) OVERRIDE;
virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
const HttpRequestInfo* request,
@@ -135,7 +135,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler {
// Parse the challenge, saving the results into this instance.
HttpAuth::AuthorizationResult ParseChallenge(
- HttpAuth::ChallengeTokenizer* tok, bool initial_challenge);
+ HttpAuthChallengeTokenizer* tok, bool initial_challenge);
// Given an input token received from the server, generate the next output
// token to be sent to the server.
diff --git a/chromium/net/http/http_auth_handler_ntlm_portable.cc b/chromium/net/http/http_auth_handler_ntlm_portable.cc
index d1fbf23c59f..035a6dc8017 100644
--- a/chromium/net/http/http_auth_handler_ntlm_portable.cc
+++ b/chromium/net/http/http_auth_handler_ntlm_portable.cc
@@ -70,12 +70,10 @@ namespace net {
*
* ***** END LICENSE BLOCK ***** */
-// Discover the endianness by testing processor architecture.
-#if defined(ARCH_CPU_X86) || defined(ARCH_CPU_X86_64)\
- || defined(ARCH_CPU_ARMEL) || defined(ARCH_CPU_MIPSEL)
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
#define IS_LITTLE_ENDIAN 1
#undef IS_BIG_ENDIAN
-#elif defined(ARCH_CPU_MIPSEB)
+#elif defined(ARCH_CPU_BIG_ENDIAN)
#define IS_BIG_ENDIAN 1
#undef IS_LITTLE_ENDIAN
#else
@@ -211,7 +209,8 @@ static void* WriteSecBuf(void* buf, uint16 length, uint32 offset) {
* to pass the same buffer as both input and output, which is a handy way to
* convert the unicode buffer to little-endian on big-endian platforms.
*/
-static void* WriteUnicodeLE(void* buf, const char16* str, uint32 str_len) {
+static void* WriteUnicodeLE(
+ void* buf, const base::char16* str, uint32 str_len) {
// Convert input string from BE to LE.
uint8* cursor = static_cast<uint8*>(buf);
const uint8* input = reinterpret_cast<const uint8*>(str);
@@ -257,7 +256,7 @@ static void LM_Hash(const base::string16& password, uint8* hash) {
// Convert password to OEM character set. We'll just use the native
// filesystem charset.
- std::string passbuf = base::SysWideToNativeMB(UTF16ToWide(password));
+ std::string passbuf = base::SysWideToNativeMB(base::UTF16ToWide(password));
StringToUpperASCII(&passbuf);
passbuf.resize(14, '\0');
@@ -480,14 +479,15 @@ static int GenerateType3Msg(const base::string16& domain,
ucs_domain_buf = domain;
domain_ptr = ucs_domain_buf.data();
domain_len = ucs_domain_buf.length() * 2;
- WriteUnicodeLE(const_cast<void*>(domain_ptr), (const char16*) domain_ptr,
+ WriteUnicodeLE(const_cast<void*>(domain_ptr),
+ (const base::char16*) domain_ptr,
ucs_domain_buf.length());
#else
domain_ptr = domain.data();
domain_len = domain.length() * 2;
#endif
} else {
- oem_domain_buf = base::SysWideToNativeMB(UTF16ToWide(domain));
+ oem_domain_buf = base::SysWideToNativeMB(base::UTF16ToWide(domain));
domain_ptr = oem_domain_buf.data();
domain_len = oem_domain_buf.length();
}
@@ -500,14 +500,14 @@ static int GenerateType3Msg(const base::string16& domain,
ucs_user_buf = username;
user_ptr = ucs_user_buf.data();
user_len = ucs_user_buf.length() * 2;
- WriteUnicodeLE(const_cast<void*>(user_ptr), (const char16*) user_ptr,
+ WriteUnicodeLE(const_cast<void*>(user_ptr), (const base::char16*) user_ptr,
ucs_user_buf.length());
#else
user_ptr = username.data();
user_len = username.length() * 2;
#endif
} else {
- oem_user_buf = base::SysWideToNativeMB(UTF16ToWide(username));
+ oem_user_buf = base::SysWideToNativeMB(base::UTF16ToWide(username));
user_ptr = oem_user_buf.data();
user_len = oem_user_buf.length();
}
@@ -521,7 +521,7 @@ static int GenerateType3Msg(const base::string16& domain,
host_ptr = ucs_host_buf.data();
host_len = ucs_host_buf.length() * 2;
#ifdef IS_BIG_ENDIAN
- WriteUnicodeLE(const_cast<void*>(host_ptr), (const char16*) host_ptr,
+ WriteUnicodeLE(const_cast<void*>(host_ptr), (const base::char16*) host_ptr,
ucs_host_buf.length());
#endif
} else {
@@ -707,7 +707,7 @@ int HttpAuthHandlerNTLM::GetNextToken(const void* in_token,
}
int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
diff --git a/chromium/net/http/http_auth_handler_ntlm_win.cc b/chromium/net/http/http_auth_handler_ntlm_win.cc
index 041522f79e6..acc6fc15e2e 100644
--- a/chromium/net/http/http_auth_handler_ntlm_win.cc
+++ b/chromium/net/http/http_auth_handler_ntlm_win.cc
@@ -52,7 +52,7 @@ HttpAuthHandlerNTLM::Factory::~Factory() {
}
int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
- HttpAuth::ChallengeTokenizer* challenge,
+ HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
diff --git a/chromium/net/http/http_auth_handler_unittest.cc b/chromium/net/http/http_auth_handler_unittest.cc
index f8928fcc428..a53573d6b47 100644
--- a/chromium/net/http/http_auth_handler_unittest.cc
+++ b/chromium/net/http/http_auth_handler_unittest.cc
@@ -10,6 +10,7 @@
#include "net/base/net_errors.h"
#include "net/base/net_log_unittest.h"
#include "net/base/test_completion_callback.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_handler_mock.h"
#include "net/http/http_request_info.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -19,7 +20,8 @@ namespace net {
TEST(HttpAuthHandlerTest, NetLog) {
GURL origin("http://www.example.com");
std::string challenge = "Mock asdf";
- AuthCredentials credentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass"));
+ AuthCredentials credentials(base::ASCIIToUTF16("user"),
+ base::ASCIIToUTF16("pass"));
std::string auth_token;
HttpRequestInfo request;
@@ -33,7 +35,7 @@ TEST(HttpAuthHandlerTest, NetLog) {
(k == 0) ? HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
NetLog::EventType event_type =
(k == 0) ? NetLog::TYPE_AUTH_PROXY : NetLog::TYPE_AUTH_SERVER;
- HttpAuth::ChallengeTokenizer tokenizer(
+ HttpAuthChallengeTokenizer tokenizer(
challenge.begin(), challenge.end());
HttpAuthHandlerMock mock_handler;
CapturingNetLog capturing_net_log;
diff --git a/chromium/net/http/http_auth_sspi_win.cc b/chromium/net/http/http_auth_sspi_win.cc
index 5718f9ef753..8a0e49fff11 100644
--- a/chromium/net/http/http_auth_sspi_win.cc
+++ b/chromium/net/http/http_auth_sspi_win.cc
@@ -13,6 +13,7 @@
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
#include "net/http/http_auth.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
namespace net {
@@ -226,7 +227,7 @@ void HttpAuthSSPI::ResetSecurityContext() {
}
HttpAuth::AuthorizationResult HttpAuthSSPI::ParseChallenge(
- HttpAuth::ChallengeTokenizer* tok) {
+ HttpAuthChallengeTokenizer* tok) {
// Verify the challenge's auth-scheme.
if (!LowerCaseEqualsASCII(tok->scheme(), StringToLowerASCII(scheme_).c_str()))
return HttpAuth::AUTHORIZATION_RESULT_INVALID;
diff --git a/chromium/net/http/http_auth_sspi_win.h b/chromium/net/http/http_auth_sspi_win.h
index bc7da46c312..dd0b1772b16 100644
--- a/chromium/net/http/http_auth_sspi_win.h
+++ b/chromium/net/http/http_auth_sspi_win.h
@@ -22,6 +22,8 @@
namespace net {
+class HttpAuthChallengeTokenizer;
+
// SSPILibrary is introduced so unit tests can mock the calls to Windows' SSPI
// implementation. The default implementation simply passes the arguments on to
// the SSPI implementation provided by Secur32.dll.
@@ -134,7 +136,7 @@ class NET_EXPORT_PRIVATE HttpAuthSSPI {
bool AllowsExplicitCredentials() const;
HttpAuth::AuthorizationResult ParseChallenge(
- HttpAuth::ChallengeTokenizer* tok);
+ HttpAuthChallengeTokenizer* tok);
// Generates an authentication token for the service specified by the
// Service Principal Name |spn| and stores the value in |*auth_token|.
diff --git a/chromium/net/http/http_auth_sspi_win_unittest.cc b/chromium/net/http/http_auth_sspi_win_unittest.cc
index 09fe6fa25ef..586822d2ef7 100644
--- a/chromium/net/http/http_auth_sspi_win_unittest.cc
+++ b/chromium/net/http/http_auth_sspi_win_unittest.cc
@@ -4,6 +4,7 @@
#include "base/basictypes.h"
#include "net/base/net_errors.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_sspi_win.h"
#include "net/http/mock_sspi_library_win.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -62,8 +63,8 @@ TEST(HttpAuthSSPITest, ParseChallenge_FirstRound) {
HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
NEGOSSP_NAME, kMaxTokenLength);
std::string challenge_text = "Negotiate";
- HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
- challenge_text.end());
+ HttpAuthChallengeTokenizer challenge(challenge_text.begin(),
+ challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
auth_sspi.ParseChallenge(&challenge));
}
@@ -75,8 +76,8 @@ TEST(HttpAuthSSPITest, ParseChallenge_TwoRounds) {
HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
NEGOSSP_NAME, kMaxTokenLength);
std::string first_challenge_text = "Negotiate";
- HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(),
- first_challenge_text.end());
+ HttpAuthChallengeTokenizer first_challenge(first_challenge_text.begin(),
+ first_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
auth_sspi.ParseChallenge(&first_challenge));
@@ -86,8 +87,8 @@ TEST(HttpAuthSSPITest, ParseChallenge_TwoRounds) {
&auth_token));
std::string second_challenge_text = "Negotiate Zm9vYmFy";
- HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
- second_challenge_text.end());
+ HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
+ second_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
auth_sspi.ParseChallenge(&second_challenge));
}
@@ -99,8 +100,8 @@ TEST(HttpAuthSSPITest, ParseChallenge_UnexpectedTokenFirstRound) {
HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
NEGOSSP_NAME, kMaxTokenLength);
std::string challenge_text = "Negotiate Zm9vYmFy";
- HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
- challenge_text.end());
+ HttpAuthChallengeTokenizer challenge(challenge_text.begin(),
+ challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID,
auth_sspi.ParseChallenge(&challenge));
}
@@ -112,8 +113,8 @@ TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) {
HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
NEGOSSP_NAME, kMaxTokenLength);
std::string first_challenge_text = "Negotiate";
- HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(),
- first_challenge_text.end());
+ HttpAuthChallengeTokenizer first_challenge(first_challenge_text.begin(),
+ first_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
auth_sspi.ParseChallenge(&first_challenge));
@@ -121,8 +122,8 @@ TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) {
EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
&auth_token));
std::string second_challenge_text = "Negotiate";
- HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
- second_challenge_text.end());
+ HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
+ second_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT,
auth_sspi.ParseChallenge(&second_challenge));
}
@@ -134,8 +135,8 @@ TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) {
HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
NEGOSSP_NAME, kMaxTokenLength);
std::string first_challenge_text = "Negotiate";
- HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(),
- first_challenge_text.end());
+ HttpAuthChallengeTokenizer first_challenge(first_challenge_text.begin(),
+ first_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
auth_sspi.ParseChallenge(&first_challenge));
@@ -143,8 +144,8 @@ TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) {
EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
&auth_token));
std::string second_challenge_text = "Negotiate =happyjoy=";
- HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
- second_challenge_text.end());
+ HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
+ second_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID,
auth_sspi.ParseChallenge(&second_challenge));
}
diff --git a/chromium/net/http/http_auth_unittest.cc b/chromium/net/http/http_auth_unittest.cc
index 6f1471d472a..cf68fa8039d 100644
--- a/chromium/net/http/http_auth_unittest.cc
+++ b/chromium/net/http/http_auth_unittest.cc
@@ -11,6 +11,7 @@
#include "net/base/net_errors.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_auth.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_filter.h"
#include "net/http/http_auth_handler.h"
#include "net/http/http_auth_handler_factory.h"
@@ -28,7 +29,7 @@ HttpAuthHandlerMock* CreateMockHandler(bool connection_based) {
HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
auth_handler->set_connection_based(connection_based);
std::string challenge_text = "Basic";
- HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
+ HttpAuthChallengeTokenizer challenge(challenge_text.begin(),
challenge_text.end());
GURL origin("www.example.com");
EXPECT_TRUE(auth_handler->InitFromChallenge(&challenge,
@@ -245,173 +246,6 @@ TEST(HttpAuthTest, HandleChallengeResponse) {
EXPECT_EQ("Mock token_a", challenge_used);
}
-TEST(HttpAuthTest, ChallengeTokenizer) {
- std::string challenge_str = "Basic realm=\"foobar\"";
- HttpAuth::ChallengeTokenizer challenge(challenge_str.begin(),
- challenge_str.end());
- HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
-
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("Basic"), challenge.scheme());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("realm"), parameters.name());
- EXPECT_EQ(std::string("foobar"), parameters.value());
- EXPECT_FALSE(parameters.GetNext());
-}
-
-// Use a name=value property with no quote marks.
-TEST(HttpAuthTest, ChallengeTokenizerNoQuotes) {
- std::string challenge_str = "Basic realm=foobar@baz.com";
- HttpAuth::ChallengeTokenizer challenge(challenge_str.begin(),
- challenge_str.end());
- HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
-
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("Basic"), challenge.scheme());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("realm"), parameters.name());
- EXPECT_EQ(std::string("foobar@baz.com"), parameters.value());
- EXPECT_FALSE(parameters.GetNext());
-}
-
-// Use a name=value property with mismatching quote marks.
-TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotes) {
- std::string challenge_str = "Basic realm=\"foobar@baz.com";
- HttpAuth::ChallengeTokenizer challenge(challenge_str.begin(),
- challenge_str.end());
- HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
-
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("Basic"), challenge.scheme());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("realm"), parameters.name());
- EXPECT_EQ(std::string("foobar@baz.com"), parameters.value());
- EXPECT_FALSE(parameters.GetNext());
-}
-
-// Use a name= property without a value and with mismatching quote marks.
-TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotesNoValue) {
- std::string challenge_str = "Basic realm=\"";
- HttpAuth::ChallengeTokenizer challenge(challenge_str.begin(),
- challenge_str.end());
- HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
-
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("Basic"), challenge.scheme());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("realm"), parameters.name());
- EXPECT_EQ(std::string(), parameters.value());
- EXPECT_FALSE(parameters.GetNext());
-}
-
-// Use a name=value property with mismatching quote marks and spaces in the
-// value.
-TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotesSpaces) {
- std::string challenge_str = "Basic realm=\"foo bar";
- HttpAuth::ChallengeTokenizer challenge(challenge_str.begin(),
- challenge_str.end());
- HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
-
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("Basic"), challenge.scheme());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("realm"), parameters.name());
- EXPECT_EQ(std::string("foo bar"), parameters.value());
- EXPECT_FALSE(parameters.GetNext());
-}
-
-// Use multiple name=value properties with mismatching quote marks in the last
-// value.
-TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotesMultiple) {
- std::string challenge_str = "Digest qop=auth-int, algorithm=md5, realm=\"foo";
- HttpAuth::ChallengeTokenizer challenge(challenge_str.begin(),
- challenge_str.end());
- HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
-
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("Digest"), challenge.scheme());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("qop"), parameters.name());
- EXPECT_EQ(std::string("auth-int"), parameters.value());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("algorithm"), parameters.name());
- EXPECT_EQ(std::string("md5"), parameters.value());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("realm"), parameters.name());
- EXPECT_EQ(std::string("foo"), parameters.value());
- EXPECT_FALSE(parameters.GetNext());
-}
-
-// Use a name= property which has no value.
-TEST(HttpAuthTest, ChallengeTokenizerNoValue) {
- std::string challenge_str = "Digest qop=";
- HttpAuth::ChallengeTokenizer challenge(
- challenge_str.begin(), challenge_str.end());
- HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
-
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("Digest"), challenge.scheme());
- EXPECT_FALSE(parameters.GetNext());
- EXPECT_FALSE(parameters.valid());
-}
-
-// Specify multiple properties, comma separated.
-TEST(HttpAuthTest, ChallengeTokenizerMultiple) {
- std::string challenge_str =
- "Digest algorithm=md5, realm=\"Oblivion\", qop=auth-int";
- HttpAuth::ChallengeTokenizer challenge(challenge_str.begin(),
- challenge_str.end());
- HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
-
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("Digest"), challenge.scheme());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("algorithm"), parameters.name());
- EXPECT_EQ(std::string("md5"), parameters.value());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("realm"), parameters.name());
- EXPECT_EQ(std::string("Oblivion"), parameters.value());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("qop"), parameters.name());
- EXPECT_EQ(std::string("auth-int"), parameters.value());
- EXPECT_FALSE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
-}
-
-// Use a challenge which has no property.
-TEST(HttpAuthTest, ChallengeTokenizerNoProperty) {
- std::string challenge_str = "NTLM";
- HttpAuth::ChallengeTokenizer challenge(
- challenge_str.begin(), challenge_str.end());
- HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
-
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("NTLM"), challenge.scheme());
- EXPECT_FALSE(parameters.GetNext());
-}
-
-// Use a challenge with Base64 encoded token.
-TEST(HttpAuthTest, ChallengeTokenizerBase64) {
- std::string challenge_str = "NTLM SGVsbG8sIFdvcmxkCg===";
- HttpAuth::ChallengeTokenizer challenge(challenge_str.begin(),
- challenge_str.end());
-
- EXPECT_EQ(std::string("NTLM"), challenge.scheme());
- // Notice the two equal statements below due to padding removal.
- EXPECT_EQ(std::string("SGVsbG8sIFdvcmxkCg=="), challenge.base64_param());
-}
-
TEST(HttpAuthTest, GetChallengeHeaderName) {
std::string name;
diff --git a/chromium/net/http/http_basic_stream.cc b/chromium/net/http/http_basic_stream.cc
index 87f6469ad61..0d14e0f9a0e 100644
--- a/chromium/net/http/http_basic_stream.cc
+++ b/chromium/net/http/http_basic_stream.cc
@@ -42,10 +42,6 @@ int HttpBasicStream::ReadResponseHeaders(const CompletionCallback& callback) {
return parser()->ReadResponseHeaders(callback);
}
-const HttpResponseInfo* HttpBasicStream::GetResponseInfo() const {
- return parser()->GetResponseInfo();
-}
-
int HttpBasicStream::ReadResponseBody(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) {
@@ -86,7 +82,9 @@ bool HttpBasicStream::IsConnectionReusable() const {
}
int64 HttpBasicStream::GetTotalReceivedBytes() const {
- return parser()->received_bytes();
+ if (parser())
+ return parser()->received_bytes();
+ return 0;
}
bool HttpBasicStream::GetLoadTimingInfo(
diff --git a/chromium/net/http/http_basic_stream.h b/chromium/net/http/http_basic_stream.h
index 4a67ccaac00..00253c37db4 100644
--- a/chromium/net/http/http_basic_stream.h
+++ b/chromium/net/http/http_basic_stream.h
@@ -46,8 +46,6 @@ class HttpBasicStream : public HttpStream {
virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE;
- virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE;
-
virtual int ReadResponseBody(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) OVERRIDE;
diff --git a/chromium/net/http/http_byte_range.h b/chromium/net/http/http_byte_range.h
index 98708721a4f..63c02f1ba5c 100644
--- a/chromium/net/http/http_byte_range.h
+++ b/chromium/net/http/http_byte_range.h
@@ -13,8 +13,8 @@
namespace net {
// A container class that represents a "range" specified for range request
-// specified by RFC 2616 Section 14.35.1.
-// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
+// specified by RFC 7233 Section 2.1.
+// https://tools.ietf.org/html/rfc7233#section-2.1
class NET_EXPORT HttpByteRange {
public:
HttpByteRange();
diff --git a/chromium/net/http/http_cache.cc b/chromium/net/http/http_cache.cc
index 49591da8ff4..3ae69c80a6f 100644
--- a/chromium/net/http/http_cache.cc
+++ b/chromium/net/http/http_cache.cc
@@ -33,6 +33,7 @@
#include "net/base/net_errors.h"
#include "net/base/upload_data_stream.h"
#include "net/disk_cache/disk_cache.h"
+#include "net/http/disk_cache_based_quic_server_info.h"
#include "net/http/http_cache_transaction.h"
#include "net/http/http_network_layer.h"
#include "net/http/http_network_session.h"
@@ -40,6 +41,7 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
+#include "net/quic/crypto/quic_server_info.h"
namespace {
@@ -267,23 +269,44 @@ void HttpCache::MetadataWriter::OnIOComplete(int result) {
//-----------------------------------------------------------------------------
+class HttpCache::QuicServerInfoFactoryAdaptor : public QuicServerInfoFactory {
+ public:
+ QuicServerInfoFactoryAdaptor(HttpCache* http_cache)
+ : http_cache_(http_cache) {
+ }
+
+ virtual QuicServerInfo* GetForServer(
+ const QuicServerId& server_id) OVERRIDE {
+ return new DiskCacheBasedQuicServerInfo(server_id, http_cache_);
+ }
+
+ private:
+ HttpCache* const http_cache_;
+};
+
+//-----------------------------------------------------------------------------
HttpCache::HttpCache(const net::HttpNetworkSession::Params& params,
BackendFactory* backend_factory)
: net_log_(params.net_log),
backend_factory_(backend_factory),
building_backend_(false),
mode_(NORMAL),
- network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))) {
+ network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))),
+ weak_factory_(this) {
+ SetupQuicServerInfoFactory(network_layer_->GetSession());
}
+// This call doesn't change the shared |session|'s QuicServerInfoFactory because
+// |session| is shared.
HttpCache::HttpCache(HttpNetworkSession* session,
BackendFactory* backend_factory)
: net_log_(session->net_log()),
backend_factory_(backend_factory),
building_backend_(false),
mode_(NORMAL),
- network_layer_(new HttpNetworkLayer(session)) {
+ network_layer_(new HttpNetworkLayer(session)),
+ weak_factory_(this) {
}
HttpCache::HttpCache(HttpTransactionFactory* network_layer,
@@ -293,10 +316,16 @@ HttpCache::HttpCache(HttpTransactionFactory* network_layer,
backend_factory_(backend_factory),
building_backend_(false),
mode_(NORMAL),
- network_layer_(network_layer) {
+ network_layer_(network_layer),
+ weak_factory_(this) {
+ SetupQuicServerInfoFactory(network_layer_->GetSession());
}
HttpCache::~HttpCache() {
+ // Transactions should see an invalid cache after this point; otherwise they
+ // could see an inconsistent object (half destroyed).
+ weak_factory_.InvalidateWeakPtrs();
+
// If we have any active entries remaining, then we need to deactivate them.
// We may have some pending calls to OnProcessPendingQueue, but since those
// won't run (due to our destruction), we can simply ignore the corresponding
@@ -379,7 +408,7 @@ void HttpCache::WriteMetadata(const GURL& url,
}
HttpCache::Transaction* trans =
- new HttpCache::Transaction(priority, this, NULL);
+ new HttpCache::Transaction(priority, this);
MetadataWriter* writer = new MetadataWriter(trans);
// The writer will self destruct when done.
@@ -387,17 +416,13 @@ void HttpCache::WriteMetadata(const GURL& url,
}
void HttpCache::CloseAllConnections() {
- net::HttpNetworkLayer* network =
- static_cast<net::HttpNetworkLayer*>(network_layer_.get());
- HttpNetworkSession* session = network->GetSession();
+ HttpNetworkSession* session = GetSession();
if (session)
session->CloseAllConnections();
}
void HttpCache::CloseIdleConnections() {
- net::HttpNetworkLayer* network =
- static_cast<net::HttpNetworkLayer*>(network_layer_.get());
- HttpNetworkSession* session = network->GetSession();
+ HttpNetworkSession* session = GetSession();
if (session)
session->CloseIdleConnections();
}
@@ -421,15 +446,14 @@ void HttpCache::InitializeInfiniteCache(const base::FilePath& path) {
}
int HttpCache::CreateTransaction(RequestPriority priority,
- scoped_ptr<HttpTransaction>* trans,
- HttpTransactionDelegate* delegate) {
+ scoped_ptr<HttpTransaction>* trans) {
// Do lazy initialization of disk cache if needed.
if (!disk_cache_.get()) {
// We don't care about the result.
CreateBackend(NULL, net::CompletionCallback());
}
- trans->reset(new HttpCache::Transaction(priority, this, delegate));
+ trans->reset(new HttpCache::Transaction(priority, this));
return OK;
}
@@ -438,9 +462,15 @@ HttpCache* HttpCache::GetCache() {
}
HttpNetworkSession* HttpCache::GetSession() {
- net::HttpNetworkLayer* network =
- static_cast<net::HttpNetworkLayer*>(network_layer_.get());
- return network->GetSession();
+ return network_layer_->GetSession();
+}
+
+scoped_ptr<HttpTransactionFactory>
+HttpCache::SetHttpNetworkTransactionFactoryForTesting(
+ scoped_ptr<HttpTransactionFactory> new_network_layer) {
+ scoped_ptr<HttpTransactionFactory> old_network_layer(network_layer_.Pass());
+ network_layer_ = new_network_layer.Pass();
+ return old_network_layer.Pass();
}
//-----------------------------------------------------------------------------
@@ -468,7 +498,7 @@ int HttpCache::CreateBackend(disk_cache::Backend** backend,
pending_op->writer = item.release();
pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
- AsWeakPtr(), pending_op);
+ GetWeakPtr(), pending_op);
int rv = backend_factory_->CreateBackend(net_log_, &pending_op->backend,
pending_op->callback);
@@ -583,7 +613,7 @@ int HttpCache::AsyncDoomEntry(const std::string& key, Transaction* trans) {
pending_op->writer = item;
pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
- AsWeakPtr(), pending_op);
+ GetWeakPtr(), pending_op);
int rv = disk_cache_->DoomEntry(key, pending_op->callback);
if (rv != ERR_IO_PENDING) {
@@ -723,7 +753,7 @@ int HttpCache::OpenEntry(const std::string& key, ActiveEntry** entry,
pending_op->writer = item;
pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
- AsWeakPtr(), pending_op);
+ GetWeakPtr(), pending_op);
int rv = disk_cache_->OpenEntry(key, &(pending_op->disk_entry),
pending_op->callback);
@@ -752,7 +782,7 @@ int HttpCache::CreateEntry(const std::string& key, ActiveEntry** entry,
pending_op->writer = item;
pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
- AsWeakPtr(), pending_op);
+ GetWeakPtr(), pending_op);
int rv = disk_cache_->CreateEntry(key, &(pending_op->disk_entry),
pending_op->callback);
@@ -968,6 +998,16 @@ bool HttpCache::RemovePendingTransactionFromPendingOp(PendingOp* pending_op,
return false;
}
+void HttpCache::SetupQuicServerInfoFactory(HttpNetworkSession* session) {
+ if (session && session->params().enable_quic_persist_server_info &&
+ !session->quic_stream_factory()->has_quic_server_info_factory()) {
+ DCHECK(!quic_server_info_factory_);
+ quic_server_info_factory_.reset(new QuicServerInfoFactoryAdaptor(this));
+ session->quic_stream_factory()->set_quic_server_info_factory(
+ quic_server_info_factory_.get());
+ }
+}
+
void HttpCache::ProcessPendingQueue(ActiveEntry* entry) {
// Multiple readers may finish with an entry at once, so we want to batch up
// calls to OnProcessPendingQueue. This flag also tells us that we should
@@ -978,7 +1018,7 @@ void HttpCache::ProcessPendingQueue(ActiveEntry* entry) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(&HttpCache::OnProcessPendingQueue, AsWeakPtr(), entry));
+ base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry));
}
void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) {
@@ -1135,8 +1175,8 @@ void HttpCache::OnBackendCreated(int result, PendingOp* pending_op) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(
- &HttpCache::OnBackendCreated, AsWeakPtr(), result, pending_op));
+ base::Bind(&HttpCache::OnBackendCreated, GetWeakPtr(),
+ result, pending_op));
} else {
building_backend_ = false;
DeletePendingOp(pending_op);
diff --git a/chromium/net/http/http_cache.h b/chromium/net/http/http_cache.h
index db2db6906d5..732a9c09c75 100644
--- a/chromium/net/http/http_cache.h
+++ b/chromium/net/http/http_cache.h
@@ -60,7 +60,6 @@ class ViewCacheHelper;
struct HttpRequestInfo;
class NET_EXPORT HttpCache : public HttpTransactionFactory,
- public base::SupportsWeakPtr<HttpCache>,
NON_EXPORTED_BASE(public base::NonThreadSafe) {
public:
// The cache mode of operation.
@@ -125,17 +124,16 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
HttpCache(const net::HttpNetworkSession::Params& params,
BackendFactory* backend_factory);
- // The disk cache is initialized lazily (by CreateTransaction) in this case.
+ // The disk cache is initialized lazily (by CreateTransaction) in this case.
// Provide an existing HttpNetworkSession, the cache can construct a
// network layer with a shared HttpNetworkSession in order for multiple
// network layers to share information (e.g. authentication data). The
// HttpCache takes ownership of the |backend_factory|.
HttpCache(HttpNetworkSession* session, BackendFactory* backend_factory);
- // Initialize the cache from its component parts, which is useful for
- // testing. The lifetime of the network_layer and backend_factory are managed
- // by the HttpCache and will be destroyed using |delete| when the HttpCache is
- // destroyed.
+ // Initialize the cache from its component parts. The lifetime of the
+ // |network_layer| and |backend_factory| are managed by the HttpCache and
+ // will be destroyed using |delete| when the HttpCache is destroyed.
HttpCache(HttpTransactionFactory* network_layer,
NetLog* net_log,
BackendFactory* backend_factory);
@@ -191,12 +189,23 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
// HttpTransactionFactory implementation:
virtual int CreateTransaction(RequestPriority priority,
- scoped_ptr<HttpTransaction>* trans,
- HttpTransactionDelegate* delegate) OVERRIDE;
+ scoped_ptr<HttpTransaction>* trans) OVERRIDE;
virtual HttpCache* GetCache() OVERRIDE;
virtual HttpNetworkSession* GetSession() OVERRIDE;
- protected:
+ base::WeakPtr<HttpCache> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
+
+ // Resets the network layer to allow for tests that probe
+ // network changes (e.g. host unreachable). The old network layer is
+ // returned to allow for filter patterns that only intercept
+ // some creation requests. Note ownership exchange.
+ scoped_ptr<HttpTransactionFactory>
+ SetHttpNetworkTransactionFactoryForTesting(
+ scoped_ptr<HttpTransactionFactory> new_network_layer);
+
+ private:
+ // Types --------------------------------------------------------------------
+
// Disk cache entry data indices.
enum {
kResponseInfoIndex = 0,
@@ -206,15 +215,13 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
// Must remain at the end of the enum.
kNumCacheEntryDataIndices
};
- friend class ViewCacheHelper;
-
- private:
- // Types --------------------------------------------------------------------
class MetadataWriter;
+ class QuicServerInfoFactoryAdaptor;
class Transaction;
class WorkItem;
friend class Transaction;
+ friend class ViewCacheHelper;
struct PendingOp; // Info for an entry under construction.
typedef std::list<Transaction*> TransactionList;
@@ -347,6 +354,9 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
bool RemovePendingTransactionFromPendingOp(PendingOp* pending_op,
Transaction* trans);
+ // Instantiates and sets QUIC server info factory.
+ void SetupQuicServerInfoFactory(HttpNetworkSession* session);
+
// Resumes processing the pending list of |entry|.
void ProcessPendingQueue(ActiveEntry* entry);
@@ -382,7 +392,10 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
Mode mode_;
- const scoped_ptr<HttpTransactionFactory> network_layer_;
+ scoped_ptr<QuicServerInfoFactoryAdaptor> quic_server_info_factory_;
+
+ scoped_ptr<HttpTransactionFactory> network_layer_;
+
scoped_ptr<disk_cache::Backend> disk_cache_;
// The set of active entries indexed by cache key.
@@ -396,6 +409,8 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
scoped_ptr<PlaybackCacheMap> playback_cache_map_;
+ base::WeakPtrFactory<HttpCache> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(HttpCache);
};
diff --git a/chromium/net/http/http_cache_transaction.cc b/chromium/net/http/http_cache_transaction.cc
index 88fb53a69c4..efb21e1df17 100644
--- a/chromium/net/http/http_cache_transaction.cc
+++ b/chromium/net/http/http_cache_transaction.cc
@@ -36,7 +36,6 @@
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_transaction.h"
-#include "net/http/http_transaction_delegate.h"
#include "net/http/http_util.h"
#include "net/http/partial_data.h"
#include "net/ssl/ssl_cert_request_info.h"
@@ -118,6 +117,15 @@ void RecordVaryHeaderHistogram(const net::HttpResponseInfo* response) {
UMA_HISTOGRAM_ENUMERATION("HttpCache.Vary", vary, VARY_MAX);
}
+void RecordNoStoreHeaderHistogram(int load_flags,
+ const net::HttpResponseInfo* response) {
+ if (load_flags & net::LOAD_MAIN_FRAME) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "Net.MainFrameNoStore",
+ response->headers->HasHeaderValue("cache-control", "no-store"));
+ }
+}
+
} // namespace
namespace net {
@@ -184,12 +192,11 @@ static bool HeaderMatches(const HttpRequestHeaders& headers,
HttpCache::Transaction::Transaction(
RequestPriority priority,
- HttpCache* cache,
- HttpTransactionDelegate* transaction_delegate)
+ HttpCache* cache)
: next_state_(STATE_NONE),
request_(NULL),
priority_(priority),
- cache_(cache->AsWeakPtr()),
+ cache_(cache->GetWeakPtr()),
entry_(NULL),
new_entry_(NULL),
new_response_(NULL),
@@ -213,7 +220,7 @@ HttpCache::Transaction::Transaction(
io_callback_(base::Bind(&Transaction::OnIOComplete,
weak_factory_.GetWeakPtr())),
transaction_pattern_(PATTERN_UNDEFINED),
- transaction_delegate_(transaction_delegate),
+ total_received_bytes_(0),
websocket_handshake_stream_base_create_helper_(NULL) {
COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders ==
arraysize(kValidationHeaders),
@@ -225,8 +232,6 @@ HttpCache::Transaction::~Transaction() {
// after this point.
callback_.Reset();
- transaction_delegate_ = NULL;
-
if (cache_) {
if (entry_) {
bool cancel_request = reading_ && response_.headers;
@@ -450,6 +455,9 @@ void HttpCache::Transaction::StopCaching() {
// entry how it is (it will be marked as truncated at destruction), and let
// the next piece of code that executes know that we are now reading directly
// from the net.
+ // TODO(mmenke): This doesn't release the lock on the cache entry, so a
+ // future request for the resource will be blocked on this one.
+ // Fix this.
if (cache_.get() && entry_ && (mode_ & WRITE) && network_trans_.get() &&
!is_sparse_ && !range_requested_) {
mode_ = NONE;
@@ -465,6 +473,13 @@ bool HttpCache::Transaction::GetFullRequestHeaders(
return false;
}
+int64 HttpCache::Transaction::GetTotalReceivedBytes() const {
+ int64 total_received_bytes = total_received_bytes_;
+ if (network_trans_)
+ total_received_bytes += network_trans_->GetTotalReceivedBytes();
+ return total_received_bytes;
+}
+
void HttpCache::Transaction::DoneReading() {
if (cache_.get() && entry_) {
DCHECK_NE(mode_, UPDATE);
@@ -507,6 +522,9 @@ UploadProgress HttpCache::Transaction::GetUploadProgress() const {
return final_upload_progress_;
}
+void HttpCache::Transaction::SetQuicServerInfo(
+ QuicServerInfo* quic_server_info) {}
+
bool HttpCache::Transaction::GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const {
if (network_trans_)
@@ -541,6 +559,18 @@ void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper(
network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper);
}
+void HttpCache::Transaction::SetBeforeNetworkStartCallback(
+ const BeforeNetworkStartCallback& callback) {
+ DCHECK(!network_trans_);
+ before_network_start_callback_ = callback;
+}
+
+int HttpCache::Transaction::ResumeNetworkStart() {
+ if (network_trans_)
+ return network_trans_->ResumeNetworkStart();
+ return ERR_UNEXPECTED;
+}
+
//-----------------------------------------------------------------------------
void HttpCache::Transaction::DoCallback(int rv) {
@@ -791,13 +821,11 @@ int HttpCache::Transaction::DoGetBackend() {
cache_pending_ = true;
next_state_ = STATE_GET_BACKEND_COMPLETE;
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND);
- ReportCacheActionStart();
return cache_->GetBackendForTransaction(this);
}
int HttpCache::Transaction::DoGetBackendComplete(int result) {
DCHECK(result == OK || result == ERR_FAILED);
- ReportCacheActionFinish();
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_GET_BACKEND,
result);
cache_pending_ = false;
@@ -860,10 +888,11 @@ int HttpCache::Transaction::DoSendRequest() {
send_request_since_ = TimeTicks::Now();
// Create a network transaction.
- int rv = cache_->network_layer_->CreateTransaction(
- priority_, &network_trans_, NULL);
+ int rv = cache_->network_layer_->CreateTransaction(priority_,
+ &network_trans_);
if (rv != OK)
return rv;
+ network_trans_->SetBeforeNetworkStartCallback(before_network_start_callback_);
// Old load timing information, if any, is now obsolete.
old_network_trans_load_timing_.reset();
@@ -872,15 +901,12 @@ int HttpCache::Transaction::DoSendRequest() {
network_trans_->SetWebSocketHandshakeStreamCreateHelper(
websocket_handshake_stream_base_create_helper_);
- ReportNetworkActionStart();
next_state_ = STATE_SEND_REQUEST_COMPLETE;
rv = network_trans_->Start(request_, io_callback_, net_log_);
return rv;
}
int HttpCache::Transaction::DoSendRequestComplete(int result) {
- ReportNetworkActionFinish();
-
if (!cache_.get())
return ERR_UNEXPECTED;
@@ -938,15 +964,37 @@ int HttpCache::Transaction::DoSendRequestComplete(int result) {
int HttpCache::Transaction::DoSuccessfulSendRequest() {
DCHECK(!new_response_);
const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
+ bool authentication_failure = false;
if (new_response->headers->response_code() == 401 ||
new_response->headers->response_code() == 407) {
auth_response_ = *new_response;
- return OK;
+ if (!reading_)
+ return OK;
+
+ // We initiated a second request the caller doesn't know about. We should be
+ // able to authenticate this request because we should have authenticated
+ // this URL moments ago.
+ if (IsReadyToRestartForAuth()) {
+ DCHECK(!response_.auth_challenge.get());
+ next_state_ = STATE_SEND_REQUEST_COMPLETE;
+ // In theory we should check to see if there are new cookies, but there
+ // is no way to do that from here.
+ return network_trans_->RestartWithAuth(AuthCredentials(), io_callback_);
+ }
+
+ // We have to perform cleanup at this point so that at least the next
+ // request can succeed.
+ authentication_failure = true;
+ if (entry_)
+ DoomPartialEntry(false);
+ mode_ = NONE;
+ partial_.reset();
}
new_response_ = new_response;
- if (!ValidatePartialResponse() && !auth_response_.headers.get()) {
+ if (authentication_failure ||
+ (!ValidatePartialResponse() && !auth_response_.headers.get())) {
// Something went wrong with this request and we have to restart it.
// If we have an authentication response, we are exposed to weird things
// hapenning if the user cancels the authentication before we receive
@@ -958,18 +1006,13 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() {
next_state_ = STATE_SEND_REQUEST;
return OK;
}
+
if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
// We have stored the full entry, but it changed and the server is
// sending a range. We have to delete the old entry.
UpdateTransactionPattern(PATTERN_NOT_COVERED);
DoneWritingToEntry(false);
}
- if (new_response_->headers->response_code() == 416 &&
- (request_->method == "GET" || request_->method == "POST")) {
- DCHECK_EQ(NONE, mode_);
- response_ = *new_response_;
- return OK;
- }
if (mode_ == WRITE &&
transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) {
@@ -993,6 +1036,14 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() {
}
RecordVaryHeaderHistogram(new_response);
+ RecordNoStoreHeaderHistogram(request_->load_flags, new_response);
+
+ if (new_response_->headers->response_code() == 416 &&
+ (request_->method == "GET" || request_->method == "POST")) {
+ // If there is an ective entry it may be destroyed with this transaction.
+ response_ = *new_response_;
+ return OK;
+ }
// Are we expecting a response to a conditional query?
if (mode_ == READ_WRITE || mode_ == UPDATE) {
@@ -1010,7 +1061,6 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() {
}
int HttpCache::Transaction::DoNetworkRead() {
- ReportNetworkActionStart();
next_state_ = STATE_NETWORK_READ_COMPLETE;
return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
}
@@ -1018,8 +1068,6 @@ int HttpCache::Transaction::DoNetworkRead() {
int HttpCache::Transaction::DoNetworkReadComplete(int result) {
DCHECK(mode_ & WRITE || mode_ == NONE);
- ReportNetworkActionFinish();
-
if (!cache_.get())
return ERR_UNEXPECTED;
@@ -1053,7 +1101,6 @@ int HttpCache::Transaction::DoOpenEntry() {
cache_pending_ = true;
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
first_cache_access_since_ = TimeTicks::Now();
- ReportCacheActionStart();
return cache_->OpenEntry(cache_key_, &new_entry_, this);
}
@@ -1061,7 +1108,6 @@ int HttpCache::Transaction::DoOpenEntryComplete(int result) {
// It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
// OK, otherwise the cache will end up with an active entry without any
// transaction attached.
- ReportCacheActionFinish();
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result);
cache_pending_ = false;
if (result == OK) {
@@ -1105,7 +1151,6 @@ int HttpCache::Transaction::DoCreateEntry() {
next_state_ = STATE_CREATE_ENTRY_COMPLETE;
cache_pending_ = true;
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY);
- ReportCacheActionStart();
return cache_->CreateEntry(cache_key_, &new_entry_, this);
}
@@ -1113,7 +1158,6 @@ int HttpCache::Transaction::DoCreateEntryComplete(int result) {
// It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
// OK, otherwise the cache will end up with an active entry without any
// transaction attached.
- ReportCacheActionFinish();
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY,
result);
cache_pending_ = false;
@@ -1147,12 +1191,10 @@ int HttpCache::Transaction::DoDoomEntry() {
if (first_cache_access_since_.is_null())
first_cache_access_since_ = TimeTicks::Now();
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY);
- ReportCacheActionStart();
return cache_->DoomEntry(cache_key_, this);
}
int HttpCache::Transaction::DoDoomEntryComplete(int result) {
- ReportCacheActionFinish();
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result);
next_state_ = STATE_CREATE_ENTRY;
cache_pending_ = false;
@@ -1337,20 +1379,18 @@ int HttpCache::Transaction::DoTruncateCachedData() {
next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
if (!entry_)
return OK;
- if (net_log_.IsLoggingAllEvents())
+ if (net_log_.IsLogging())
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA);
- ReportCacheActionStart();
// Truncate the stream.
return WriteToEntry(kResponseContentIndex, 0, NULL, 0, io_callback_);
}
int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) {
if (entry_) {
- ReportCacheActionFinish();
- if (net_log_.IsLoggingAllEvents()) {
- net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA,
- result);
- }
+ if (net_log_.IsLogging()) {
+ net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA,
+ result);
+ }
}
next_state_ = STATE_TRUNCATE_CACHED_METADATA;
@@ -1362,16 +1402,14 @@ int HttpCache::Transaction::DoTruncateCachedMetadata() {
if (!entry_)
return OK;
- if (net_log_.IsLoggingAllEvents())
+ if (net_log_.IsLogging())
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
- ReportCacheActionStart();
return WriteToEntry(kMetadataIndex, 0, NULL, 0, io_callback_);
}
int HttpCache::Transaction::DoTruncateCachedMetadataComplete(int result) {
if (entry_) {
- ReportCacheActionFinish();
- if (net_log_.IsLoggingAllEvents()) {
+ if (net_log_.IsLogging()) {
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
result);
}
@@ -1412,13 +1450,11 @@ int HttpCache::Transaction::DoCacheReadResponse() {
read_buf_ = new IOBuffer(io_buf_len_);
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO);
- ReportCacheActionStart();
return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_.get(),
io_buf_len_, io_callback_);
}
int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
- ReportCacheActionFinish();
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
if (result != io_buf_len_ ||
!HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_,
@@ -1465,18 +1501,16 @@ int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
int HttpCache::Transaction::DoCacheWriteResponse() {
if (entry_) {
- if (net_log_.IsLoggingAllEvents())
+ if (net_log_.IsLogging())
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
- ReportCacheActionStart();
}
return WriteResponseInfoToEntry(false);
}
int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
if (entry_) {
- if (net_log_.IsLoggingAllEvents())
+ if (net_log_.IsLogging())
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
- ReportCacheActionStart();
}
return WriteResponseInfoToEntry(true);
}
@@ -1486,8 +1520,7 @@ int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
target_state_ = STATE_NONE;
if (!entry_)
return OK;
- ReportCacheActionFinish();
- if (net_log_.IsLoggingAllEvents()) {
+ if (net_log_.IsLogging()) {
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
result);
}
@@ -1509,7 +1542,6 @@ int HttpCache::Transaction::DoCacheReadMetadata() {
new IOBufferWithSize(entry_->disk_entry->GetDataSize(kMetadataIndex));
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO);
- ReportCacheActionStart();
return entry_->disk_entry->ReadData(kMetadataIndex, 0,
response_.metadata.get(),
response_.metadata->size(),
@@ -1517,7 +1549,6 @@ int HttpCache::Transaction::DoCacheReadMetadata() {
}
int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
- ReportCacheActionFinish();
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
if (result != response_.metadata->size())
return OnCacheReadError(result, false);
@@ -1547,9 +1578,8 @@ int HttpCache::Transaction::DoCacheReadData() {
DCHECK(entry_);
next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
- if (net_log_.IsLoggingAllEvents())
+ if (net_log_.IsLogging())
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA);
- ReportCacheActionStart();
if (partial_.get()) {
return partial_->CacheRead(entry_->disk_entry, read_buf_.get(), io_buf_len_,
io_callback_);
@@ -1561,8 +1591,7 @@ int HttpCache::Transaction::DoCacheReadData() {
}
int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
- ReportCacheActionFinish();
- if (net_log_.IsLoggingAllEvents()) {
+ if (net_log_.IsLogging()) {
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA,
result);
}
@@ -1593,9 +1622,8 @@ int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
write_len_ = num_bytes;
if (entry_) {
- if (net_log_.IsLoggingAllEvents())
+ if (net_log_.IsLogging())
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA);
- ReportCacheActionStart();
}
return AppendResponseDataToEntry(read_buf_.get(), num_bytes, io_callback_);
@@ -1603,8 +1631,7 @@ int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
int HttpCache::Transaction::DoCacheWriteDataComplete(int result) {
if (entry_) {
- ReportCacheActionFinish();
- if (net_log_.IsLoggingAllEvents()) {
+ if (net_log_.IsLogging()) {
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA,
result);
}
@@ -1923,7 +1950,6 @@ int HttpCache::Transaction::RestartNetworkRequest() {
DCHECK(network_trans_.get());
DCHECK_EQ(STATE_NONE, next_state_);
- ReportNetworkActionStart();
next_state_ = STATE_SEND_REQUEST_COMPLETE;
int rv = network_trans_->RestartIgnoringLastError(io_callback_);
if (rv != ERR_IO_PENDING)
@@ -1937,7 +1963,6 @@ int HttpCache::Transaction::RestartNetworkRequestWithCertificate(
DCHECK(network_trans_.get());
DCHECK_EQ(STATE_NONE, next_state_);
- ReportNetworkActionStart();
next_state_ = STATE_SEND_REQUEST_COMPLETE;
int rv = network_trans_->RestartWithCertificate(client_cert, io_callback_);
if (rv != ERR_IO_PENDING)
@@ -1951,7 +1976,6 @@ int HttpCache::Transaction::RestartNetworkRequestWithAuth(
DCHECK(network_trans_.get());
DCHECK_EQ(STATE_NONE, next_state_);
- ReportNetworkActionStart();
next_state_ = STATE_SEND_REQUEST_COMPLETE;
int rv = network_trans_->RestartWithAuth(credentials, io_callback_);
if (rv != ERR_IO_PENDING)
@@ -2265,8 +2289,7 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) {
response_.headers->HasHeaderValue("cache-control", "no-store")) ||
net::IsCertStatusError(response_.ssl_info.cert_status)) {
DoneWritingToEntry(false);
- ReportCacheActionFinish();
- if (net_log_.IsLoggingAllEvents())
+ if (net_log_.IsLogging())
net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
return OK;
}
@@ -2387,6 +2410,7 @@ void HttpCache::Transaction::ResetNetworkTransaction() {
LoadTimingInfo load_timing;
if (network_trans_->GetLoadTimingInfo(&load_timing))
old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing));
+ total_received_bytes_ += network_trans_->GetTotalReceivedBytes();
network_trans_.reset();
}
@@ -2422,30 +2446,6 @@ bool HttpCache::Transaction::CanResume(bool has_data) {
return true;
}
-void HttpCache::Transaction::OnIOComplete(int result) {
- DoLoop(result);
-}
-
-void HttpCache::Transaction::ReportCacheActionStart() {
- if (transaction_delegate_)
- transaction_delegate_->OnCacheActionStart();
-}
-
-void HttpCache::Transaction::ReportCacheActionFinish() {
- if (transaction_delegate_)
- transaction_delegate_->OnCacheActionFinish();
-}
-
-void HttpCache::Transaction::ReportNetworkActionStart() {
- if (transaction_delegate_)
- transaction_delegate_->OnNetworkActionStart();
-}
-
-void HttpCache::Transaction::ReportNetworkActionFinish() {
- if (transaction_delegate_)
- transaction_delegate_->OnNetworkActionFinish();
-}
-
void HttpCache::Transaction::UpdateTransactionPattern(
TransactionPattern new_transaction_pattern) {
if (transaction_pattern_ == PATTERN_NOT_COVERED)
@@ -2532,4 +2532,8 @@ void HttpCache::Transaction::RecordHistograms() {
}
}
+void HttpCache::Transaction::OnIOComplete(int result) {
+ DoLoop(result);
+}
+
} // namespace net
diff --git a/chromium/net/http/http_cache_transaction.h b/chromium/net/http/http_cache_transaction.h
index 90c4db5a39c..aeef83e9b9c 100644
--- a/chromium/net/http/http_cache_transaction.h
+++ b/chromium/net/http/http_cache_transaction.h
@@ -23,7 +23,6 @@ namespace net {
class PartialData;
struct HttpRequestInfo;
-class HttpTransactionDelegate;
struct LoadTimingInfo;
// This is the transaction that is returned by the HttpCache transaction
@@ -60,8 +59,7 @@ class HttpCache::Transaction : public HttpTransaction {
};
Transaction(RequestPriority priority,
- HttpCache* cache,
- HttpTransactionDelegate* transaction_delegate);
+ HttpCache* cache);
virtual ~Transaction();
Mode mode() const { return mode_; }
@@ -123,15 +121,20 @@ class HttpCache::Transaction : public HttpTransaction {
virtual void StopCaching() OVERRIDE;
virtual bool GetFullRequestHeaders(
HttpRequestHeaders* headers) const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
virtual void DoneReading() OVERRIDE;
virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE;
virtual LoadState GetLoadState() const OVERRIDE;
virtual UploadProgress GetUploadProgress(void) const OVERRIDE;
+ virtual void SetQuicServerInfo(QuicServerInfo* quic_server_info) OVERRIDE;
virtual bool GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const OVERRIDE;
virtual void SetPriority(RequestPriority priority) OVERRIDE;
virtual void SetWebSocketHandshakeStreamCreateHelper(
net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) OVERRIDE;
+ virtual void SetBeforeNetworkStartCallback(
+ const BeforeNetworkStartCallback& callback) OVERRIDE;
+ virtual int ResumeNetworkStart() OVERRIDE;
private:
static const size_t kNumValidationHeaders = 2;
@@ -373,16 +376,12 @@ class HttpCache::Transaction : public HttpTransaction {
// data is considered for the result.
bool CanResume(bool has_data);
- // Called to signal completion of asynchronous IO.
- void OnIOComplete(int result);
-
- void ReportCacheActionStart();
- void ReportCacheActionFinish();
- void ReportNetworkActionStart();
- void ReportNetworkActionFinish();
void UpdateTransactionPattern(TransactionPattern new_transaction_pattern);
void RecordHistograms();
+ // Called to signal completion of asynchronous IO.
+ void OnIOComplete(int result);
+
State next_state_;
const HttpRequestInfo* request_;
RequestPriority priority_;
@@ -403,14 +402,14 @@ class HttpCache::Transaction : public HttpTransaction {
std::string cache_key_;
Mode mode_;
State target_state_;
- bool reading_; // We are already reading.
+ bool reading_; // We are already reading. Never reverts to false once set.
bool invalid_range_; // We may bypass the cache for this request.
bool truncated_; // We don't have all the response data.
bool is_sparse_; // The data is stored in sparse byte ranges.
bool range_requested_; // The user requested a byte range.
bool handling_206_; // We must deal with this 206 response.
bool cache_pending_; // We are waiting for the HttpCache.
- bool done_reading_;
+ bool done_reading_; // All available data was read.
bool vary_mismatch_; // The request doesn't match the stored vary data.
bool couldnt_conditionalize_request_;
scoped_refptr<IOBuffer> read_buf_;
@@ -429,7 +428,7 @@ class HttpCache::Transaction : public HttpTransaction {
base::TimeTicks first_cache_access_since_;
base::TimeTicks send_request_since_;
- HttpTransactionDelegate* transaction_delegate_;
+ int64 total_received_bytes_;
// Load timing information for the last network request, if any. Set in the
// 304 and 206 response cases, as the network transaction may be destroyed
@@ -443,6 +442,8 @@ class HttpCache::Transaction : public HttpTransaction {
WebSocketHandshakeStreamBase::CreateHelper*
websocket_handshake_stream_base_create_helper_;
+ BeforeNetworkStartCallback before_network_start_callback_;
+
DISALLOW_COPY_AND_ASSIGN(Transaction);
};
diff --git a/chromium/net/http/http_cache_unittest.cc b/chromium/net/http/http_cache_unittest.cc
index aa6056a4177..c87fa1b7eec 100644
--- a/chromium/net/http/http_cache_unittest.cc
+++ b/chromium/net/http/http_cache_unittest.cc
@@ -4,6 +4,8 @@
#include "net/http/http_cache.h"
+#include <algorithm>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/scoped_vector.h"
@@ -27,8 +29,7 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_transaction.h"
-#include "net/http/http_transaction_delegate.h"
-#include "net/http/http_transaction_unittest.h"
+#include "net/http/http_transaction_test_util.h"
#include "net/http/http_util.h"
#include "net/http/mock_http_cache.h"
#include "net/socket/client_socket_handle.h"
@@ -108,60 +109,6 @@ class DeleteCacheCompletionCallback : public net::TestCompletionCallbackBase {
//-----------------------------------------------------------------------------
// helpers
-class TestHttpTransactionDelegate : public net::HttpTransactionDelegate {
- public:
- TestHttpTransactionDelegate(int num_cache_actions_to_observe,
- int num_network_actions_to_observe)
- : num_callbacks_observed_(0),
- num_remaining_cache_actions_to_observe_(num_cache_actions_to_observe),
- num_remaining_network_actions_to_observe_(
- num_network_actions_to_observe),
- cache_action_in_progress_(false),
- network_action_in_progress_(false) {
- }
- virtual ~TestHttpTransactionDelegate() {
- EXPECT_EQ(0, num_remaining_cache_actions_to_observe_);
- EXPECT_EQ(0, num_remaining_network_actions_to_observe_);
- EXPECT_FALSE(cache_action_in_progress_);
- EXPECT_FALSE(network_action_in_progress_);
- }
- virtual void OnCacheActionStart() OVERRIDE {
- num_callbacks_observed_++;
- EXPECT_FALSE(cache_action_in_progress_);
- EXPECT_FALSE(network_action_in_progress_);
- EXPECT_GT(num_remaining_cache_actions_to_observe_, 0);
- num_remaining_cache_actions_to_observe_--;
- cache_action_in_progress_ = true;
- }
- virtual void OnCacheActionFinish() OVERRIDE {
- num_callbacks_observed_++;
- EXPECT_TRUE(cache_action_in_progress_);
- cache_action_in_progress_ = false;
- }
- virtual void OnNetworkActionStart() OVERRIDE {
- num_callbacks_observed_++;
- EXPECT_FALSE(cache_action_in_progress_);
- EXPECT_FALSE(network_action_in_progress_);
- EXPECT_GT(num_remaining_network_actions_to_observe_, 0);
- num_remaining_network_actions_to_observe_--;
- network_action_in_progress_ = true;
- }
- virtual void OnNetworkActionFinish() OVERRIDE {
- num_callbacks_observed_++;
- EXPECT_TRUE(network_action_in_progress_);
- network_action_in_progress_ = false;
- }
-
- int num_callbacks_observed() { return num_callbacks_observed_; }
-
- private:
- int num_callbacks_observed_;
- int num_remaining_cache_actions_to_observe_;
- int num_remaining_network_actions_to_observe_;
- bool cache_action_in_progress_;
- bool network_action_in_progress_;
-};
-
void ReadAndVerifyTransaction(net::HttpTransaction* trans,
const MockTransaction& trans_info) {
std::string content;
@@ -172,31 +119,19 @@ void ReadAndVerifyTransaction(net::HttpTransaction* trans,
EXPECT_EQ(expected, content);
}
-const int kNoDelegateTransactionCheck = -1;
-
-void RunTransactionTestWithRequestAndDelegateAndGetTiming(
- net::HttpCache* cache,
- const MockTransaction& trans_info,
- const MockHttpRequest& request,
- net::HttpResponseInfo* response_info,
- int num_cache_delegate_actions,
- int num_network_delegate_actions,
- const net::BoundNetLog& net_log,
- net::LoadTimingInfo* load_timing_info) {
+void RunTransactionTestBase(net::HttpCache* cache,
+ const MockTransaction& trans_info,
+ const MockHttpRequest& request,
+ net::HttpResponseInfo* response_info,
+ const net::BoundNetLog& net_log,
+ net::LoadTimingInfo* load_timing_info,
+ int64* received_bytes) {
net::TestCompletionCallback callback;
// write to the cache
- scoped_ptr<TestHttpTransactionDelegate> delegate;
- if (num_cache_delegate_actions != kNoDelegateTransactionCheck &&
- num_network_delegate_actions != kNoDelegateTransactionCheck) {
- delegate.reset(
- new TestHttpTransactionDelegate(num_cache_delegate_actions,
- num_network_delegate_actions));
- }
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, delegate.get());
+ int rv = cache->CreateTransaction(net::DEFAULT_PRIORITY, &trans);
EXPECT_EQ(net::OK, rv);
ASSERT_TRUE(trans.get());
@@ -223,47 +158,25 @@ void RunTransactionTestWithRequestAndDelegateAndGetTiming(
}
ReadAndVerifyTransaction(trans.get(), trans_info);
-}
-void RunTransactionTestWithRequestAndDelegate(
- net::HttpCache* cache,
- const MockTransaction& trans_info,
- const MockHttpRequest& request,
- net::HttpResponseInfo* response_info,
- int num_cache_delegate_actions,
- int num_network_delegate_actions) {
- RunTransactionTestWithRequestAndDelegateAndGetTiming(
- cache, trans_info, request, response_info, num_cache_delegate_actions,
- num_network_delegate_actions, net::BoundNetLog(), NULL);
+ if (received_bytes)
+ *received_bytes = trans->GetTotalReceivedBytes();
}
void RunTransactionTestWithRequest(net::HttpCache* cache,
const MockTransaction& trans_info,
const MockHttpRequest& request,
net::HttpResponseInfo* response_info) {
- RunTransactionTestWithRequestAndDelegate(
- cache, trans_info, request, response_info, kNoDelegateTransactionCheck,
- kNoDelegateTransactionCheck);
+ RunTransactionTestBase(cache, trans_info, request, response_info,
+ net::BoundNetLog(), NULL, NULL);
}
-void RunTransactionTestAndGetTiming(
- net::HttpCache* cache,
- const MockTransaction& trans_info,
- const net::BoundNetLog& log,
- net::LoadTimingInfo* load_timing_info) {
- RunTransactionTestWithRequestAndDelegateAndGetTiming(
- cache, trans_info, MockHttpRequest(trans_info), NULL,
- kNoDelegateTransactionCheck, kNoDelegateTransactionCheck, log,
- load_timing_info);
-}
-
-void RunTransactionTestWithDelegate(net::HttpCache* cache,
+void RunTransactionTestAndGetTiming(net::HttpCache* cache,
const MockTransaction& trans_info,
- int num_cache_delegate_actions,
- int num_network_delegate_actions) {
- RunTransactionTestWithRequestAndDelegate(
- cache, trans_info, MockHttpRequest(trans_info), NULL,
- num_cache_delegate_actions, num_network_delegate_actions);
+ const net::BoundNetLog& log,
+ net::LoadTimingInfo* load_timing_info) {
+ RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
+ NULL, log, load_timing_info, NULL);
}
void RunTransactionTest(net::HttpCache* cache,
@@ -274,8 +187,8 @@ void RunTransactionTest(net::HttpCache* cache,
void RunTransactionTestWithResponseInfo(net::HttpCache* cache,
const MockTransaction& trans_info,
net::HttpResponseInfo* response) {
- RunTransactionTestWithRequest(
- cache, trans_info, MockHttpRequest(trans_info), response);
+ RunTransactionTestWithRequest(cache, trans_info, MockHttpRequest(trans_info),
+ response);
}
void RunTransactionTestWithResponseInfoAndGetTiming(
@@ -284,10 +197,8 @@ void RunTransactionTestWithResponseInfoAndGetTiming(
net::HttpResponseInfo* response,
const net::BoundNetLog& log,
net::LoadTimingInfo* load_timing_info) {
- RunTransactionTestWithRequestAndDelegateAndGetTiming(
- cache, trans_info, MockHttpRequest(trans_info), response,
- kNoDelegateTransactionCheck, kNoDelegateTransactionCheck, log,
- load_timing_info);
+ RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
+ response, log, load_timing_info, NULL);
}
void RunTransactionTestWithResponse(net::HttpCache* cache,
@@ -305,10 +216,8 @@ void RunTransactionTestWithResponseAndGetTiming(
const net::BoundNetLog& log,
net::LoadTimingInfo* load_timing_info) {
net::HttpResponseInfo response;
- RunTransactionTestWithRequestAndDelegateAndGetTiming(
- cache, trans_info, MockHttpRequest(trans_info), &response,
- kNoDelegateTransactionCheck, kNoDelegateTransactionCheck,
- log, load_timing_info);
+ RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
+ &response, log, load_timing_info, NULL);
response.headers->GetNormalizedHeaders(response_headers);
}
@@ -418,6 +327,13 @@ void RangeTransactionServer::RangeHandler(const net::HttpRequestInfo* request,
// We want to make sure we don't delete extra headers.
EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
+ if (request->extra_headers.HasHeader("X-Require-Mock-Auth") &&
+ !request->extra_headers.HasHeader("Authorization")) {
+ response_status->assign("HTTP/1.1 401 Unauthorized");
+ response_data->assign("WWW-Authenticate: Foo\n");
+ return;
+ }
+
if (not_modified_) {
response_status->assign("HTTP/1.1 304 Not Modified");
response_data->clear();
@@ -591,6 +507,31 @@ class FakeWebSocketHandshakeStreamCreateHelper
}
};
+// Returns true if |entry| is not one of the log types paid attention to in this
+// test. Note that TYPE_HTTP_CACHE_WRITE_INFO and TYPE_HTTP_CACHE_*_DATA are
+// ignored.
+bool ShouldIgnoreLogEntry(const net::CapturingNetLog::CapturedEntry& entry) {
+ switch (entry.type) {
+ case net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND:
+ case net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY:
+ case net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY:
+ case net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY:
+ case net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY:
+ case net::NetLog::TYPE_HTTP_CACHE_READ_INFO:
+ return false;
+ default:
+ return true;
+ }
+}
+
+// Modifies |entries| to only include log entries created by the cache layer and
+// asserted on in these tests.
+void FilterLogEntries(net::CapturingNetLog::CapturedEntryList* entries) {
+ entries->erase(std::remove_if(entries->begin(), entries->end(),
+ &ShouldIgnoreLogEntry),
+ entries->end());
+}
+
} // namespace
@@ -601,9 +542,7 @@ TEST(HttpCache, CreateThenDestroy) {
MockHttpCache cache;
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ EXPECT_EQ(net::OK, cache.CreateTransaction(&trans));
ASSERT_TRUE(trans.get());
}
@@ -638,7 +577,6 @@ TEST(HttpCache, SimpleGETNoDiskCache) {
cache.disk_cache()->set_fail_requests();
net::CapturingBoundNetLog log;
- log.SetLogLevel(net::NetLog::LOG_BASIC);
net::LoadTimingInfo load_timing_info;
// Read from the network, and don't use the cache.
@@ -649,6 +587,7 @@ TEST(HttpCache, SimpleGETNoDiskCache) {
// (We attempted to both Open and Create entries, but both failed).
net::CapturingNetLog::CapturedEntryList entries;
log.GetEntries(&entries);
+ FilterLogEntries(&entries);
EXPECT_EQ(6u, entries.size());
EXPECT_TRUE(net::LogContainsBeginEvent(
@@ -693,15 +632,13 @@ TEST(HttpCache, ReleaseBuffer) {
MockHttpRequest request(kSimpleGET_Transaction);
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- ASSERT_EQ(net::OK, rv);
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
const int kBufferSize = 10;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
net::ReleaseBufferCompletionCallback cb(buffer.get());
- rv = trans->Start(&request, cb.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, cb.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, cb.GetResult(rv));
rv = trans->Read(buffer.get(), kBufferSize, cb.callback());
@@ -736,9 +673,8 @@ TEST(HttpCache, SimpleGETWithDiskFailures2) {
MockHttpRequest request(kSimpleGET_Transaction);
scoped_ptr<Context> c(new Context());
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::ERR_IO_PENDING, rv);
@@ -782,9 +718,8 @@ TEST(HttpCache, SimpleGETWithDiskFailures3) {
// Now fail to read from the cache.
scoped_ptr<Context> c(new Context());
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
MockHttpRequest request(kSimpleGET_Transaction);
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
@@ -808,10 +743,6 @@ TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) {
MockHttpCache cache;
net::CapturingBoundNetLog log;
-
- // This prevents a number of write events from being logged.
- log.SetLogLevel(net::NetLog::LOG_BASIC);
-
net::LoadTimingInfo load_timing_info;
// Write to the cache.
@@ -821,6 +752,7 @@ TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) {
// Check that the NetLog was filled as expected.
net::CapturingNetLog::CapturedEntryList entries;
log.GetEntries(&entries);
+ FilterLogEntries(&entries);
EXPECT_EQ(8u, entries.size());
EXPECT_TRUE(net::LogContainsBeginEvent(
@@ -853,6 +785,7 @@ TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) {
// Check that the NetLog was filled as expected.
log.GetEntries(&entries);
+ FilterLogEntries(&entries);
EXPECT_EQ(8u, entries.size());
EXPECT_TRUE(net::LogContainsBeginEvent(
@@ -889,12 +822,9 @@ TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Miss) {
net::TestCompletionCallback callback;
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
- ASSERT_TRUE(trans.get());
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_CACHE_MISS, rv);
@@ -1042,11 +972,8 @@ TEST(HttpCache, SimpleGET_CacheOverride_Offline) {
MockHttpRequest request(transaction);
net::TestCompletionCallback callback;
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
- ASSERT_TRUE(trans.get());
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, callback.GetResult(rv));
const net::HttpResponseInfo* response_info = trans->GetResponseInfo();
@@ -1090,6 +1017,42 @@ TEST(HttpCache, SimpleGET_CacheOverride_NonOffline) {
RemoveMockTransaction(&transaction);
}
+// Tests that was_cached was set properly on a failure, even if the cached
+// response wasn't returned.
+TEST(HttpCache, SimpleGET_CacheSignal_Failure) {
+ MockHttpCache cache;
+
+ // Prime cache.
+ MockTransaction transaction(kSimpleGET_Transaction);
+ transaction.response_headers = "Cache-Control: no-cache\n";
+
+ AddMockTransaction(&transaction);
+ RunTransactionTest(cache.http_cache(), transaction);
+ EXPECT_EQ(1, cache.network_layer()->transaction_count());
+ EXPECT_EQ(1, cache.disk_cache()->create_count());
+ RemoveMockTransaction(&transaction);
+
+ // Network failure with error; should fail but have was_cached set.
+ transaction.return_code = net::ERR_FAILED;
+ AddMockTransaction(&transaction);
+
+ MockHttpRequest request(transaction);
+ net::TestCompletionCallback callback;
+ scoped_ptr<net::HttpTransaction> trans;
+ int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY, &trans);
+ EXPECT_EQ(net::OK, rv);
+ ASSERT_TRUE(trans.get());
+ rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ EXPECT_EQ(net::ERR_FAILED, callback.GetResult(rv));
+
+ const net::HttpResponseInfo* response_info = trans->GetResponseInfo();
+ ASSERT_TRUE(response_info);
+ EXPECT_TRUE(response_info->was_cached);
+ EXPECT_EQ(2, cache.network_layer()->transaction_count());
+
+ RemoveMockTransaction(&transaction);
+}
+
// Confirm if we have an empty cache, a read is marked as network verified.
TEST(HttpCache, SimpleGET_NetworkAccessed_Network) {
MockHttpCache cache;
@@ -1138,9 +1101,6 @@ TEST(HttpCache, SimpleGET_LoadBypassCache) {
transaction.load_flags |= net::LOAD_BYPASS_CACHE;
net::CapturingBoundNetLog log;
-
- // This prevents a number of write events from being logged.
- log.SetLogLevel(net::NetLog::LOG_BASIC);
net::LoadTimingInfo load_timing_info;
// Write to the cache.
@@ -1150,6 +1110,7 @@ TEST(HttpCache, SimpleGET_LoadBypassCache) {
// Check that the NetLog was filled as expected.
net::CapturingNetLog::CapturedEntryList entries;
log.GetEntries(&entries);
+ FilterLogEntries(&entries);
EXPECT_EQ(8u, entries.size());
EXPECT_TRUE(net::LogContainsBeginEvent(
@@ -1317,9 +1278,8 @@ TEST(HttpCache, SimpleGET_ManyReaders) {
context_list.push_back(new Context());
Context* c = context_list[i];
- c->result = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
EXPECT_EQ(net::LOAD_STATE_IDLE, c->trans->GetLoadState());
c->result = c->trans->Start(
@@ -1386,9 +1346,8 @@ TEST(HttpCache, SimpleGET_RacingReaders) {
context_list.push_back(new Context());
Context* c = context_list[i];
- c->result = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
MockHttpRequest* this_request = &request;
if (i == 1 || i == 2)
@@ -1472,9 +1431,8 @@ TEST(HttpCache, SimpleGET_DoomWithPending) {
context_list.push_back(new Context());
Context* c = context_list[i];
- c->result = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
MockHttpRequest* this_request = &request;
if (i == 3)
@@ -1521,9 +1479,8 @@ TEST(HttpCache, FastNoStoreGET_DoneWithPending) {
context_list.push_back(new Context());
Context* c = context_list[i];
- c->result = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
c->result = c->trans->Start(
&request, c->callback.callback(), net::BoundNetLog());
@@ -1569,9 +1526,8 @@ TEST(HttpCache, SimpleGET_ManyWriters_CancelFirst) {
context_list.push_back(new Context());
Context* c = context_list[i];
- c->result = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
c->result = c->trans->Start(
&request, c->callback.callback(), net::BoundNetLog());
@@ -1630,9 +1586,8 @@ TEST(HttpCache, SimpleGET_ManyWriters_CancelCreate) {
context_list.push_back(new Context());
Context* c = context_list[i];
- c->result = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
c->result = c->trans->Start(
&request, c->callback.callback(), net::BoundNetLog());
@@ -1682,9 +1637,8 @@ TEST(HttpCache, SimpleGET_CancelCreate) {
Context* c = new Context();
- c->result = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
c->result = c->trans->Start(
&request, c->callback.callback(), net::BoundNetLog());
@@ -1713,9 +1667,8 @@ TEST(HttpCache, SimpleGET_ManyWriters_BypassCache) {
context_list.push_back(new Context());
Context* c = context_list[i];
- c->result = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
c->result = c->trans->Start(
&request, c->callback.callback(), net::BoundNetLog());
@@ -1756,10 +1709,8 @@ TEST(HttpCache, SimpleGET_AbandonedCacheRead) {
net::TestCompletionCallback callback;
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
ASSERT_EQ(net::OK, rv);
@@ -1792,9 +1743,8 @@ TEST(HttpCache, SimpleGET_ManyWriters_DeleteCache) {
context_list.push_back(new Context());
Context* c = context_list[i];
- c->result = cache->http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache->CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
c->result = c->trans->Start(
&request, c->callback.callback(), net::BoundNetLog());
@@ -1832,9 +1782,8 @@ TEST(HttpCache, SimpleGET_WaitForBackend) {
context_list.push_back(new Context());
Context* c = context_list[i];
- c->result = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
}
context_list[0]->result = context_list[0]->trans->Start(
@@ -1879,9 +1828,8 @@ TEST(HttpCache, SimpleGET_WaitForBackend_CancelCreate) {
context_list.push_back(new Context());
Context* c = context_list[i];
- c->result = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
}
context_list[0]->result = context_list[0]->trans->Start(
@@ -1926,9 +1874,8 @@ TEST(HttpCache, DeleteCacheWaitingForBackend) {
MockHttpRequest request(kSimpleGET_Transaction);
scoped_ptr<Context> c(new Context());
- c->result = cache->http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache->CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
@@ -1965,9 +1912,8 @@ TEST(HttpCache, DeleteCacheWaitingForBackend2) {
MockHttpRequest request(kSimpleGET_Transaction);
scoped_ptr<Context> c(new Context());
- c->result = cache->http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, c->result);
+ c->result = cache->CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, c->result);
c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
@@ -2776,12 +2722,10 @@ TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Miss) {
net::TestCompletionCallback callback;
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
ASSERT_TRUE(trans.get());
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
ASSERT_EQ(net::ERR_CACHE_MISS, callback.GetResult(rv));
trans.reset();
@@ -3383,6 +3327,23 @@ TEST(HttpCache, GET_Crazy206) {
RemoveMockTransaction(&transaction);
}
+// Tests that receiving 416 for a regular request is handled correctly.
+TEST(HttpCache, GET_Crazy416) {
+ MockHttpCache cache;
+
+ // Write to the cache.
+ MockTransaction transaction(kSimpleGET_Transaction);
+ AddMockTransaction(&transaction);
+ transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
+ RunTransactionTest(cache.http_cache(), transaction);
+
+ EXPECT_EQ(1, cache.network_layer()->transaction_count());
+ EXPECT_EQ(0, cache.disk_cache()->open_count());
+ EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+ RemoveMockTransaction(&transaction);
+}
+
// Tests that we don't cache partial responses that can't be validated.
TEST(HttpCache, RangeGET_NoStrongValidators) {
MockHttpCache cache;
@@ -4327,9 +4288,8 @@ TEST(HttpCache, RangeGET_Cancel) {
MockHttpRequest request(kRangeGET_TransactionOK);
Context* c = new Context();
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
@@ -4367,9 +4327,8 @@ TEST(HttpCache, RangeGET_Cancel2) {
request.load_flags |= net::LOAD_VALIDATE_CACHE;
Context* c = new Context();
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
@@ -4413,9 +4372,8 @@ TEST(HttpCache, RangeGET_Cancel3) {
request.load_flags |= net::LOAD_VALIDATE_CACHE;
Context* c = new Context();
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::ERR_IO_PENDING, rv);
@@ -4441,9 +4399,8 @@ TEST(HttpCache, RangeGET_Cancel3) {
// active entry (no open or create).
c = new Context();
- rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::ERR_IO_PENDING, rv);
@@ -4723,8 +4680,7 @@ TEST(HttpCache, RangeGET_OK_LoadOnlyFromCache) {
net::TestCompletionCallback callback;
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
+ int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY, &trans);
EXPECT_EQ(net::OK, rv);
ASSERT_TRUE(trans.get());
@@ -4802,9 +4758,8 @@ TEST(HttpCache, DoomOnDestruction) {
MockHttpRequest request(kSimpleGET_Transaction);
Context* c = new Context();
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
@@ -4833,9 +4788,8 @@ TEST(HttpCache, DoomOnDestruction2) {
MockHttpRequest request(kSimpleGET_Transaction);
Context* c = new Context();
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
@@ -4877,9 +4831,8 @@ TEST(HttpCache, DoomOnDestruction3) {
MockHttpRequest request(transaction);
Context* c = new Context();
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
@@ -4921,15 +4874,9 @@ TEST(HttpCache, SetTruncatedFlag) {
MockHttpRequest request(transaction);
scoped_ptr<Context> c(new Context());
- // We use a test delegate to ensure that after initiating destruction
- // of the transaction, no further delegate callbacks happen.
- // We initialize the TestHttpTransactionDelegate with the correct number of
- // cache actions and network actions to be reported.
- scoped_ptr<TestHttpTransactionDelegate> delegate(
- new TestHttpTransactionDelegate(7, 3));
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, delegate.get());
- EXPECT_EQ(net::OK, rv);
+
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
@@ -4952,21 +4899,11 @@ TEST(HttpCache, SetTruncatedFlag) {
EXPECT_FALSE(c->callback.have_result());
MockHttpCache::SetTestMode(TEST_MODE_SYNC_ALL);
- int num_delegate_callbacks_before_destruction =
- delegate->num_callbacks_observed();
// Destroy the transaction.
c->trans.reset();
MockHttpCache::SetTestMode(0);
- // Ensure the delegate received no callbacks during destruction.
- EXPECT_EQ(num_delegate_callbacks_before_destruction,
- delegate->num_callbacks_observed());
-
- // Since the transaction was aborted in the middle of network I/O, we will
- // manually call the delegate so that its pending I/O operation will be
- // closed (which is what the test delegate is expecting).
- delegate->OnNetworkActionFinish();
// Make sure that we don't invoke the callback. We may have an issue if the
// UrlRequestJob is killed directly (without cancelling the UrlRequest) so we
@@ -4999,9 +4936,8 @@ TEST(HttpCache, DontSetTruncatedFlag) {
MockHttpRequest request(transaction);
scoped_ptr<Context> c(new Context());
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, c->callback.GetResult(rv));
@@ -5144,18 +5080,15 @@ TEST(HttpCache, GET_IncompleteResource_Cancel) {
MockHttpRequest request(transaction);
Context* c = new Context();
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
// Queue another request to this transaction. We have to start this request
// before the first one gets the response from the server and dooms the entry,
// otherwise it will just create a new entry without being queued to the first
// request.
Context* pending = new Context();
- EXPECT_EQ(net::OK,
- cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &pending->trans, NULL));
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&pending->trans));
rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::ERR_IO_PENDING,
@@ -5239,12 +5172,11 @@ TEST(HttpCache, GET_IncompleteResource3) {
"rg: 50-59 rg: 60-69 rg: 70-79 ";
scoped_ptr<Context> c(new Context);
- EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL));
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
MockHttpRequest request(transaction);
- int rv = c->trans->Start(
- &request, c->callback.callback(), net::BoundNetLog());
+ rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, c->callback.GetResult(rv));
// We should have checked with the server before finishing Start().
@@ -5255,6 +5187,56 @@ TEST(HttpCache, GET_IncompleteResource3) {
RemoveMockTransaction(&kRangeGET_TransactionOK);
}
+// Tests that we handle 401s for truncated resources.
+TEST(HttpCache, GET_IncompleteResourceWithAuth) {
+ MockHttpCache cache;
+ AddMockTransaction(&kRangeGET_TransactionOK);
+
+ std::string raw_headers("HTTP/1.1 200 OK\n"
+ "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
+ "ETag: \"foo\"\n"
+ "Accept-Ranges: bytes\n"
+ "Content-Length: 80\n");
+ CreateTruncatedEntry(raw_headers, &cache);
+
+ // Now make a regular request.
+ MockTransaction transaction(kRangeGET_TransactionOK);
+ transaction.request_headers = "X-Require-Mock-Auth: dummy\r\n"
+ EXTRA_HEADER;
+ transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 "
+ "rg: 50-59 rg: 60-69 rg: 70-79 ";
+ RangeTransactionServer handler;
+
+ scoped_ptr<Context> c(new Context);
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
+
+ MockHttpRequest request(transaction);
+ rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
+ EXPECT_EQ(net::OK, c->callback.GetResult(rv));
+
+ const net::HttpResponseInfo* response = c->trans->GetResponseInfo();
+ ASSERT_TRUE(response);
+ ASSERT_EQ(401, response->headers->response_code());
+ rv = c->trans->RestartWithAuth(net::AuthCredentials(),
+ c->callback.callback());
+ EXPECT_EQ(net::OK, c->callback.GetResult(rv));
+ response = c->trans->GetResponseInfo();
+ ASSERT_TRUE(response);
+ ASSERT_EQ(200, response->headers->response_code());
+
+ ReadAndVerifyTransaction(c->trans.get(), transaction);
+ c.reset(); // The destructor could delete the entry.
+ EXPECT_EQ(2, cache.network_layer()->transaction_count());
+
+ // Verify that the entry was not deleted.
+ disk_cache::Entry* entry;
+ ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
+ entry->Close();
+
+ RemoveMockTransaction(&kRangeGET_TransactionOK);
+}
+
// Tests that we cache a 200 response to the validation request.
TEST(HttpCache, GET_IncompleteResource4) {
MockHttpCache cache;
@@ -5312,11 +5294,10 @@ TEST(HttpCache, GET_CancelIncompleteResource) {
MockHttpRequest request(transaction);
Context* c = new Context();
- EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &c->trans, NULL));
+ int rv = cache.CreateTransaction(&c->trans);
+ ASSERT_EQ(net::OK, rv);
- int rv = c->trans->Start(
- &request, c->callback.callback(), net::BoundNetLog());
+ rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, c->callback.GetResult(rv));
// Read 20 bytes from the cache, and 10 from the net.
@@ -5441,12 +5422,9 @@ TEST(HttpCache, CachedRedirect) {
// Write to the cache.
{
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
- ASSERT_TRUE(trans.get());
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
ASSERT_EQ(net::OK, rv);
@@ -5478,12 +5456,9 @@ TEST(HttpCache, CachedRedirect) {
// Read from the cache.
{
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
- ASSERT_TRUE(trans.get());
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
ASSERT_EQ(net::OK, rv);
@@ -5662,12 +5637,9 @@ TEST(HttpCache, SimpleGET_SSLError) {
net::TestCompletionCallback callback;
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
- ASSERT_TRUE(trans.get());
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_CACHE_MISS, rv);
@@ -5678,9 +5650,7 @@ TEST(HttpCache, OutlivedTransactions) {
MockHttpCache* cache = new MockHttpCache;
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache->http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ EXPECT_EQ(net::OK, cache->CreateTransaction(&trans));
delete cache;
trans.reset();
@@ -5927,12 +5897,10 @@ TEST(HttpCache, FilterCompletion) {
{
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
MockHttpRequest request(kSimpleGET_Transaction);
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, callback.GetResult(rv));
scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
@@ -5965,12 +5933,10 @@ TEST(HttpCache, DoneReading) {
transaction.data = "";
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
MockHttpRequest request(transaction);
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, callback.GetResult(rv));
trans->DoneReading();
@@ -5995,11 +5961,9 @@ TEST(HttpCache, StopCachingDeletesEntry) {
{
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, callback.GetResult(rv));
scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
@@ -6035,11 +5999,9 @@ TEST(HttpCache, StopCachingThenDoneReadingDeletesEntry) {
{
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, callback.GetResult(rv));
scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
@@ -6080,11 +6042,9 @@ TEST(HttpCache, StopCachingWithAuthDeletesEntry) {
{
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, callback.GetResult(rv));
trans->StopCaching();
@@ -6114,9 +6074,7 @@ TEST(HttpCache, StopCachingSavesEntry) {
{
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
// Force a response that can be resumed.
MockTransaction mock_transaction(kSimpleGET_Transaction);
@@ -6125,7 +6083,7 @@ TEST(HttpCache, StopCachingSavesEntry) {
"Content-Length: 42\n"
"Etag: \"foo\"\n";
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, callback.GetResult(rv));
scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
@@ -6172,11 +6130,9 @@ TEST(HttpCache, StopCachingTruncatedEntry) {
{
// Now make a regular request.
scoped_ptr<net::HttpTransaction> trans;
- int rv = cache.http_cache()->CreateTransaction(
- net::DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(net::OK, rv);
+ ASSERT_EQ(net::OK, cache.CreateTransaction(&trans));
- rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
+ int rv = trans->Start(&request, callback.callback(), net::BoundNetLog());
EXPECT_EQ(net::OK, callback.GetResult(rv));
scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
@@ -6253,34 +6209,13 @@ TEST(HttpCache, TruncatedByContentLength2) {
entry->Close();
}
-TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit_TransactionDelegate) {
- MockHttpCache cache;
-
- // Write to the cache.
- RunTransactionTestWithDelegate(cache.http_cache(),
- kSimpleGET_Transaction,
- 8,
- 3);
-
- // Force this transaction to read from the cache.
- MockTransaction transaction(kSimpleGET_Transaction);
- transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE;
-
- RunTransactionTestWithDelegate(cache.http_cache(),
- kSimpleGET_Transaction,
- 5,
- 0);
-}
-
// Make sure that calling SetPriority on a cache transaction passes on
// its priority updates to its underlying network transaction.
TEST(HttpCache, SetPriority) {
MockHttpCache cache;
scoped_ptr<net::HttpTransaction> trans;
- EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(
- net::IDLE, &trans, NULL));
- ASSERT_TRUE(trans.get());
+ ASSERT_EQ(net::OK, cache.http_cache()->CreateTransaction(net::IDLE, &trans));
// Shouldn't crash, but doesn't do anything either.
trans->SetPriority(net::LOW);
@@ -6322,9 +6257,7 @@ TEST(HttpCache, SetWebSocketHandshakeStreamCreateHelper) {
FakeWebSocketHandshakeStreamCreateHelper create_helper;
scoped_ptr<net::HttpTransaction> trans;
- EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(
- net::IDLE, &trans, NULL));
- ASSERT_TRUE(trans.get());
+ ASSERT_EQ(net::OK, cache.http_cache()->CreateTransaction(net::IDLE, &trans));
EXPECT_FALSE(cache.network_layer()->last_transaction());
@@ -6365,9 +6298,8 @@ TEST(HttpCache, SetPriorityNewTransaction) {
"rg: 50-59 rg: 60-69 rg: 70-79 ";
scoped_ptr<net::HttpTransaction> trans;
- EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(
- net::MEDIUM, &trans, NULL));
- ASSERT_TRUE(trans.get());
+ ASSERT_EQ(net::OK,
+ cache.http_cache()->CreateTransaction(net::MEDIUM, &trans));
EXPECT_EQ(net::DEFAULT_PRIORITY,
cache.network_layer()->last_create_transaction_priority());
@@ -6390,3 +6322,97 @@ TEST(HttpCache, SetPriorityNewTransaction) {
RemoveMockTransaction(&kRangeGET_TransactionOK);
}
+
+int64 RunTransactionAndGetReceivedBytes(
+ MockHttpCache& cache,
+ const MockTransaction& trans_info) {
+ int64 received_bytes = -1;
+ RunTransactionTestBase(cache.http_cache(), trans_info,
+ MockHttpRequest(trans_info), NULL, net::BoundNetLog(),
+ NULL, &received_bytes);
+ return received_bytes;
+}
+
+int64 TransactionSize(const MockTransaction& transaction) {
+ return strlen(transaction.status) + strlen(transaction.response_headers) +
+ strlen(transaction.data);
+}
+
+TEST(HttpCache, ReceivedBytesCacheMissAndThenHit) {
+ MockHttpCache cache;
+
+ MockTransaction transaction(kSimpleGET_Transaction);
+ int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(TransactionSize(transaction), received_bytes);
+
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(0, received_bytes);
+}
+
+TEST(HttpCache, ReceivedBytesConditionalRequest304) {
+ MockHttpCache cache;
+
+ ScopedMockTransaction transaction(kETagGET_Transaction);
+ int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(TransactionSize(transaction), received_bytes);
+
+ transaction.load_flags = net::LOAD_VALIDATE_CACHE;
+ transaction.handler = ETagGet_ConditionalRequest_Handler;
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(TransactionSize(transaction), received_bytes);
+}
+
+TEST(HttpCache, ReceivedBytesConditionalRequest200) {
+ MockHttpCache cache;
+
+ MockTransaction transaction(kTypicalGET_Transaction);
+ transaction.request_headers = "Foo: bar\r\n";
+ transaction.response_headers =
+ "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
+ "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
+ "Etag: \"foopy\"\n"
+ "Cache-Control: max-age=0\n"
+ "Vary: Foo\n";
+ AddMockTransaction(&transaction);
+ int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(TransactionSize(transaction), received_bytes);
+
+ RevalidationServer server;
+ transaction.handler = server.Handler;
+ transaction.request_headers = "Foo: none\r\n";
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(TransactionSize(transaction), received_bytes);
+
+ RemoveMockTransaction(&transaction);
+}
+
+TEST(HttpCache, ReceivedBytesRange) {
+ MockHttpCache cache;
+ AddMockTransaction(&kRangeGET_TransactionOK);
+ MockTransaction transaction(kRangeGET_TransactionOK);
+
+ // Read bytes 40-49 from the network.
+ int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ int64 range_response_size = TransactionSize(transaction);
+ EXPECT_EQ(range_response_size, received_bytes);
+
+ // Read bytes 40-49 from the cache.
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(0, received_bytes);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Read bytes 30-39 from the network.
+ transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
+ transaction.data = "rg: 30-39 ";
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(range_response_size, received_bytes);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Read bytes 20-29 and 50-59 from the network, bytes 30-49 from the cache.
+ transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
+ transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(range_response_size * 2, received_bytes);
+
+ RemoveMockTransaction(&kRangeGET_TransactionOK);
+}
diff --git a/chromium/net/http/http_chunked_decoder.h b/chromium/net/http/http_chunked_decoder.h
index 9ee7400ad7d..23076f9b368 100644
--- a/chromium/net/http/http_chunked_decoder.h
+++ b/chromium/net/http/http_chunked_decoder.h
@@ -122,8 +122,7 @@ class NET_EXPORT_PRIVATE HttpChunkedDecoder {
// Set to true when FilterBuf encounters the final CRLF.
bool reached_eof_;
- // The number of unfiltered bytes after the final CRLF, either extraneous
- // data or the first part of the next response in a pipelined stream.
+ // The number of extraneous unfiltered bytes after the final CRLF.
int bytes_after_eof_;
};
diff --git a/chromium/net/http/http_content_disposition.cc b/chromium/net/http/http_content_disposition.cc
index 3dbf234b943..3a1dedeb788 100644
--- a/chromium/net/http/http_content_disposition.cc
+++ b/chromium/net/http/http_content_disposition.cc
@@ -5,15 +5,14 @@
#include "net/http/http_content_disposition.h"
#include "base/base64.h"
-#include "base/i18n/icu_string_conversions.h"
#include "base/logging.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "net/base/net_string_util.h"
#include "net/base/net_util.h"
#include "net/http/http_util.h"
-#include "third_party/icu/source/common/unicode/ucnv.h"
namespace {
@@ -65,32 +64,16 @@ bool DecodeBQEncoding(const std::string& part,
std::string* output) {
std::string decoded;
if (!((enc_type == B_ENCODING) ?
- base::Base64Decode(part, &decoded) : DecodeQEncoding(part, &decoded)))
+ base::Base64Decode(part, &decoded) : DecodeQEncoding(part, &decoded))) {
return false;
+ }
if (decoded.empty()) {
output->clear();
return true;
}
- UErrorCode err = U_ZERO_ERROR;
- UConverter* converter(ucnv_open(charset.c_str(), &err));
- if (U_FAILURE(err))
- return false;
-
- // A single byte in a legacy encoding can be expanded to 3 bytes in UTF-8.
- // A 'two-byte character' in a legacy encoding can be expanded to 4 bytes
- // in UTF-8. Therefore, the expansion ratio is 3 at most. Add one for a
- // trailing '\0'.
- size_t output_length = decoded.length() * 3 + 1;
- char* buf = WriteInto(output, output_length);
- output_length = ucnv_toAlgorithmic(UCNV_UTF8, converter, buf, output_length,
- decoded.data(), decoded.length(), &err);
- ucnv_close(converter);
- if (U_FAILURE(err))
- return false;
- output->resize(output_length);
- return true;
+ return net::ConvertToUtf8(decoded, charset.c_str(), output);
}
bool DecodeWord(const std::string& encoded_word,
@@ -103,19 +86,18 @@ bool DecodeWord(const std::string& encoded_word,
if (encoded_word.empty())
return true;
- if (!IsStringASCII(encoded_word)) {
+ if (!base::IsStringASCII(encoded_word)) {
// Try UTF-8, referrer_charset and the native OS default charset in turn.
- if (IsStringUTF8(encoded_word)) {
+ if (base::IsStringUTF8(encoded_word)) {
*output = encoded_word;
} else {
base::string16 utf16_output;
if (!referrer_charset.empty() &&
- base::CodepageToUTF16(encoded_word, referrer_charset.c_str(),
- base::OnStringConversionError::FAIL,
- &utf16_output)) {
- *output = UTF16ToUTF8(utf16_output);
+ net::ConvertToUTF16(encoded_word, referrer_charset.c_str(),
+ &utf16_output)) {
+ *output = base::UTF16ToUTF8(utf16_output);
} else {
- *output = WideToUTF8(base::SysNativeMBToWide(encoded_word));
+ *output = base::WideToUTF8(base::SysNativeMBToWide(encoded_word));
}
}
@@ -209,7 +191,7 @@ bool DecodeWord(const std::string& encoded_word,
if (decoded_word != encoded_word)
*parse_result_flags |=
net::HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS;
- if (IsStringUTF8(decoded_word)) {
+ if (base::IsStringUTF8(decoded_word)) {
output->swap(decoded_word);
return true;
// We can try either the OS default charset or 'origin charset' here,
@@ -335,7 +317,7 @@ bool DecodeExtValue(const std::string& param_value, std::string* decoded) {
return false;
// RFC 5987 value should be ASCII-only.
- if (!IsStringASCII(value)) {
+ if (!base::IsStringASCII(value)) {
decoded->clear();
return true;
}
@@ -343,7 +325,7 @@ bool DecodeExtValue(const std::string& param_value, std::string* decoded) {
std::string unescaped = net::UnescapeURLComponent(
value, net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS);
- return base::ConvertToUtf8AndNormalize(unescaped, charset, decoded);
+ return net::ConvertToUtf8AndNormalize(unescaped, charset.c_str(), decoded);
}
} // namespace
diff --git a/chromium/net/http/http_content_disposition_unittest.cc b/chromium/net/http/http_content_disposition_unittest.cc
index 62d95778c0b..43fef9dd0ea 100644
--- a/chromium/net/http/http_content_disposition_unittest.cc
+++ b/chromium/net/http/http_content_disposition_unittest.cc
@@ -198,7 +198,7 @@ TEST(HttpContentDispositionTest, Filename) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
HttpContentDisposition header(tests[i].header, tests[i].referrer_charset);
EXPECT_EQ(tests[i].expected,
- UTF8ToWide(header.filename()))
+ base::UTF8ToWide(header.filename()))
<< "Failed on input: " << tests[i].header;
}
}
@@ -507,7 +507,7 @@ TEST(HttpContentDispositionTest, tc2231) {
HttpContentDisposition header(tests[i].header, std::string());
EXPECT_EQ(tests[i].expected_type, header.type())
<< "Failed on input: " << tests[i].header;
- EXPECT_EQ(tests[i].expected_filename, UTF8ToWide(header.filename()))
+ EXPECT_EQ(tests[i].expected_filename, base::UTF8ToWide(header.filename()))
<< "Failed on input: " << tests[i].header;
}
}
diff --git a/chromium/net/http/http_log_util.cc b/chromium/net/http/http_log_util.cc
new file mode 100644
index 00000000000..ab6ebda74ac
--- /dev/null
+++ b/chromium/net/http/http_log_util.cc
@@ -0,0 +1,81 @@
+// Copyright 2014 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.
+
+#include "net/http/http_log_util.h"
+
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
+
+namespace net {
+
+namespace {
+
+bool ShouldRedactChallenge(HttpAuthChallengeTokenizer* challenge) {
+ // Ignore lines with commas, as they may contain lists of schemes, and
+ // the information we want to hide is Base64 encoded, so has no commas.
+ if (challenge->challenge_text().find(',') != std::string::npos)
+ return false;
+
+ std::string scheme = StringToLowerASCII(challenge->scheme());
+ // Invalid input.
+ if (scheme.empty())
+ return false;
+
+ // Ignore Basic and Digest authentication challenges, as they contain
+ // public information.
+ if (scheme == "basic" || scheme == "digest")
+ return false;
+
+ return true;
+}
+
+} // namespace
+
+std::string ElideHeaderValueForNetLog(NetLog::LogLevel log_level,
+ const std::string& header,
+ const std::string& value) {
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ if (!base::strcasecmp(header.c_str(), "proxy-authorization") ||
+ !base::strcasecmp(header.c_str(), "proxy-authenticate")) {
+ return "[elided]";
+ }
+#endif
+
+ if (log_level < NetLog::LOG_STRIP_PRIVATE_DATA)
+ return value;
+
+ // Note: this logic should be kept in sync with stripCookiesAndLoginInfo in
+ // chrome/browser/resources/net_internals/log_view_painter.js.
+
+ std::string::const_iterator redact_begin = value.begin();
+ std::string::const_iterator redact_end = value.begin();
+ if (!base::strcasecmp(header.c_str(), "set-cookie") ||
+ !base::strcasecmp(header.c_str(), "set-cookie2") ||
+ !base::strcasecmp(header.c_str(), "cookie") ||
+ !base::strcasecmp(header.c_str(), "authorization") ||
+ !base::strcasecmp(header.c_str(), "proxy-authorization")) {
+ redact_begin = value.begin();
+ redact_end = value.end();
+ } else if (!base::strcasecmp(header.c_str(), "www-authenticate") ||
+ !base::strcasecmp(header.c_str(), "proxy-authenticate")) {
+ // Look for authentication information from data received from the server in
+ // multi-round Negotiate authentication.
+ HttpAuthChallengeTokenizer challenge(value.begin(), value.end());
+ if (ShouldRedactChallenge(&challenge)) {
+ redact_begin = challenge.params_begin();
+ redact_end = challenge.params_end();
+ }
+ }
+
+ if (redact_begin == redact_end)
+ return value;
+
+ return std::string(value.begin(), redact_begin) +
+ base::StringPrintf("[%ld bytes were stripped]",
+ static_cast<long>(redact_end - redact_begin)) +
+ std::string(redact_end, value.end());
+}
+
+} // namespace net
diff --git a/chromium/net/http/http_log_util.h b/chromium/net/http/http_log_util.h
new file mode 100644
index 00000000000..f18c6e737b9
--- /dev/null
+++ b/chromium/net/http/http_log_util.h
@@ -0,0 +1,24 @@
+// Copyright 2014 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_HTTP_HTTP_LOG_UTIL_
+#define NET_HTTP_HTTP_LOG_UTIL_
+
+#include <string>
+
+#include "net/base/net_export.h"
+#include "net/base/net_log.h"
+
+namespace net {
+
+// Given an HTTP header |header| with value |value|, returns the elided version
+// of the header value at |log_level|.
+NET_EXPORT_PRIVATE std::string ElideHeaderValueForNetLog(
+ NetLog::LogLevel log_level,
+ const std::string& header,
+ const std::string& value);
+
+} // namespace net
+
+#endif // NET_HTTP_HTTP_LOG_UTIL_
diff --git a/chromium/net/http/http_log_util_unittest.cc b/chromium/net/http/http_log_util_unittest.cc
new file mode 100644
index 00000000000..1b0e9dbbfa2
--- /dev/null
+++ b/chromium/net/http/http_log_util_unittest.cc
@@ -0,0 +1,76 @@
+// Copyright 2014 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.
+
+#include "net/http/http_log_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+TEST(HttpLogUtilTest, ElideHeaderValueForNetLog) {
+ // Only elide for appropriate log level.
+ EXPECT_EQ("[10 bytes were stripped]", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA, "Cookie", "name=value"));
+ EXPECT_EQ("name=value", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_ALL_BUT_BYTES, "Cookie", "name=value"));
+
+ // Headers are compared case insensitively.
+ EXPECT_EQ("[10 bytes were stripped]", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA, "cOoKiE", "name=value"));
+
+ // These headers should be completely elided.
+ EXPECT_EQ("[10 bytes were stripped]", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA, "Set-Cookie", "name=value"));
+ EXPECT_EQ("[10 bytes were stripped]", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA, "Set-Cookie2", "name=value"));
+ EXPECT_EQ("[10 bytes were stripped]", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA, "Authorization", "Basic 1234"));
+#if !defined(SPDY_PROXY_AUTH_ORIGIN)
+ EXPECT_EQ("[10 bytes were stripped]", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA,
+ "Proxy-Authorization", "Basic 1234"));
+#endif
+
+ // Unknown headers should pass through.
+ EXPECT_EQ("value", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA, "Boring", "value"));
+
+ // Basic and Digest auth challenges are public.
+ EXPECT_EQ("Basic realm=test", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA,
+ "WWW-Authenticate", "Basic realm=test"));
+ EXPECT_EQ("Digest realm=test", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA,
+ "WWW-Authenticate", "Digest realm=test"));
+#if !defined(SPDY_PROXY_AUTH_ORIGIN)
+ EXPECT_EQ("Basic realm=test", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA,
+ "Proxy-Authenticate", "Basic realm=test"));
+ EXPECT_EQ("Digest realm=test", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA,
+ "Proxy-Authenticate", "Digest realm=test"));
+#endif
+
+ // Multi-round mechanisms partially elided.
+ EXPECT_EQ("NTLM [4 bytes were stripped]", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA, "WWW-Authenticate", "NTLM 1234"));
+#if !defined(SPDY_PROXY_AUTH_ORIGIN)
+ EXPECT_EQ("NTLM [4 bytes were stripped]", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA, "Proxy-Authenticate", "NTLM 1234"));
+#endif
+
+ // Leave whitespace intact.
+ EXPECT_EQ("NTLM [4 bytes were stripped] ", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_STRIP_PRIVATE_DATA, "WWW-Authenticate", "NTLM 1234 "));
+
+ // Extra elisions for SPDY_PROXY_AUTH_ORIGIN.
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ EXPECT_EQ("[elided]", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_ALL_BUT_BYTES,
+ "Proxy-Authenticate", "Basic realm=test"));
+ EXPECT_EQ("[elided]", ElideHeaderValueForNetLog(
+ net::NetLog::LOG_ALL_BUT_BYTES, "Proxy-Authorization", "Basic 1234"));
+#endif
+}
+
+} // namspace net
diff --git a/chromium/net/http/http_network_layer.cc b/chromium/net/http/http_network_layer.cc
index 7d3f1588006..0704de420de 100644
--- a/chromium/net/http/http_network_layer.cc
+++ b/chromium/net/http/http_network_layer.cc
@@ -60,8 +60,7 @@ void HttpNetworkLayer::ForceAlternateProtocol() {
//-----------------------------------------------------------------------------
int HttpNetworkLayer::CreateTransaction(RequestPriority priority,
- scoped_ptr<HttpTransaction>* trans,
- HttpTransactionDelegate* delegate) {
+ scoped_ptr<HttpTransaction>* trans) {
if (suspended_)
return ERR_NETWORK_IO_SUSPENDED;
diff --git a/chromium/net/http/http_network_layer.h b/chromium/net/http/http_network_layer.h
index c4c41aec43e..fc94d0a7234 100644
--- a/chromium/net/http/http_network_layer.h
+++ b/chromium/net/http/http_network_layer.h
@@ -44,8 +44,7 @@ class NET_EXPORT HttpNetworkLayer
// HttpTransactionFactory methods:
virtual int CreateTransaction(RequestPriority priority,
- scoped_ptr<HttpTransaction>* trans,
- HttpTransactionDelegate* delegate) OVERRIDE;
+ scoped_ptr<HttpTransaction>* trans) OVERRIDE;
virtual HttpCache* GetCache() OVERRIDE;
virtual HttpNetworkSession* GetSession() OVERRIDE;
diff --git a/chromium/net/http/http_network_layer_unittest.cc b/chromium/net/http/http_network_layer_unittest.cc
index 98b8d4eaf44..7225001e752 100644
--- a/chromium/net/http/http_network_layer_unittest.cc
+++ b/chromium/net/http/http_network_layer_unittest.cc
@@ -11,7 +11,7 @@
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_network_session.h"
#include "net/http/http_server_properties_impl.h"
-#include "net/http/http_transaction_unittest.h"
+#include "net/http/http_transaction_test_util.h"
#include "net/http/transport_security_state.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/socket_test_util.h"
@@ -49,18 +49,6 @@ class HttpNetworkLayerTest : public PlatformTest {
factory_.reset(new HttpNetworkLayer(network_session_.get()));
}
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
- std::string GetChromeProxy() {
- return HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)).ToString();
- }
-#endif
-
-#if defined(SPDY_PROXY_AUTH_ORIGIN) && defined(DATA_REDUCTION_FALLBACK_HOST)
- std::string GetChromeFallbackProxy() {
- return HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString();
- }
-#endif
-
void ExecuteRequestExpectingContentAndHeader(const std::string& method,
const std::string& content,
const std::string& header,
@@ -73,7 +61,7 @@ class HttpNetworkLayerTest : public PlatformTest {
request_info.load_flags = LOAD_NORMAL;
scoped_ptr<HttpTransaction> trans;
- int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
+ int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
EXPECT_EQ(OK, rv);
rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
@@ -108,7 +96,7 @@ class HttpNetworkLayerTest : public PlatformTest {
// Simulates a request through a proxy which returns a bypass, which is then
// retried through a second proxy that doesn't bypass.
// Checks that the expected requests were issued, the expected content was
- // recieved, and the first proxy |bad_proxy| was marked as bad.
+ // received, and the first proxy |bad_proxy| was marked as bad.
void TestProxyFallback(const std::string& bad_proxy) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"
@@ -278,28 +266,28 @@ class HttpNetworkLayerTest : public PlatformTest {
TEST_F(HttpNetworkLayerTest, CreateAndDestroy) {
scoped_ptr<HttpTransaction> trans;
- int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
+ int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
EXPECT_EQ(OK, rv);
EXPECT_TRUE(trans.get() != NULL);
}
TEST_F(HttpNetworkLayerTest, Suspend) {
scoped_ptr<HttpTransaction> trans;
- int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
+ int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
EXPECT_EQ(OK, rv);
trans.reset();
factory_->OnSuspend();
- rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
+ rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
EXPECT_EQ(ERR_NETWORK_IO_SUSPENDED, rv);
ASSERT_TRUE(trans == NULL);
factory_->OnResume();
- rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
+ rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
EXPECT_EQ(OK, rv);
}
@@ -329,7 +317,7 @@ TEST_F(HttpNetworkLayerTest, GET) {
request_info.load_flags = LOAD_NORMAL;
scoped_ptr<HttpTransaction> trans;
- int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
+ int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
EXPECT_EQ(OK, rv);
rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
@@ -342,401 +330,6 @@ TEST_F(HttpNetworkLayerTest, GET) {
EXPECT_EQ("hello world", contents);
}
-// Proxy bypass tests. These tests run through various server-induced
-// proxy bypass scenarios using both PAC file and fixed proxy params.
-// The test scenarios are:
-// - bypass with two proxies configured and the first but not the second
-// is bypassed.
-// - bypass with one proxy configured and an explicit fallback to direct
-// connections
-// - bypass with two proxies configured and both are bypassed
-// - bypass with one proxy configured which is bypassed with no defined
-// fallback
-
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
-TEST_F(HttpNetworkLayerTest, ServerTwoProxyBypassPac) {
- std::string bad_proxy = GetChromeProxy();
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY " + bad_proxy + "; PROXY good:8080"));
- TestProxyFallback(bad_proxy);
-}
-
-TEST_F(HttpNetworkLayerTest, ServerTwoProxyBypassFixed) {
- std::string bad_proxy = GetChromeProxy();
- ConfigureTestDependencies(
- ProxyService::CreateFixed(bad_proxy +", good:8080"));
- TestProxyFallback(bad_proxy);
-}
-
-TEST_F(HttpNetworkLayerTest, BypassAndRetryIdempotentMethods) {
- std::string bad_proxy = GetChromeProxy();
- const struct {
- std::string method;
- std::string content;
- bool expected_to_retry;
- } tests[] = {
- {
- "GET",
- "content",
- true,
- },
- {
- "OPTIONS",
- "content",
- true,
- },
- {
- "HEAD",
- "",
- true,
- },
- {
- "PUT",
- "",
- true,
- },
- {
- "DELETE",
- "content",
- true,
- },
- {
- "TRACE",
- "content",
- true,
- },
- {
- "POST",
- "Bypass message",
- false,
- },
- };
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
- ConfigureTestDependencies(
- ProxyService::CreateFixed(bad_proxy +", good:8080"));
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"
- "Chrome-Proxy: bypass=0\r\n\r\n"),
- MockRead("Bypass message"),
- MockRead(SYNCHRONOUS, OK),
- };
- TestProxyFallbackByMethodWithMockReads(bad_proxy, "", data_reads,
- arraysize(data_reads),
- tests[i].method,
- tests[i].content,
- tests[i].expected_to_retry, 1u);
- }
-}
-
-TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassPac) {
- std::string bad_proxy = GetChromeProxy();
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY " + bad_proxy + "; DIRECT"));
- TestProxyFallbackToDirect(bad_proxy);
-}
-
-TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassFixed) {
- std::string bad_proxy = GetChromeProxy();
- ConfigureTestDependencies(
- ProxyService::CreateFixed(bad_proxy + ", direct://"));
- TestProxyFallbackToDirect(bad_proxy);
-}
-
-#if defined(DATA_REDUCTION_FALLBACK_HOST)
-TEST_F(HttpNetworkLayerTest, ServerTwoProxyDoubleBypassPac) {
- std::string bad_proxy = GetChromeProxy();
- std::string bad_proxy2 =
- HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString();
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY " + bad_proxy + "; PROXY " + bad_proxy2));
- TestProxyFallbackFail(2u, bad_proxy, bad_proxy2);
-}
-
-TEST_F(HttpNetworkLayerTest, ServerTwoProxyDoubleBypassFixed) {
- std::string bad_proxy = GetChromeProxy();
- std::string bad_proxy2 =
- HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString();
- ConfigureTestDependencies(ProxyService::CreateFixed(
- bad_proxy + ", " + bad_proxy2));
- TestProxyFallbackFail(2u, bad_proxy, bad_proxy2);
-}
-#endif
-
-TEST_F(HttpNetworkLayerTest, ServerOneProxyNoDirectBypassPac) {
- std::string bad_proxy = GetChromeProxy();
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY " + bad_proxy));
- TestProxyFallbackFail(1u, bad_proxy, "");
-}
-
-TEST_F(HttpNetworkLayerTest, ServerOneProxyNoDirectBypassFixed) {
- std::string bad_proxy = GetChromeProxy();
- ConfigureTestDependencies(ProxyService::CreateFixed(bad_proxy));
- TestProxyFallbackFail(1u, bad_proxy, "");
-}
-
-TEST_F(HttpNetworkLayerTest, ServerFallbackOn5xxError) {
- // Verify that "500 Internal Server Error", "502 Bad Gateway", and
- // "503 Service Unavailable" via the data reduction proxy induce proxy
- // fallback to a second proxy, if configured.
-
- // To configure this test, we need to wire up a custom proxy service to use
- // a pair of proxies. We'll induce fallback via the first and return
- // the expected data via the second.
- std::string data_reduction_proxy(
- HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)).ToString());
- std::string pac_string = base::StringPrintf(
- "PROXY %s; PROXY good:8080", data_reduction_proxy.data());
-
- std::string headers[] = {
- "HTTP/1.1 500 Internal Server Error\r\n\r\n",
- "HTTP/1.1 502 Bad Gateway\r\n\r\n",
- "HTTP/1.1 503 Service Unavailable\r\n\r\n"
- };
-
- for (size_t i = 0; i < arraysize(headers); ++i) {
- ConfigureTestDependencies(
- ProxyService::CreateFixedFromPacResult(pac_string));
-
- MockRead data_reads[] = {
- MockRead(headers[i].c_str()),
- MockRead("Bypass message"),
- MockRead(SYNCHRONOUS, OK),
- };
-
- MockWrite data_writes[] = {
- MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n"),
- };
-
- StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
- data_writes, arraysize(data_writes));
- mock_socket_factory_.AddSocketDataProvider(&data1);
-
- // Second data provider returns the expected content.
- MockRead data_reads2[] = {
- MockRead("HTTP/1.0 200 OK\r\n"
- "Server: not-proxy\r\n\r\n"),
- MockRead("content"),
- MockRead(SYNCHRONOUS, OK),
- };
- MockWrite data_writes2[] = {
- MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n"),
- };
-
- StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
- data_writes2, arraysize(data_writes2));
- mock_socket_factory_.AddSocketDataProvider(&data2);
-
- TestCompletionCallback callback;
-
- HttpRequestInfo request_info;
- request_info.url = GURL("http://www.google.com/");
- request_info.method = "GET";
- request_info.load_flags = LOAD_NORMAL;
-
- scoped_ptr<HttpTransaction> trans;
- int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(OK, rv);
-
- rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
- if (rv == ERR_IO_PENDING)
- rv = callback.WaitForResult();
- ASSERT_EQ(OK, rv);
-
- std::string contents;
- rv = ReadTransaction(trans.get(), &contents);
- EXPECT_EQ(OK, rv);
-
- // We should obtain content from the second socket provider write
- // corresponding to the fallback proxy.
- EXPECT_EQ("content", contents);
- // We also have a server header here that isn't set by the proxy.
- EXPECT_TRUE(trans->GetResponseInfo()->headers->HasHeaderValue(
- "server", "not-proxy"));
- // We should also observe the data reduction proxy in the retry list.
- ASSERT_EQ(1u, proxy_service_->proxy_retry_info().size());
- EXPECT_EQ(data_reduction_proxy,
- (*proxy_service_->proxy_retry_info().begin()).first);
- }
-}
-#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
-
-TEST_F(HttpNetworkLayerTest, ProxyBypassIgnoredOnDirectConnectionPac) {
- // Verify that a Chrome-Proxy header is ignored when returned from a directly
- // connected origin server.
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult("DIRECT"));
-
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"
- "Chrome-Proxy: bypass=0\r\n\r\n"),
- MockRead("Bypass message"),
- MockRead(SYNCHRONOUS, OK),
- };
- MockWrite data_writes[] = {
- MockWrite("GET / HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
- data_writes, arraysize(data_writes));
- mock_socket_factory_.AddSocketDataProvider(&data1);
- TestCompletionCallback callback;
-
- HttpRequestInfo request_info;
- request_info.url = GURL("http://www.google.com/");
- request_info.method = "GET";
- request_info.load_flags = LOAD_NORMAL;
-
- scoped_ptr<HttpTransaction> trans;
- int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(OK, rv);
-
- rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
- if (rv == ERR_IO_PENDING)
- rv = callback.WaitForResult();
- ASSERT_EQ(OK, rv);
-
- // We should have read the original page data.
- std::string contents;
- rv = ReadTransaction(trans.get(), &contents);
- EXPECT_EQ(OK, rv);
- EXPECT_EQ("Bypass message", contents);
-
- // We should have no entries in our bad proxy list.
- ASSERT_EQ(0u, proxy_service_->proxy_retry_info().size());
-}
-
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
-TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypass) {
- // Verify that a Chrome-Proxy: bypass=<seconds> header induces proxy
- // fallback to a second proxy, if configured.
- std::string bad_proxy = GetChromeProxy();
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY " + bad_proxy + "; PROXY good:8080"));
-
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"
- "Connection: keep-alive\r\n"
- "Chrome-Proxy: bypass=86400\r\n"
- "Via: 1.1 Chrome Compression Proxy\r\n\r\n"),
- MockRead("Bypass message"),
- MockRead(SYNCHRONOUS, OK),
- };
-
- TestProxyFallbackWithMockReads(bad_proxy, "", data_reads,
- arraysize(data_reads), 1u);
- EXPECT_EQ(base::TimeDelta::FromSeconds(86400),
- (*proxy_service_->proxy_retry_info().begin()).second.current_delay);
-}
-
-TEST_F(HttpNetworkLayerTest, ServerFallbackWithWrongViaHeader) {
- // Verify that a Via header that lacks the Chrome-Proxy induces proxy fallback
- // to a second proxy, if configured.
- std::string chrome_proxy = GetChromeProxy();
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY " + chrome_proxy + "; PROXY good:8080"));
-
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"
- "Connection: keep-alive\r\n"
- "Via: 1.0 some-other-proxy\r\n\r\n"),
- MockRead("Bypass message"),
- MockRead(SYNCHRONOUS, OK),
- };
-
- TestProxyFallbackWithMockReads(chrome_proxy, std::string(), data_reads,
- arraysize(data_reads), 1u);
-}
-
-TEST_F(HttpNetworkLayerTest, ServerFallbackWithNoViaHeader) {
- // Verify that the lack of a Via header induces proxy fallback to a second
- // proxy, if configured.
- std::string chrome_proxy = GetChromeProxy();
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY " + chrome_proxy + "; PROXY good:8080"));
-
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockRead("Bypass message"),
- MockRead(SYNCHRONOUS, OK),
- };
-
- TestProxyFallbackWithMockReads(chrome_proxy, std::string(), data_reads,
- arraysize(data_reads), 1u);
-}
-
-TEST_F(HttpNetworkLayerTest, NoServerFallbackWith304Response) {
- // Verify that Chrome will not be induced to bypass the Chrome proxy when
- // the Chrome Proxy via header is absent on a 304.
- std::string chrome_proxy = GetChromeProxy();
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY " + chrome_proxy + "; PROXY good:8080"));
-
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 304 Not Modified\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockRead(SYNCHRONOUS, OK),
- };
-
- TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(),
- data_reads, arraysize(data_reads),
- "GET", std::string(), false, 0);
-}
-
-TEST_F(HttpNetworkLayerTest, NoServerFallbackWithChainedViaHeader) {
- // Verify that Chrome will not be induced to bypass the Chrome proxy when
- // the Chrome Proxy via header is present, even if that header is chained.
- std::string chrome_proxy = GetChromeProxy();
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY " + chrome_proxy + "; PROXY good:8080"));
-
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"
- "Connection: keep-alive\r\n"
- "Via: 1.1 Chrome Compression Proxy, 1.0 some-other-proxy\r\n\r\n"),
- MockRead("Bypass message"),
- MockRead(SYNCHRONOUS, OK),
- };
-
- TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(),
- data_reads, arraysize(data_reads),
- "GET", "Bypass message", false, 0);
-}
-
-#if defined(DATA_REDUCTION_FALLBACK_HOST)
-TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypassAll) {
- // Verify that a Chrome-Proxy: block=<seconds> header bypasses a
- // a configured Chrome-Proxy and fallback and induces proxy fallback to a
- // third proxy, if configured.
- std::string bad_proxy = GetChromeProxy();
- std::string fallback_proxy = GetChromeFallbackProxy();
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY " + bad_proxy + "; PROXY " + fallback_proxy +
- "; PROXY good:8080"));
-
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"
- "Connection: keep-alive\r\n"
- "Chrome-Proxy: block=86400\r\n"
- "Via: 1.1 Chrome Compression Proxy\r\n\r\n"),
- MockRead("Bypass message"),
- MockRead(SYNCHRONOUS, OK),
- };
-
- TestProxyFallbackWithMockReads(bad_proxy, fallback_proxy, data_reads,
- arraysize(data_reads), 2u);
- EXPECT_EQ(base::TimeDelta::FromSeconds(86400),
- (*proxy_service_->proxy_retry_info().begin()).second.current_delay);
-}
-#endif // defined(DATA_REDUCTION_FALLBACK_HOST)
-#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
-
TEST_F(HttpNetworkLayerTest, NetworkVerified) {
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n\r\n"),
@@ -763,7 +356,7 @@ TEST_F(HttpNetworkLayerTest, NetworkVerified) {
request_info.load_flags = LOAD_NORMAL;
scoped_ptr<HttpTransaction> trans;
- int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
+ int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
EXPECT_EQ(OK, rv);
rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
@@ -796,7 +389,7 @@ TEST_F(HttpNetworkLayerTest, NetworkUnVerified) {
request_info.load_flags = LOAD_NORMAL;
scoped_ptr<HttpTransaction> trans;
- int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
+ int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
EXPECT_EQ(OK, rv);
rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
diff --git a/chromium/net/http/http_network_session.cc b/chromium/net/http/http_network_session.cc
index 1be93fe5c3f..b4e373e5de7 100644
--- a/chromium/net/http/http_network_session.cc
+++ b/chromium/net/http/http_network_session.cc
@@ -24,6 +24,7 @@
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_pool_manager_impl.h"
#include "net/socket/next_proto.h"
+#include "net/spdy/hpack_huffman_aggregator.h"
#include "net/spdy/spdy_session_pool.h"
namespace {
@@ -66,13 +67,10 @@ HttpNetworkSession::Params::Params()
network_delegate(NULL),
net_log(NULL),
host_mapping_rules(NULL),
- force_http_pipelining(false),
ignore_certificate_errors(false),
- http_pipelining_enabled(false),
testing_fixed_http_port(0),
testing_fixed_https_port(0),
force_spdy_single_domain(false),
- enable_spdy_ip_pooling(true),
enable_spdy_compression(true),
enable_spdy_ping_based_connection_checking(true),
spdy_default_protocol(kProtoUnknown),
@@ -80,13 +78,22 @@ HttpNetworkSession::Params::Params()
spdy_initial_max_concurrent_streams(0),
spdy_max_concurrent_streams_limit(0),
time_func(&base::TimeTicks::Now),
+ force_spdy_over_ssl(true),
+ force_spdy_always(false),
+ use_alternate_protocols(false),
+ enable_websocket_over_spdy(false),
enable_quic(false),
enable_quic_https(false),
+ enable_quic_port_selection(true),
+ enable_quic_pacing(false),
+ enable_quic_time_based_loss_detection(false),
+ enable_quic_persist_server_info(true),
quic_clock(NULL),
quic_random(NULL),
quic_max_packet_length(kDefaultMaxPacketSize),
enable_user_alternate_protocol_ports(false),
quic_crypto_client_stream_factory(NULL) {
+ quic_supported_versions.push_back(QUIC_VERSION_18);
}
HttpNetworkSession::Params::~Params() {}
@@ -98,7 +105,6 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
http_server_properties_(params.http_server_properties),
cert_verifier_(params.cert_verifier),
http_auth_handler_factory_(params.http_auth_handler_factory),
- force_http_pipelining_(params.force_http_pipelining),
proxy_service_(params.proxy_service),
ssl_config_service_(params.ssl_config_service),
normal_socket_pool_manager_(
@@ -110,17 +116,22 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
params.client_socket_factory :
net::ClientSocketFactory::GetDefaultFactory(),
params.http_server_properties,
+ params.cert_verifier,
params.quic_crypto_client_stream_factory,
params.quic_random ? params.quic_random :
QuicRandom::GetInstance(),
params.quic_clock ? params. quic_clock :
new QuicClock(),
- params.quic_max_packet_length),
+ params.quic_max_packet_length,
+ params.quic_user_agent_id,
+ params.quic_supported_versions,
+ params.enable_quic_port_selection,
+ params.enable_quic_pacing,
+ params.enable_quic_time_based_loss_detection),
spdy_session_pool_(params.host_resolver,
params.ssl_config_service,
params.http_server_properties,
params.force_spdy_single_domain,
- params.enable_spdy_ip_pooling,
params.enable_spdy_compression,
params.enable_spdy_ping_based_connection_checking,
params.spdy_default_protocol,
@@ -136,6 +147,40 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
DCHECK(proxy_service_);
DCHECK(ssl_config_service_.get());
CHECK(http_server_properties_);
+
+ for (int i = ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION;
+ i <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION; ++i) {
+ enabled_protocols_[i - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] = false;
+ }
+
+ // TODO(rtenneti): bug 116575 - consider combining the NextProto and
+ // AlternateProtocol.
+ for (std::vector<NextProto>::const_iterator it = params_.next_protos.begin();
+ it != params_.next_protos.end(); ++it) {
+ NextProto proto = *it;
+
+ // Add the protocol to the TLS next protocol list, except for QUIC
+ // since it uses UDP.
+ if (proto != kProtoQUIC1SPDY3) {
+ next_protos_.push_back(SSLClientSocket::NextProtoToString(proto));
+ }
+
+ // Enable the corresponding alternate protocol, except for HTTP
+ // which has not corresponding alternative.
+ if (proto != kProtoHTTP11) {
+ AlternateProtocol alternate = AlternateProtocolFromNextProto(proto);
+ if (!IsAlternateProtocolValid(alternate)) {
+ NOTREACHED() << "Invalid next proto: " << proto;
+ continue;
+ }
+ enabled_protocols_[alternate - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] =
+ true;
+ }
+ }
+
+ if (HpackHuffmanAggregator::UseAggregator()) {
+ huffman_aggregator_.reset(new HpackHuffmanAggregator());
+ }
}
HttpNetworkSession::~HttpNetworkSession() {
@@ -198,6 +243,14 @@ base::Value* HttpNetworkSession::QuicInfoToValue() const {
dict->Set("sessions", quic_stream_factory_.QuicStreamFactoryInfoToValue());
dict->SetBoolean("quic_enabled", params_.enable_quic);
dict->SetBoolean("quic_enabled_https", params_.enable_quic_https);
+ dict->SetBoolean("enable_quic_port_selection",
+ params_.enable_quic_port_selection);
+ dict->SetBoolean("enable_quic_pacing",
+ params_.enable_quic_pacing);
+ dict->SetBoolean("enable_quic_time_based_loss_detection",
+ params_.enable_quic_time_based_loss_detection);
+ dict->SetBoolean("enable_quic_persist_server_info",
+ params_.enable_quic_persist_server_info);
dict->SetString("origin_to_force_quic_on",
params_.origin_to_force_quic_on.ToString());
return dict;
@@ -216,6 +269,27 @@ void HttpNetworkSession::CloseIdleConnections() {
spdy_session_pool_.CloseCurrentIdleSessions();
}
+bool HttpNetworkSession::IsProtocolEnabled(AlternateProtocol protocol) const {
+ DCHECK(IsAlternateProtocolValid(protocol));
+ return enabled_protocols_[
+ protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION];
+}
+
+void HttpNetworkSession::GetNextProtos(
+ std::vector<std::string>* next_protos) const {
+ if (HttpStreamFactory::spdy_enabled()) {
+ *next_protos = next_protos_;
+ } else {
+ next_protos->clear();
+ }
+}
+
+bool HttpNetworkSession::HasSpdyExclusion(
+ HostPortPair host_port_pair) const {
+ return params_.forced_spdy_exclusions.find(host_port_pair) !=
+ params_.forced_spdy_exclusions.end();
+}
+
ClientSocketPoolManager* HttpNetworkSession::GetSocketPoolManager(
SocketPoolType pool_type) {
switch (pool_type) {
diff --git a/chromium/net/http/http_network_session.h b/chromium/net/http/http_network_session.h
index 471041220ec..b877b08081a 100644
--- a/chromium/net/http/http_network_session.h
+++ b/chromium/net/http/http_network_session.h
@@ -7,6 +7,7 @@
#include <set>
#include <string>
+#include <vector>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
@@ -18,6 +19,7 @@
#include "net/http/http_auth_cache.h"
#include "net/http/http_stream_factory.h"
#include "net/quic/quic_stream_factory.h"
+#include "net/socket/next_proto.h"
#include "net/spdy/spdy_session_pool.h"
#include "net/ssl/ssl_client_auth_cache.h"
@@ -30,7 +32,9 @@ namespace net {
class CertVerifier;
class ClientSocketFactory;
class ClientSocketPoolManager;
+class CTVerifier;
class HostResolver;
+class HpackHuffmanAggregator;
class HttpAuthHandlerFactory;
class HttpNetworkSessionPeer;
class HttpProxyClientSocketPool;
@@ -42,6 +46,7 @@ class ServerBoundCertService;
class ProxyService;
class QuicClock;
class QuicCryptoClientStreamFactory;
+class QuicServerInfoFactory;
class SOCKSClientSocketPool;
class SSLClientSocketPool;
class SSLConfigService;
@@ -71,29 +76,50 @@ class NET_EXPORT HttpNetworkSession
base::WeakPtr<HttpServerProperties> http_server_properties;
NetLog* net_log;
HostMappingRules* host_mapping_rules;
- bool force_http_pipelining;
bool ignore_certificate_errors;
- bool http_pipelining_enabled;
uint16 testing_fixed_http_port;
uint16 testing_fixed_https_port;
+
bool force_spdy_single_domain;
- bool enable_spdy_ip_pooling;
bool enable_spdy_compression;
bool enable_spdy_ping_based_connection_checking;
NextProto spdy_default_protocol;
+ // The protocols supported by NPN (next protocol negotiation) during the
+ // SSL handshake as well as by HTTP Alternate-Protocol.
+ // TODO(mmenke): This is currently empty by default, and alternate
+ // protocols are disabled. We should use some reasonable
+ // defaults.
+ NextProtoVector next_protos;
size_t spdy_stream_initial_recv_window_size;
size_t spdy_initial_max_concurrent_streams;
size_t spdy_max_concurrent_streams_limit;
SpdySessionPool::TimeFunc time_func;
std::string trusted_spdy_proxy;
+ // Controls whether or not ssl is used when in SPDY mode.
+ bool force_spdy_over_ssl;
+ // Controls whether or not SPDY is used without NPN.
+ bool force_spdy_always;
+ // URLs to exclude from forced SPDY.
+ std::set<HostPortPair> forced_spdy_exclusions;
+ // Noe: Using this in the case of NPN for HTTP only results in the browser
+ // trying SSL and then falling back to http.
+ bool use_alternate_protocols;
+ bool enable_websocket_over_spdy;
+
bool enable_quic;
bool enable_quic_https;
+ bool enable_quic_port_selection;
+ bool enable_quic_pacing;
+ bool enable_quic_time_based_loss_detection;
+ bool enable_quic_persist_server_info;
HostPortPair origin_to_force_quic_on;
QuicClock* quic_clock; // Will be owned by QuicStreamFactory.
QuicRandom* quic_random;
size_t quic_max_packet_length;
+ std::string quic_user_agent_id;
bool enable_user_alternate_protocol_ports;
QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory;
+ QuicVersionVector quic_supported_versions;
};
enum SocketPoolType {
@@ -148,6 +174,9 @@ class NET_EXPORT HttpNetworkSession
NetLog* net_log() {
return net_log_;
}
+ HpackHuffmanAggregator* huffman_aggregator() {
+ return huffman_aggregator_.get();
+ }
// Creates a Value summary of the state of the socket pools. The caller is
// responsible for deleting the returned value.
@@ -164,14 +193,16 @@ class NET_EXPORT HttpNetworkSession
void CloseAllConnections();
void CloseIdleConnections();
- bool force_http_pipelining() const { return force_http_pipelining_; }
-
// Returns the original Params used to construct this session.
const Params& params() const { return params_; }
- void set_http_pipelining_enabled(bool enable) {
- params_.http_pipelining_enabled = enable;
- }
+ bool IsProtocolEnabled(AlternateProtocol protocol) const;
+
+ void GetNextProtos(std::vector<std::string>* next_protos) const;
+
+ // Convenience function for searching through |params_| for
+ // |forced_spdy_exclusions|.
+ bool HasSpdyExclusion(HostPortPair host_port_pair) const;
private:
friend class base::RefCounted<HttpNetworkSession>;
@@ -186,7 +217,6 @@ class NET_EXPORT HttpNetworkSession
const base::WeakPtr<HttpServerProperties> http_server_properties_;
CertVerifier* const cert_verifier_;
HttpAuthHandlerFactory* const http_auth_handler_factory_;
- bool force_http_pipelining_;
// Not const since it's modified by HttpNetworkSessionPeer for testing.
ProxyService* proxy_service_;
@@ -202,6 +232,12 @@ class NET_EXPORT HttpNetworkSession
scoped_ptr<HttpStreamFactory> http_stream_factory_for_websocket_;
std::set<HttpResponseBodyDrainer*> response_drainers_;
+ // TODO(jgraettinger): Remove when Huffman collection is complete.
+ scoped_ptr<HpackHuffmanAggregator> huffman_aggregator_;
+
+ std::vector<std::string> next_protos_;
+ bool enabled_protocols_[NUM_VALID_ALTERNATE_PROTOCOLS];
+
Params params_;
};
diff --git a/chromium/net/http/http_network_transaction.cc b/chromium/net/http/http_network_transaction.cc
index d7b3f41ff76..32af2dd1844 100644
--- a/chromium/net/http/http_network_transaction.cc
+++ b/chromium/net/http/http_network_transaction.cc
@@ -54,6 +54,7 @@
#include "net/socket/ssl_client_socket.h"
#include "net/socket/ssl_client_socket_pool.h"
#include "net/socket/transport_client_socket_pool.h"
+#include "net/spdy/hpack_huffman_aggregator.h"
#include "net/spdy/spdy_http_stream.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_session_pool.h"
@@ -75,8 +76,7 @@ namespace net {
namespace {
void ProcessAlternateProtocol(
- HttpStreamFactory* factory,
- const base::WeakPtr<HttpServerProperties>& http_server_properties,
+ HttpNetworkSession* session,
const HttpResponseHeaders& headers,
const HostPortPair& http_host_port_pair) {
std::string alternate_protocol_str;
@@ -87,9 +87,11 @@ void ProcessAlternateProtocol(
return;
}
- factory->ProcessAlternateProtocol(http_server_properties,
- alternate_protocol_str,
- http_host_port_pair);
+ session->http_stream_factory()->ProcessAlternateProtocol(
+ session->http_server_properties(),
+ alternate_protocol_str,
+ http_host_port_pair,
+ *session);
}
// Returns true if |error| is a client certificate authentication error.
@@ -119,30 +121,6 @@ base::Value* NetLogSSLVersionFallbackCallback(
return dict;
}
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
-// Returns true if |response_headers| contains the data reduction proxy Via
-// header value.
-bool IsChromeProxyResponse(const net::HttpResponseHeaders* response_headers) {
- if (!response_headers) {
- return false;
- }
- const char kDataReductionProxyViaValue[] = "1.1 Chrome Compression Proxy";
- size_t value_len = strlen(kDataReductionProxyViaValue);
- void* iter = NULL;
- std::string temp;
- while (response_headers->EnumerateHeader(&iter, "Via", &temp)) {
- std::string::const_iterator it =
- std::search(temp.begin(), temp.end(),
- kDataReductionProxyViaValue,
- kDataReductionProxyViaValue + value_len,
- base::CaseInsensitiveCompareASCII<char>());
- if (it != temp.end())
- return true;
- }
- return false;
-}
-#endif
-
} // namespace
//-----------------------------------------------------------------------------
@@ -160,14 +138,12 @@ HttpNetworkTransaction::HttpNetworkTransaction(RequestPriority priority,
fallback_error_code_(ERR_SSL_INAPPROPRIATE_FALLBACK),
request_headers_(),
read_buf_len_(0),
+ total_received_bytes_(0),
next_state_(STATE_NONE),
establishing_tunnel_(false),
websocket_handshake_stream_base_create_helper_(NULL) {
session->ssl_config_service()->GetSSLConfig(&server_ssl_config_);
- if (session->http_stream_factory()->has_next_protos()) {
- server_ssl_config_.next_protos =
- session->http_stream_factory()->next_protos();
- }
+ session->GetNextProtos(&server_ssl_config_.next_protos);
proxy_ssl_config_ = server_ssl_config_;
}
@@ -216,13 +192,11 @@ int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
proxy_ssl_config_.rev_checking_enabled = false;
}
- // Channel ID is enabled unless --disable-tls-channel-id flag is set,
- // or if privacy mode is enabled.
- bool channel_id_enabled = server_ssl_config_.channel_id_enabled &&
- (request_->privacy_mode == kPrivacyModeDisabled);
- server_ssl_config_.channel_id_enabled = channel_id_enabled;
+ // Channel ID is disabled if privacy mode is enabled for this request.
+ if (request_->privacy_mode == PRIVACY_MODE_ENABLED)
+ server_ssl_config_.channel_id_enabled = false;
- next_state_ = STATE_CREATE_STREAM;
+ next_state_ = STATE_NOTIFY_BEFORE_CREATE_STREAM;
int rv = DoLoop(OK);
if (rv == ERR_IO_PENDING)
callback_ = callback;
@@ -331,6 +305,7 @@ void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
DCHECK(!stream_request_.get());
if (stream_.get()) {
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
HttpStream* new_stream = NULL;
if (keep_alive && stream_->IsConnectionReusable()) {
// We should call connection_->set_idle_time(), but this doesn't occur
@@ -347,6 +322,8 @@ void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
stream_->Close(true);
next_state_ = STATE_CREATE_STREAM;
} else {
+ // Renewed streams shouldn't carry over received bytes.
+ DCHECK_EQ(0, new_stream->GetTotalReceivedBytes());
next_state_ = STATE_INIT_STREAM;
}
stream_.reset(new_stream);
@@ -400,6 +377,8 @@ int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
return rv;
}
+void HttpNetworkTransaction::StopCaching() {}
+
bool HttpNetworkTransaction::GetFullRequestHeaders(
HttpRequestHeaders* headers) const {
// TODO(ttuttle): Make sure we've populated request_headers_.
@@ -407,6 +386,15 @@ bool HttpNetworkTransaction::GetFullRequestHeaders(
return true;
}
+int64 HttpNetworkTransaction::GetTotalReceivedBytes() const {
+ int64 total_received_bytes = total_received_bytes_;
+ if (stream_)
+ total_received_bytes += stream_->GetTotalReceivedBytes();
+ return total_received_bytes;
+}
+
+void HttpNetworkTransaction::DoneReading() {}
+
const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
return ((headers_valid_ && response_.headers.get()) ||
response_.ssl_info.cert.get() || response_.cert_request_info.get())
@@ -418,6 +406,8 @@ LoadState HttpNetworkTransaction::GetLoadState() const {
// TODO(wtc): Define a new LoadState value for the
// STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
switch (next_state_) {
+ case STATE_CREATE_STREAM:
+ return LOAD_STATE_WAITING_FOR_DELEGATE;
case STATE_CREATE_STREAM_COMPLETE:
return stream_request_->GetLoadState();
case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
@@ -441,6 +431,9 @@ UploadProgress HttpNetworkTransaction::GetUploadProgress() const {
return static_cast<HttpStream*>(stream_.get())->GetUploadProgress();
}
+void HttpNetworkTransaction::SetQuicServerInfo(
+ QuicServerInfo* quic_server_info) {}
+
bool HttpNetworkTransaction::GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const {
if (!stream_ || !stream_->GetLoadTimingInfo(load_timing_info))
@@ -467,12 +460,24 @@ void HttpNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
websocket_handshake_stream_base_create_helper_ = create_helper;
}
+void HttpNetworkTransaction::SetBeforeNetworkStartCallback(
+ const BeforeNetworkStartCallback& callback) {
+ before_network_start_callback_ = callback;
+}
+
+int HttpNetworkTransaction::ResumeNetworkStart() {
+ DCHECK_EQ(next_state_, STATE_CREATE_STREAM);
+ return DoLoop(OK);
+}
+
void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStreamBase* stream) {
DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
DCHECK(stream_request_.get());
+ if (stream_)
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
stream_.reset(stream);
server_ssl_config_ = used_ssl_config;
proxy_info_ = used_proxy_info;
@@ -481,7 +486,8 @@ void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
stream_request_->protocol_negotiated());
response_.was_fetched_via_spdy = stream_request_->using_spdy();
response_.was_fetched_via_proxy = !proxy_info_.is_direct();
-
+ if (response_.was_fetched_via_proxy && !proxy_info_.is_empty())
+ response_.proxy_server = proxy_info_.proxy_server().host_port_pair();
OnIOComplete(OK);
}
@@ -566,6 +572,8 @@ void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
response_ = response_info;
server_ssl_config_ = used_ssl_config;
proxy_info_ = used_proxy_info;
+ if (stream_)
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
stream_.reset(stream);
stream_request_.reset(); // we're done with the stream request
OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
@@ -599,6 +607,10 @@ int HttpNetworkTransaction::DoLoop(int result) {
State state = next_state_;
next_state_ = STATE_NONE;
switch (state) {
+ case STATE_NOTIFY_BEFORE_CREATE_STREAM:
+ DCHECK_EQ(OK, rv);
+ rv = DoNotifyBeforeCreateStream();
+ break;
case STATE_CREATE_STREAM:
DCHECK_EQ(OK, rv);
rv = DoCreateStream();
@@ -692,9 +704,18 @@ int HttpNetworkTransaction::DoLoop(int result) {
return rv;
}
+int HttpNetworkTransaction::DoNotifyBeforeCreateStream() {
+ next_state_ = STATE_CREATE_STREAM;
+ bool defer = false;
+ if (!before_network_start_callback_.is_null())
+ before_network_start_callback_.Run(&defer);
+ if (!defer)
+ return OK;
+ return ERR_IO_PENDING;
+}
+
int HttpNetworkTransaction::DoCreateStream() {
next_state_ = STATE_CREATE_STREAM_COMPLETE;
-
if (ForWebSocketHandshake()) {
stream_request_.reset(
session_->http_stream_factory_for_websocket()
@@ -755,6 +776,8 @@ int HttpNetworkTransaction::DoInitStreamComplete(int result) {
result = HandleIOError(result);
// The stream initialization failed, so this stream will never be useful.
+ if (stream_)
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
stream_.reset();
}
@@ -918,16 +941,6 @@ int HttpNetworkTransaction::DoReadHeaders() {
return stream_->ReadResponseHeaders(io_callback_);
}
-int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
- if (!response_.headers.get() && !stream_->IsConnectionReused()) {
- // The connection was closed before any data was sent. Likely an error
- // rather than empty HTTP/0.9 response.
- return ERR_EMPTY_RESPONSE;
- }
-
- return OK;
-}
-
int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
// We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
// due to SSL renegotiation.
@@ -954,108 +967,40 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
return OK;
}
- if (result < 0 && result != ERR_CONNECTION_CLOSED)
- return HandleIOError(result);
-
- if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
- ResetConnectionAndRequestForResend();
- return OK;
- }
-
// After we call RestartWithAuth a new response_time will be recorded, and
// we need to be cautious about incorrectly logging the duration across the
// authentication activity.
if (result == OK)
LogTransactionConnectedMetrics();
- if (result == ERR_CONNECTION_CLOSED) {
- // For now, if we get at least some data, we do the best we can to make
- // sense of it and send it back up the stack.
- int rv = HandleConnectionClosedBeforeEndOfHeaders();
- if (rv != OK)
- return rv;
- }
- DCHECK(response_.headers.get());
+ // ERR_CONNECTION_CLOSED is treated differently at this point; if partial
+ // response headers were received, we do the best we can to make sense of it
+ // and send it back up the stack.
+ //
+ // TODO(davidben): Consider moving this to HttpBasicStream, It's a little
+ // bizarre for SPDY. Assuming this logic is useful at all.
+ // TODO(davidben): Bubble the error code up so we do not cache?
+ if (result == ERR_CONNECTION_CLOSED && response_.headers.get())
+ result = OK;
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
- // Server-induced fallback; see: http://crbug.com/143712
- if (response_.was_fetched_via_proxy && response_.headers.get() != NULL) {
- ProxyService::DataReductionProxyBypassEventType proxy_bypass_event =
- ProxyService::BYPASS_EVENT_TYPE_MAX;
- net::HttpResponseHeaders::ChromeProxyInfo chrome_proxy_info;
- bool chrome_proxy_used =
- proxy_info_.proxy_server().isDataReductionProxy();
- bool chrome_fallback_proxy_used = false;
-#if defined(DATA_REDUCTION_FALLBACK_HOST)
- if (!chrome_proxy_used) {
- chrome_fallback_proxy_used =
- proxy_info_.proxy_server().isDataReductionProxyFallback();
- }
-#endif
+ if (result < 0)
+ return HandleIOError(result);
- if (chrome_proxy_used || chrome_fallback_proxy_used) {
- // A Via header might not be present in a 304. Since the goal of a 304
- // response is to minimize information transfer, a sender in general
- // should not generate representation metadata other than Cache-Control,
- // Content-Location, Date, ETag, Expires, and Vary.
- if (!IsChromeProxyResponse(response_.headers.get()) &&
- (response_.headers->response_code() != HTTP_NOT_MODIFIED)) {
- proxy_bypass_event = ProxyService::MISSING_VIA_HEADER;
- } else if (response_.headers->GetChromeProxyInfo(&chrome_proxy_info)) {
- if (chrome_proxy_info.bypass_duration < TimeDelta::FromMinutes(30))
- proxy_bypass_event = ProxyService::SHORT_BYPASS;
- else
- proxy_bypass_event = ProxyService::LONG_BYPASS;
- } else {
- // Additionally, fallback if a 500, 502 or 503 is returned via the data
- // reduction proxy. This is conservative, as the 500, 502 or 503 might
- // have been generated by the origin, and not the proxy.
- if (response_.headers->response_code() == HTTP_INTERNAL_SERVER_ERROR ||
- response_.headers->response_code() == HTTP_BAD_GATEWAY ||
- response_.headers->response_code() == HTTP_SERVICE_UNAVAILABLE) {
- proxy_bypass_event = ProxyService::INTERNAL_SERVER_ERROR_BYPASS;
- }
- }
+ DCHECK(response_.headers.get());
- if (proxy_bypass_event < ProxyService::BYPASS_EVENT_TYPE_MAX) {
- ProxyService* proxy_service = session_->proxy_service();
-
- proxy_service->RecordDataReductionProxyBypassInfo(
- chrome_proxy_used, proxy_info_.proxy_server(), proxy_bypass_event);
-
- ProxyServer proxy_server;
-#if defined(DATA_REDUCTION_FALLBACK_HOST)
- if (chrome_proxy_used && chrome_proxy_info.bypass_all) {
- // TODO(bengr): Rename as DATA_REDUCTION_FALLBACK_ORIGIN.
- GURL proxy_url(DATA_REDUCTION_FALLBACK_HOST);
- if (proxy_url.SchemeIsHTTPOrHTTPS()) {
- proxy_server = ProxyServer(proxy_url.SchemeIs("http") ?
- ProxyServer::SCHEME_HTTP :
- ProxyServer::SCHEME_HTTPS,
- HostPortPair::FromURL(proxy_url));
- }
- }
-#endif
- if (proxy_service->MarkProxiesAsBad(proxy_info_,
- chrome_proxy_info.bypass_duration,
- proxy_server,
- net_log_)) {
- // Only retry idempotent methods. We don't want to resubmit a POST
- // if the proxy took some action.
- if (request_->method == "GET" ||
- request_->method == "OPTIONS" ||
- request_->method == "HEAD" ||
- request_->method == "PUT" ||
- request_->method == "DELETE" ||
- request_->method == "TRACE") {
- ResetConnectionAndRequestForResend();
- return OK;
- }
- }
- }
- }
+ // On a 408 response from the server ("Request Timeout") on a stale socket,
+ // retry the request.
+ // Headers can be NULL because of http://crbug.com/384554.
+ if (response_.headers.get() && response_.headers->response_code() == 408 &&
+ stream_->IsConnectionReused()) {
+ net_log_.AddEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR,
+ response_.headers->response_code());
+ // This will close the socket - it would be weird to try and reuse it, even
+ // if the server doesn't actually close it.
+ ResetConnectionAndRequestForResend();
+ return OK;
}
-#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
// Like Net.HttpResponseCode, but only for MAIN_FRAME loads.
if (request_->load_flags & LOAD_MAIN_FRAME) {
@@ -1091,8 +1036,7 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
HostPortPair endpoint = HostPortPair(request_->url.HostNoBrackets(),
request_->url.EffectiveIntPort());
- ProcessAlternateProtocol(session_->http_stream_factory(),
- session_->http_server_properties(),
+ ProcessAlternateProtocol(session_,
*response_.headers.get(),
endpoint);
@@ -1104,6 +1048,14 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
stream_->GetSSLInfo(&response_.ssl_info);
headers_valid_ = true;
+
+ if (session_->huffman_aggregator()) {
+ session_->huffman_aggregator()->AggregateTransactionCharacterCounts(
+ *request_,
+ request_headers_,
+ proxy_info_.proxy_server(),
+ *response_.headers);
+ }
return OK;
}
@@ -1280,6 +1232,7 @@ int HttpNetworkTransaction::HandleCertificateRequest(int error) {
// Since we already have a stream, we're being called as part of SSL
// renegotiation.
DCHECK(!stream_request_.get());
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
stream_->Close(true);
stream_.reset();
}
@@ -1328,7 +1281,7 @@ void HttpNetworkTransaction::HandleClientAuthError(int error) {
if (server_ssl_config_.send_client_cert &&
(error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) {
session_->ssl_client_auth_cache()->Remove(
- GetHostAndPort(request_->url));
+ HostPortPair::FromURL(request_->url));
}
}
@@ -1428,15 +1381,11 @@ int HttpNetworkTransaction::HandleIOError(int error) {
// likely happen when trying to retrieve its IP address.
// See http://crbug.com/105824 for more details.
case ERR_SOCKET_NOT_CONNECTED:
- if (ShouldResendRequest(error)) {
- net_log_.AddEventWithNetErrorCode(
- NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
- ResetConnectionAndRequestForResend();
- error = OK;
- }
- break;
- case ERR_PIPELINE_EVICTION:
- if (!session_->force_http_pipelining()) {
+ // If a socket is closed on its initial request, HttpStreamParser returns
+ // ERR_EMPTY_RESPONSE. This may still be close/reuse race if the socket was
+ // preconnected but failed to be used before the server timed it out.
+ case ERR_EMPTY_RESPONSE:
+ if (ShouldResendRequest()) {
net_log_.AddEventWithNetErrorCode(
NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
ResetConnectionAndRequestForResend();
@@ -1457,6 +1406,8 @@ int HttpNetworkTransaction::HandleIOError(int error) {
void HttpNetworkTransaction::ResetStateForRestart() {
ResetStateForAuthRestart();
+ if (stream_)
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
stream_.reset();
}
@@ -1477,7 +1428,7 @@ HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
return response_.headers.get();
}
-bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
+bool HttpNetworkTransaction::ShouldResendRequest() const {
bool connection_is_proven = stream_->IsConnectionReused();
bool has_received_headers = GetResponseHeaders() != NULL;
@@ -1580,6 +1531,7 @@ bool HttpNetworkTransaction::ForWebSocketHandshake() const {
std::string HttpNetworkTransaction::DescribeState(State state) {
std::string description;
switch (state) {
+ STATE_CASE(STATE_NOTIFY_BEFORE_CREATE_STREAM);
STATE_CASE(STATE_CREATE_STREAM);
STATE_CASE(STATE_CREATE_STREAM_COMPLETE);
STATE_CASE(STATE_INIT_REQUEST_BODY);
diff --git a/chromium/net/http/http_network_transaction.h b/chromium/net/http/http_network_transaction.h
index 3ae1725d1de..24ab95b8ac2 100644
--- a/chromium/net/http/http_network_transaction.h
+++ b/chromium/net/http/http_network_transaction.h
@@ -59,18 +59,23 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
virtual int Read(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) OVERRIDE;
- virtual void StopCaching() OVERRIDE {}
+ virtual void StopCaching() OVERRIDE;
virtual bool GetFullRequestHeaders(
HttpRequestHeaders* headers) const OVERRIDE;
- virtual void DoneReading() OVERRIDE {}
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
+ virtual void DoneReading() OVERRIDE;
virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE;
virtual LoadState GetLoadState() const OVERRIDE;
virtual UploadProgress GetUploadProgress() const OVERRIDE;
+ virtual void SetQuicServerInfo(QuicServerInfo* quic_server_info) OVERRIDE;
virtual bool GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const OVERRIDE;
virtual void SetPriority(RequestPriority priority) OVERRIDE;
virtual void SetWebSocketHandshakeStreamCreateHelper(
WebSocketHandshakeStreamBase::CreateHelper* create_helper) OVERRIDE;
+ virtual void SetBeforeNetworkStartCallback(
+ const BeforeNetworkStartCallback& callback) OVERRIDE;
+ virtual int ResumeNetworkStart() OVERRIDE;
// HttpStreamRequest::Delegate methods:
virtual void OnStreamReady(const SSLConfig& used_ssl_config,
@@ -116,6 +121,7 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
FlowControlNegativeSendWindowSize);
enum State {
+ STATE_NOTIFY_BEFORE_CREATE_STREAM,
STATE_CREATE_STREAM,
STATE_CREATE_STREAM_COMPLETE,
STATE_INIT_STREAM,
@@ -151,6 +157,7 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
// argument receive the result from the previous state. If a method returns
// ERR_IO_PENDING, then the result from OnIOComplete will be passed to the
// next state method as the result arg.
+ int DoNotifyBeforeCreateStream();
int DoCreateStream();
int DoCreateStreamComplete(int result);
int DoInitStream();
@@ -203,19 +210,14 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
// Gets the response headers from the HttpStream.
HttpResponseHeaders* GetResponseHeaders() const;
- // Called when we reached EOF or got an error. Returns true if we should
- // resend the request. |error| is OK when we reached EOF.
- bool ShouldResendRequest(int error) const;
+ // Called when the socket is unexpectedly closed. Returns true if the request
+ // should be resent in case of a socket reuse/close race.
+ bool ShouldResendRequest() const;
// Resets the connection and the request headers for resend. Called when
// ShouldResendRequest() is true.
void ResetConnectionAndRequestForResend();
- // Decides the policy when the connection is closed before the end of headers
- // has been read. This only applies to reading responses, and not writing
- // requests.
- int HandleConnectionClosedBeforeEndOfHeaders();
-
// Sets up the state machine to restart the transaction with auth.
void PrepareForAuthRestart(HttpAuth::Target target);
@@ -254,6 +256,8 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
// Debug helper.
static std::string DescribeState(State state);
+ void SetStream(HttpStreamBase* stream);
+
scoped_refptr<HttpAuthController>
auth_controllers_[HttpAuth::AUTH_NUM_TARGETS];
@@ -306,6 +310,9 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
scoped_refptr<IOBuffer> read_buf_;
int read_buf_len_;
+ // Total number of bytes received on streams for this transaction.
+ int64 total_received_bytes_;
+
// The time the Start method was called.
base::Time start_time_;
@@ -326,6 +333,8 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
WebSocketHandshakeStreamBase::CreateHelper*
websocket_handshake_stream_base_create_helper_;
+ BeforeNetworkStartCallback before_network_start_callback_;
+
DISALLOW_COPY_AND_ASSIGN(HttpNetworkTransaction);
};
diff --git a/chromium/net/http/http_network_transaction_unittest.cc b/chromium/net/http/http_network_transaction_unittest.cc
index dd9eefecf37..01756a19654 100644
--- a/chromium/net/http/http_network_transaction_unittest.cc
+++ b/chromium/net/http/http_network_transaction_unittest.cc
@@ -16,6 +16,7 @@
#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_file_util.h"
@@ -35,6 +36,7 @@
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/host_cache.h"
#include "net/dns/mock_host_resolver.h"
+#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_handler_digest.h"
#include "net/http/http_auth_handler_mock.h"
#include "net/http/http_auth_handler_ntlm.h"
@@ -44,7 +46,7 @@
#include "net/http/http_server_properties_impl.h"
#include "net/http/http_stream.h"
#include "net/http/http_stream_factory.h"
-#include "net/http/http_transaction_unittest.h"
+#include "net/http/http_transaction_test_util.h"
#include "net/proxy/proxy_config_service_fixed.h"
#include "net/proxy/proxy_info.h"
#include "net/proxy/proxy_resolver.h"
@@ -69,6 +71,8 @@
#include "testing/platform_test.h"
#include "url/gurl.h"
+using base::ASCIIToUTF16;
+
//-----------------------------------------------------------------------------
namespace {
@@ -244,6 +248,7 @@ class HttpNetworkTransactionTest
int rv;
std::string status_line;
std::string response_data;
+ int64 totalReceivedBytes;
LoadTimingInfo load_timing_info;
};
@@ -260,8 +265,6 @@ class HttpNetworkTransactionTest
PlatformTest::TearDown();
NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
base::MessageLoop::current()->RunUntilIdle();
- HttpStreamFactory::set_use_alternate_protocols(false);
- HttpStreamFactory::SetNextProtos(std::vector<NextProto>());
}
// This is the expected return from a current server advertising SPDY.
@@ -279,6 +282,14 @@ class HttpNetworkTransactionTest
void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
const MockRead* read_failure);
+ // Either |write_failure| specifies a write failure or |read_failure|
+ // specifies a read failure when using a reused socket. In either case, the
+ // failure should cause the network transaction to resend the request, and the
+ // other argument should be NULL.
+ void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
+ const MockRead* read_failure,
+ bool use_spdy);
+
SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
size_t data_count) {
SimpleGetHelperResult out;
@@ -300,7 +311,7 @@ class HttpNetworkTransactionTest
TestCompletionCallback callback;
- EXPECT_TRUE(log.bound().IsLoggingAllEvents());
+ EXPECT_TRUE(log.bound().IsLogging());
int rv = trans->Start(&request, callback.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -356,6 +367,7 @@ class HttpNetworkTransactionTest
EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
response_headers);
+ out.totalReceivedBytes = trans->GetTotalReceivedBytes();
return out;
}
@@ -366,6 +378,13 @@ class HttpNetworkTransactionTest
return SimpleGetHelperForData(data, 1);
}
+ int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
+ int64 size = 0;
+ for (size_t i = 0; i < reads_count; ++i)
+ size += data_reads[i].data_len;
+ return size;
+ }
+
void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
int expected_status);
@@ -388,11 +407,32 @@ INSTANTIATE_TEST_CASE_P(
NextProto,
HttpNetworkTransactionTest,
testing::Values(kProtoDeprecatedSPDY2,
- kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
- kProtoHTTP2Draft04));
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
namespace {
+class BeforeNetworkStartHandler {
+ public:
+ explicit BeforeNetworkStartHandler(bool defer)
+ : defer_on_before_network_start_(defer),
+ observed_before_network_start_(false) {}
+
+ void OnBeforeNetworkStart(bool* defer) {
+ *defer = defer_on_before_network_start_;
+ observed_before_network_start_ = true;
+ }
+
+ bool observed_before_network_start() const {
+ return observed_before_network_start_;
+ }
+
+ private:
+ const bool defer_on_before_network_start_;
+ bool observed_before_network_start_;
+
+ DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
+};
+
// Fill |str| with a long header list that consumes >= |size| bytes.
void FillLargeHeadersString(std::string* str, int size) {
const char* row =
@@ -584,6 +624,8 @@ TEST_P(HttpNetworkTransactionTest, SimpleGET) {
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
EXPECT_EQ("hello world", out.response_data);
+ int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
+ EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
// Response with no status line.
@@ -597,6 +639,8 @@ TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
EXPECT_EQ("hello world", out.response_data);
+ int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
+ EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
// Allow up to 4 bytes of junk to precede status line.
@@ -610,6 +654,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
EXPECT_EQ("DATA", out.response_data);
+ int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
+ EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
// Allow up to 4 bytes of junk to precede status line.
@@ -623,6 +669,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
EXPECT_EQ("DATA", out.response_data);
+ int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
+ EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
// Beyond 4 bytes of slop and it should fail to find a status line.
@@ -636,6 +684,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
+ int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
+ EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
@@ -653,6 +703,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
EXPECT_EQ("DATA", out.response_data);
+ int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
+ EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
// Close the connection before enough bytes to have a status line.
@@ -666,15 +718,18 @@ TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
EXPECT_EQ("HTT", out.response_data);
+ int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
+ EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
// Simulate a 204 response, lacking a Content-Length header, sent over a
// persistent connection. The response should still terminate since a 204
// cannot have a response body.
TEST_P(HttpNetworkTransactionTest, StopsReading204) {
+ char junk[] = "junk";
MockRead data_reads[] = {
MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
- MockRead("junk"), // Should not be read!!
+ MockRead(junk), // Should not be read!!
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
@@ -682,18 +737,23 @@ TEST_P(HttpNetworkTransactionTest, StopsReading204) {
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
EXPECT_EQ("", out.response_data);
+ int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
+ int64 response_size = reads_size - strlen(junk);
+ EXPECT_EQ(response_size, out.totalReceivedBytes);
}
// A simple request using chunked encoding with some extra data after.
-// (Like might be seen in a pipelined response.)
TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
+ std::string final_chunk = "0\r\n\r\n";
+ std::string extra_data = "HTTP/1.1 200 OK\r\n";
+ std::string last_read = final_chunk + extra_data;
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
MockRead("5\r\nHello\r\n"),
MockRead("1\r\n"),
MockRead(" \r\n"),
MockRead("5\r\nworld\r\n"),
- MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
+ MockRead(last_read.data()),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
@@ -701,6 +761,9 @@ TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
EXPECT_EQ("Hello world", out.response_data);
+ int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
+ int64 response_size = reads_size - extra_data.size();
+ EXPECT_EQ(response_size, out.totalReceivedBytes);
}
// Next tests deal with http://crbug.com/56344.
@@ -883,6 +946,7 @@ TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
std::string url;
EXPECT_TRUE(response->headers->IsRedirect(&url));
EXPECT_EQ("http://good.com/", url);
+ EXPECT_TRUE(response->proxy_server.IsEmpty());
}
// Checks that two distinct Location headers result in an error.
@@ -945,6 +1009,7 @@ TEST_P(HttpNetworkTransactionTest, Head) {
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ(1234, response->headers->GetContentLength());
EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
+ EXPECT_TRUE(response->proxy_server.IsEmpty());
std::string server_header;
void* iter = NULL;
@@ -1000,6 +1065,7 @@ TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
+ EXPECT_TRUE(response->proxy_server.IsEmpty());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
@@ -1181,7 +1247,7 @@ void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
};
if (write_failure) {
- ASSERT_TRUE(!read_failure);
+ ASSERT_FALSE(read_failure);
data1_writes[1] = *write_failure;
} else {
ASSERT_TRUE(read_failure);
@@ -1240,6 +1306,126 @@ void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
}
}
+void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
+ const MockWrite* write_failure,
+ const MockRead* read_failure,
+ bool use_spdy) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.foo.com/");
+ request.load_flags = 0;
+
+ CapturingNetLog net_log;
+ session_deps_.net_log = &net_log;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+
+ SSLSocketDataProvider ssl1(ASYNC, OK);
+ SSLSocketDataProvider ssl2(ASYNC, OK);
+ if (use_spdy) {
+ ssl1.SetNextProto(GetParam());
+ ssl2.SetNextProto(GetParam());
+ }
+ session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
+ session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
+
+ // SPDY versions of the request and response.
+ scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
+ request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
+ scoped_ptr<SpdyFrame> spdy_response(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdyFrame> spdy_data(
+ spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
+
+ // HTTP/1.1 versions of the request and response.
+ const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n\r\n";
+ const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
+ const char kHttpData[] = "hello";
+
+ std::vector<MockRead> data1_reads;
+ std::vector<MockWrite> data1_writes;
+ if (write_failure) {
+ ASSERT_FALSE(read_failure);
+ data1_writes.push_back(*write_failure);
+ data1_reads.push_back(MockRead(ASYNC, OK));
+ } else {
+ ASSERT_TRUE(read_failure);
+ if (use_spdy) {
+ data1_writes.push_back(CreateMockWrite(*spdy_request));
+ } else {
+ data1_writes.push_back(MockWrite(kHttpRequest));
+ }
+ data1_reads.push_back(*read_failure);
+ }
+
+ StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
+ &data1_writes[0], data1_writes.size());
+ session_deps_.socket_factory->AddSocketDataProvider(&data1);
+
+ std::vector<MockRead> data2_reads;
+ std::vector<MockWrite> data2_writes;
+
+ if (use_spdy) {
+ data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
+
+ data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
+ data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
+ data2_reads.push_back(MockRead(ASYNC, OK, 3));
+ } else {
+ data2_writes.push_back(
+ MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
+
+ data2_reads.push_back(
+ MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
+ data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
+ data2_reads.push_back(MockRead(ASYNC, OK, 3));
+ }
+ OrderedSocketData data2(&data2_reads[0], data2_reads.size(),
+ &data2_writes[0], data2_writes.size());
+ session_deps_.socket_factory->AddSocketDataProvider(&data2);
+
+ // Preconnect a socket.
+ net::SSLConfig ssl_config;
+ session->ssl_config_service()->GetSSLConfig(&ssl_config);
+ session->GetNextProtos(&ssl_config.next_protos);
+ session->http_stream_factory()->PreconnectStreams(
+ 1, request, DEFAULT_PRIORITY, ssl_config, ssl_config);
+ // Wait for the preconnect to complete.
+ // TODO(davidben): Some way to wait for an idle socket count might be handy.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
+
+ // Make the request.
+ TestCompletionCallback callback;
+
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ LoadTimingInfo load_timing_info;
+ EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
+ TestLoadTimingNotReused(
+ load_timing_info,
+ CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+
+ EXPECT_TRUE(response->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
+
+ std::string response_data;
+ rv = ReadTransaction(trans.get(), &response_data);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ(kHttpData, response_data);
+}
+
TEST_P(HttpNetworkTransactionTest,
KeepAliveConnectionNotConnectedOnWrite) {
MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
@@ -1256,6 +1442,71 @@ TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
KeepAliveConnectionResendRequestTest(NULL, &read_failure);
}
+// Make sure that on a 408 response (Request Timeout), the request is retried,
+// if the socket was a reused keep alive socket.
+TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
+ MockRead read_failure(SYNCHRONOUS,
+ "HTTP/1.1 408 Request Timeout\r\n"
+ "Connection: Keep-Alive\r\n"
+ "Content-Length: 6\r\n\r\n"
+ "Pickle");
+ KeepAliveConnectionResendRequestTest(NULL, &read_failure);
+}
+
+TEST_P(HttpNetworkTransactionTest,
+ PreconnectErrorNotConnectedOnWrite) {
+ MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
+ PreconnectErrorResendRequestTest(&write_failure, NULL, false);
+}
+
+TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
+ MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
+ PreconnectErrorResendRequestTest(NULL, &read_failure, false);
+}
+
+TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
+ MockRead read_failure(SYNCHRONOUS, OK); // EOF
+ PreconnectErrorResendRequestTest(NULL, &read_failure, false);
+}
+
+TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
+ MockRead read_failure(ASYNC, OK); // EOF
+ PreconnectErrorResendRequestTest(NULL, &read_failure, false);
+}
+
+// Make sure that on a 408 response (Request Timeout), the request is retried,
+// if the socket was a preconnected (UNUSED_IDLE) socket.
+TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
+ MockRead read_failure(SYNCHRONOUS,
+ "HTTP/1.1 408 Request Timeout\r\n"
+ "Connection: Keep-Alive\r\n"
+ "Content-Length: 6\r\n\r\n"
+ "Pickle");
+ KeepAliveConnectionResendRequestTest(NULL, &read_failure);
+ PreconnectErrorResendRequestTest(NULL, &read_failure, false);
+}
+
+TEST_P(HttpNetworkTransactionTest,
+ SpdyPreconnectErrorNotConnectedOnWrite) {
+ MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
+ PreconnectErrorResendRequestTest(&write_failure, NULL, true);
+}
+
+TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
+ MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
+ PreconnectErrorResendRequestTest(NULL, &read_failure, true);
+}
+
+TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
+ MockRead read_failure(SYNCHRONOUS, OK); // EOF
+ PreconnectErrorResendRequestTest(NULL, &read_failure, true);
+}
+
+TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
+ MockRead read_failure(ASYNC, OK); // EOF
+ PreconnectErrorResendRequestTest(NULL, &read_failure, true);
+}
+
TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
HttpRequestInfo request;
request.method = "GET";
@@ -1308,6 +1559,85 @@ TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
}
+// Test that network access can be deferred and resumed.
+TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
+
+ // Defer on OnBeforeNetworkStart.
+ BeforeNetworkStartHandler net_start_handler(true); // defer
+ trans->SetBeforeNetworkStartCallback(
+ base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
+ base::Unretained(&net_start_handler)));
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 200 OK\r\n"),
+ MockRead("Content-Length: 5\r\n\r\n"),
+ MockRead("hello"),
+ MockRead(SYNCHRONOUS, 0),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Should have deferred for network start.
+ EXPECT_TRUE(net_start_handler.observed_before_network_start());
+ EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
+ EXPECT_TRUE(trans->GetResponseInfo() == NULL);
+
+ trans->ResumeNetworkStart();
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+ EXPECT_TRUE(trans->GetResponseInfo() != NULL);
+
+ scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
+ rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ EXPECT_EQ(5, rv);
+ trans.reset();
+}
+
+// Test that network use can be deferred and canceled.
+TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
+
+ // Defer on OnBeforeNetworkStart.
+ BeforeNetworkStartHandler net_start_handler(true); // defer
+ trans->SetBeforeNetworkStartCallback(
+ base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
+ base::Unretained(&net_start_handler)));
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Should have deferred for network start.
+ EXPECT_TRUE(net_start_handler.observed_before_network_start());
+ EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
+ EXPECT_TRUE(trans->GetResponseInfo() == NULL);
+}
+
// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
// tests. There was a bug causing HttpNetworkTransaction to hang in the
// destructor in such situations.
@@ -1569,6 +1899,9 @@ TEST_P(HttpNetworkTransactionTest, BasicAuth) {
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
+ int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
+ EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
+
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
@@ -1591,6 +1924,9 @@ TEST_P(HttpNetworkTransactionTest, BasicAuth) {
load_timing_info2.connect_timing.connect_start);
EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
+ int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
+ EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
+
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
@@ -1633,6 +1969,9 @@ TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
rv = callback.WaitForResult();
EXPECT_EQ(0, rv);
+ int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
+ EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
+
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
@@ -1730,6 +2069,12 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(5, response->headers->GetContentLength());
+
+ std::string response_data;
+ rv = ReadTransaction(trans.get(), &response_data);
+ EXPECT_EQ(OK, rv);
+ int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
+ EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
}
// Test the request-challenge-retry sequence for basic auth, over a keep-alive
@@ -2683,6 +3028,82 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
EXPECT_EQ(kUploadData, response_data);
}
+// Verifies that a session which races and wins against the owning transaction
+// (completing prior to host resolution), doesn't fail the transaction.
+// Regression test for crbug.com/334413.
+TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.load_flags = 0;
+
+ // Configure SPDY proxy server "proxy:70".
+ session_deps_.proxy_service.reset(
+ ProxyService::CreateFixed("https://proxy:70"));
+ CapturingBoundNetLog log;
+ session_deps_.net_log = log.bound().net_log();
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+
+ // Fetch http://www.google.com/ through the SPDY proxy.
+ scoped_ptr<SpdyFrame> req(
+ spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
+ MockWrite spdy_writes[] = {CreateMockWrite(*req)};
+
+ scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ MockRead spdy_reads[] = {
+ CreateMockRead(*resp), CreateMockRead(*data), MockRead(ASYNC, 0, 0),
+ };
+
+ DelayedSocketData spdy_data(
+ 1, // wait for one write to finish before reading.
+ spdy_reads,
+ arraysize(spdy_reads),
+ spdy_writes,
+ arraysize(spdy_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
+
+ SSLSocketDataProvider ssl(ASYNC, OK);
+ ssl.SetNextProto(GetParam());
+ session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
+
+ TestCompletionCallback callback1;
+
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
+
+ // Stall the hostname resolution begun by the transaction.
+ session_deps_.host_resolver->set_synchronous_mode(false);
+ session_deps_.host_resolver->set_ondemand_mode(true);
+
+ int rv = trans->Start(&request, callback1.callback(), log.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Race a session to the proxy, which completes first.
+ session_deps_.host_resolver->set_ondemand_mode(false);
+ SpdySessionKey key(
+ HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
+ base::WeakPtr<SpdySession> spdy_session =
+ CreateSecureSpdySession(session, key, log.bound());
+
+ // Unstall the resolution begun by the transaction.
+ session_deps_.host_resolver->set_ondemand_mode(true);
+ session_deps_.host_resolver->ResolveAllPending();
+
+ EXPECT_FALSE(callback1.have_result());
+ rv = callback1.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+ ASSERT_TRUE(response->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
+
+ std::string response_data;
+ ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
+ EXPECT_EQ(kUploadData, response_data);
+}
+
// Test a SPDY get through an HTTPS Proxy.
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
HttpRequestInfo request;
@@ -3064,23 +3485,15 @@ TEST_P(HttpNetworkTransactionTest,
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
// CONNECT to news.google.com:443 via SPDY.
- const char* const kConnectHeaders2[] = {
- spdy_util_.GetMethodKey(), "CONNECT",
- spdy_util_.GetPathKey(), "news.google.com:443",
- spdy_util_.GetHostKey(), "news.google.com",
- spdy_util_.GetVersionKey(), "HTTP/1.1",
- };
+ SpdySynStreamIR connect2_ir(3);
+ spdy_util_.SetPriority(LOWEST, &connect2_ir);
+ connect2_ir.SetHeader(spdy_util_.GetMethodKey(), "CONNECT");
+ connect2_ir.SetHeader(spdy_util_.GetPathKey(), "news.google.com:443");
+ connect2_ir.SetHeader(spdy_util_.GetHostKey(), "news.google.com");
+ spdy_util_.MaybeAddVersionHeader(&connect2_ir);
scoped_ptr<SpdyFrame> connect2(
- spdy_util_.ConstructSpdyControlFrame(NULL,
- 0,
- /*compressed*/ false,
- 3,
- LOWEST,
- SYN_STREAM,
- CONTROL_FLAG_NONE,
- kConnectHeaders2,
- arraysize(kConnectHeaders2),
- 0));
+ spdy_util_.CreateFramer(false)->SerializeFrame(connect2_ir));
+
scoped_ptr<SpdyFrame> conn_resp2(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
@@ -3635,6 +4048,10 @@ TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
}
+TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
+ ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
+}
+
TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
}
@@ -7160,7 +7577,7 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
},
};
- HttpStreamFactory::set_use_alternate_protocols(true);
+ session_deps_.use_alternate_protocols = true;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
session_deps_.proxy_service.reset(
@@ -7224,7 +7641,7 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
},
};
- HttpStreamFactory::set_use_alternate_protocols(true);
+ session_deps_.use_alternate_protocols = true;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
session_deps_.proxy_service.reset(
@@ -7295,7 +7712,7 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
},
};
- HttpStreamFactory::set_use_alternate_protocols(true);
+ session_deps_.use_alternate_protocols = true;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
session_deps_.proxy_service.reset(
@@ -7710,7 +8127,7 @@ TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
base::FilePath temp_file;
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
std::string temp_file_content("Unreadable file.");
- ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
+ ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
temp_file_content.length()));
ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
@@ -7961,8 +8378,8 @@ TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
}
TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
- HttpStreamFactory::set_use_alternate_protocols(true);
+ session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.use_alternate_protocols = true;
std::string alternate_protocol_http_header =
GetAlternateProtocolHttpHeader();
@@ -7993,7 +8410,7 @@ TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
EXPECT_EQ(ERR_IO_PENDING, rv);
HostPortPair http_host_port_pair("www.google.com", 80);
- const HttpServerProperties& http_server_properties =
+ HttpServerProperties& http_server_properties =
*session->http_server_properties();
EXPECT_FALSE(
http_server_properties.HasAlternateProtocol(http_host_port_pair));
@@ -8022,7 +8439,7 @@ TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
TEST_P(HttpNetworkTransactionTest,
MarkBrokenAlternateProtocolAndFallback) {
- HttpStreamFactory::set_use_alternate_protocols(true);
+ session_deps_.use_alternate_protocols = true;
HttpRequestInfo request;
request.method = "GET";
@@ -8085,7 +8502,7 @@ TEST_P(HttpNetworkTransactionTest,
// protocol to an unrestricted (port >= 1024) when the original traffic was
// on a restricted port (port < 1024). Ensure that we can redirect in all
// other cases.
- HttpStreamFactory::set_use_alternate_protocols(true);
+ session_deps_.use_alternate_protocols = true;
HttpRequestInfo restricted_port_request;
restricted_port_request.method = "GET";
@@ -8135,7 +8552,7 @@ TEST_P(HttpNetworkTransactionTest,
// on a restricted port (port < 1024) if we set
// enable_user_alternate_protocol_ports.
- HttpStreamFactory::set_use_alternate_protocols(true);
+ session_deps_.use_alternate_protocols = true;
session_deps_.enable_user_alternate_protocol_ports = true;
HttpRequestInfo restricted_port_request;
@@ -8184,7 +8601,7 @@ TEST_P(HttpNetworkTransactionTest,
// protocol to an unrestricted (port >= 1024) when the original traffic was
// on a restricted port (port < 1024). Ensure that we can redirect in all
// other cases.
- HttpStreamFactory::set_use_alternate_protocols(true);
+ session_deps_.use_alternate_protocols = true;
HttpRequestInfo restricted_port_request;
restricted_port_request.method = "GET";
@@ -8233,7 +8650,7 @@ TEST_P(HttpNetworkTransactionTest,
// protocol to an unrestricted (port >= 1024) when the original traffic was
// on a restricted port (port < 1024). Ensure that we can redirect in all
// other cases.
- HttpStreamFactory::set_use_alternate_protocols(true);
+ session_deps_.use_alternate_protocols = true;
HttpRequestInfo unrestricted_port_request;
unrestricted_port_request.method = "GET";
@@ -8281,7 +8698,7 @@ TEST_P(HttpNetworkTransactionTest,
// protocol to an unrestricted (port >= 1024) when the original traffic was
// on a restricted port (port < 1024). Ensure that we can redirect in all
// other cases.
- HttpStreamFactory::set_use_alternate_protocols(true);
+ session_deps_.use_alternate_protocols = true;
HttpRequestInfo unrestricted_port_request;
unrestricted_port_request.method = "GET";
@@ -8323,12 +8740,11 @@ TEST_P(HttpNetworkTransactionTest,
EXPECT_EQ(OK, callback.WaitForResult());
}
-TEST_P(HttpNetworkTransactionTest,
- AlternateProtocolUnsafeBlocked) {
+TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
// Ensure that we're not allowed to redirect traffic via an alternate
// protocol to an unsafe port, and that we resume the second
// HttpStreamFactoryImpl::Job once the alternate protocol request fails.
- HttpStreamFactory::set_use_alternate_protocols(true);
+ session_deps_.use_alternate_protocols = true;
HttpRequestInfo request;
request.method = "GET";
@@ -8366,7 +8782,7 @@ TEST_P(HttpNetworkTransactionTest,
EXPECT_EQ(OK, callback.WaitForResult());
// Disable alternate protocol before the asserts.
- HttpStreamFactory::set_use_alternate_protocols(false);
+ // HttpStreamFactory::set_use_alternate_protocols(false);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
@@ -8379,8 +8795,8 @@ TEST_P(HttpNetworkTransactionTest,
}
TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
- HttpStreamFactory::set_use_alternate_protocols(true);
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
+ session_deps_.use_alternate_protocols = true;
+ session_deps_.next_protos = SpdyNextProtos();
HttpRequestInfo request;
request.method = "GET";
@@ -8469,8 +8885,8 @@ TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
}
TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
- HttpStreamFactory::set_use_alternate_protocols(true);
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
+ session_deps_.use_alternate_protocols = true;
+ session_deps_.next_protos = SpdyNextProtos();
HttpRequestInfo request;
request.method = "GET";
@@ -8586,8 +9002,8 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
}
TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
- HttpStreamFactory::set_use_alternate_protocols(true);
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
+ session_deps_.use_alternate_protocols = true;
+ session_deps_.next_protos = SpdyNextProtos();
HttpRequestInfo request;
request.method = "GET";
@@ -8705,8 +9121,8 @@ class CapturingProxyResolver : public ProxyResolver {
TEST_P(HttpNetworkTransactionTest,
UseAlternateProtocolForTunneledNpnSpdy) {
- HttpStreamFactory::set_use_alternate_protocols(true);
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
+ session_deps_.use_alternate_protocols = true;
+ session_deps_.next_protos = SpdyNextProtos();
ProxyConfig proxy_config;
proxy_config.set_auto_detect(true);
@@ -8827,8 +9243,8 @@ TEST_P(HttpNetworkTransactionTest,
TEST_P(HttpNetworkTransactionTest,
UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
- HttpStreamFactory::set_use_alternate_protocols(true);
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
+ session_deps_.use_alternate_protocols = true;
+ session_deps_.next_protos = SpdyNextProtos();
HttpRequestInfo request;
request.method = "GET";
@@ -8894,7 +9310,7 @@ TEST_P(HttpNetworkTransactionTest,
// Set up an initial SpdySession in the pool to reuse.
HostPortPair host_port_pair("www.google.com", 443);
SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
- kPrivacyModeDisabled);
+ PRIVACY_MODE_DISABLED);
base::WeakPtr<SpdySession> spdy_session =
CreateSecureSpdySession(session, key, BoundNetLog());
@@ -9230,8 +9646,8 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
std::string auth_challenge = "Mock realm=proxy";
GURL origin(test_config.proxy_url);
- HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
- auth_challenge.end());
+ HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
+ auth_challenge.end());
auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
origin, BoundNetLog());
auth_handler->SetGenerateExpectation(
@@ -9244,8 +9660,8 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
std::string auth_challenge = "Mock realm=server";
GURL origin(test_config.server_url);
- HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
- auth_challenge.end());
+ HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
+ auth_challenge.end());
auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
origin, BoundNetLog());
auth_handler->SetGenerateExpectation(
@@ -9341,8 +9757,8 @@ TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
auth_handler->set_connection_based(true);
std::string auth_challenge = "Mock realm=server";
GURL origin("http://www.example.com");
- HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
- auth_challenge.end());
+ HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
+ auth_challenge.end());
auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
origin, BoundNetLog());
auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
@@ -9518,10 +9934,11 @@ TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
// This tests the case that a request is issued via http instead of spdy after
// npn is negotiated.
TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
- HttpStreamFactory::set_use_alternate_protocols(true);
- std::vector<NextProto> next_protos;
+ session_deps_.use_alternate_protocols = true;
+ NextProtoVector next_protos;
next_protos.push_back(kProtoHTTP11);
- HttpStreamFactory::SetNextProtos(next_protos);
+ session_deps_.next_protos = next_protos;
+
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
@@ -9582,8 +9999,8 @@ TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
// Simulate the SSL handshake completing with an NPN negotiation
// followed by an immediate server closing of the socket.
// Fix crash: http://crbug.com/46369
- HttpStreamFactory::set_use_alternate_protocols(true);
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
+ session_deps_.use_alternate_protocols = true;
+ session_deps_.next_protos = SpdyNextProtos();
HttpRequestInfo request;
request.method = "GET";
@@ -9645,8 +10062,8 @@ class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
// This test ensures that the URL passed into the proxy is upgraded
// to https when doing an Alternate Protocol upgrade.
- HttpStreamFactory::set_use_alternate_protocols(true);
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
+ session_deps_.use_alternate_protocols = true;
+ session_deps_.next_protos = SpdyNextProtos();
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
@@ -9840,6 +10257,56 @@ TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
base::MessageLoop::current()->RunUntilIdle();
}
+// Test that if a transaction is cancelled after receiving the headers, the
+// stream is drained properly and added back to the socket pool. The main
+// purpose of this test is to make sure that an HttpStreamParser can be read
+// from after the HttpNetworkTransaction and the objects it owns have been
+// deleted.
+// See http://crbug.com/368418
+TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
+ MockRead data_reads[] = {
+ MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
+ MockRead(ASYNC, "Content-Length: 2\r\n"),
+ MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
+ MockRead(ASYNC, "1"),
+ // 2 async reads are necessary to trigger a ReadResponseBody call after the
+ // HttpNetworkTransaction has been deleted.
+ MockRead(ASYNC, "2"),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+
+ {
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.load_flags = 0;
+
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
+ TestCompletionCallback callback;
+
+ int rv = trans.Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ callback.WaitForResult();
+
+ const HttpResponseInfo* response = trans.GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+ EXPECT_TRUE(response->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
+
+ // The transaction and HttpRequestInfo are deleted.
+ }
+
+ // Let the HttpResponseBodyDrainer drain the socket.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Socket should now be idle, waiting to be reused.
+ EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
+}
+
// Test a basic GET request through a proxy.
TEST_P(HttpNetworkTransactionTest, ProxyGet) {
session_deps_.proxy_service.reset(
@@ -9887,6 +10354,8 @@ TEST_P(HttpNetworkTransactionTest, ProxyGet) {
EXPECT_EQ(200, response->headers->response_code());
EXPECT_EQ(100, response->headers->GetContentLength());
EXPECT_TRUE(response->was_fetched_via_proxy);
+ EXPECT_TRUE(
+ response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
LoadTimingInfo load_timing_info;
@@ -9961,6 +10430,8 @@ TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
EXPECT_EQ(100, response->headers->GetContentLength());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
EXPECT_TRUE(response->was_fetched_via_proxy);
+ EXPECT_TRUE(
+ response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
@@ -10053,7 +10524,7 @@ TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
// Set up an initial SpdySession in the pool to reuse.
HostPortPair host_port_pair("www.google.com", 443);
SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
- kPrivacyModeDisabled);
+ PRIVACY_MODE_DISABLED);
base::WeakPtr<SpdySession> spdy_session =
CreateInsecureSpdySession(session, key, BoundNetLog());
@@ -10130,7 +10601,7 @@ TEST_P(HttpNetworkTransactionTest,
request_info.load_flags = net::LOAD_NORMAL;
scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
- cert_request->host_and_port = "www.example.com:443";
+ cert_request->host_and_port = HostPortPair("www.example.com", 443);
// [ssl_]data1 contains the data for the first SSL handshake. When a
// CertificateRequest is received for the first time, the handshake will
@@ -10210,8 +10681,8 @@ TEST_P(HttpNetworkTransactionTest,
// Ensure the certificate was added to the client auth cache before
// allowing the connection to continue restarting.
scoped_refptr<X509Certificate> client_cert;
- ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
+ ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
+ HostPortPair("www.example.com", 443), &client_cert));
ASSERT_EQ(NULL, client_cert.get());
// Restart the handshake. This will consume ssl_data2, which fails, and
@@ -10222,8 +10693,8 @@ TEST_P(HttpNetworkTransactionTest,
// Ensure that the client certificate is removed from the cache on a
// handshake failure.
- ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
+ ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
+ HostPortPair("www.example.com", 443), &client_cert));
}
// Ensure that a client certificate is removed from the SSL client auth
@@ -10240,7 +10711,7 @@ TEST_P(HttpNetworkTransactionTest,
request_info.load_flags = net::LOAD_NORMAL;
scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
- cert_request->host_and_port = "www.example.com:443";
+ cert_request->host_and_port = HostPortPair("www.example.com", 443);
// When TLS False Start is used, SSLClientSocket::Connect() calls will
// return successfully after reading up to the peer's Certificate message.
@@ -10331,8 +10802,8 @@ TEST_P(HttpNetworkTransactionTest,
// Ensure the certificate was added to the client auth cache before
// allowing the connection to continue restarting.
scoped_refptr<X509Certificate> client_cert;
- ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
+ ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
+ HostPortPair("www.example.com", 443), &client_cert));
ASSERT_EQ(NULL, client_cert.get());
// Restart the handshake. This will consume ssl_data2, which fails, and
@@ -10343,8 +10814,8 @@ TEST_P(HttpNetworkTransactionTest,
// Ensure that the client certificate is removed from the cache on a
// handshake failure.
- ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
+ ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
+ HostPortPair("www.example.com", 443), &client_cert));
}
// Ensure that a client certificate is removed from the SSL client auth
@@ -10362,7 +10833,7 @@ TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
session_deps_.net_log = log.bound().net_log();
scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
- cert_request->host_and_port = "proxy:70";
+ cert_request->host_and_port = HostPortPair("proxy", 70);
// See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
// [ssl_]data[1-3]. Rather than represending the endpoint
@@ -10425,13 +10896,13 @@ TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
// Ensure the certificate was added to the client auth cache before
// allowing the connection to continue restarting.
scoped_refptr<X509Certificate> client_cert;
- ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
- &client_cert));
+ ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
+ HostPortPair("proxy", 70), &client_cert));
ASSERT_EQ(NULL, client_cert.get());
// Ensure the certificate was NOT cached for the endpoint. This only
// applies to HTTPS requests, but is fine to check for HTTP requests.
- ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
+ ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
+ HostPortPair("www.example.com", 443), &client_cert));
// Restart the handshake. This will consume ssl_data2, which fails, and
// then consume ssl_data3, which should also fail. The result code is
@@ -10441,10 +10912,10 @@ TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
// Now that the new handshake has failed, ensure that the client
// certificate was removed from the client auth cache.
- ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
- &client_cert));
- ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
+ ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
+ HostPortPair("proxy", 70), &client_cert));
+ ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
+ HostPortPair("www.example.com", 443), &client_cert));
}
}
@@ -10465,8 +10936,8 @@ TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
#define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
#endif
WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
- HttpStreamFactory::set_use_alternate_protocols(true);
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
+ session_deps_.use_alternate_protocols = true;
+ session_deps_.next_protos = SpdyNextProtos();
// Set up a special HttpNetworkSession with a MockCachingHostResolver.
session_deps_.host_resolver.reset(new MockCachingHostResolver());
@@ -10568,8 +11039,8 @@ WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
#undef MAYBE_UseIPConnectionPooling
TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
- HttpStreamFactory::set_use_alternate_protocols(true);
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
+ session_deps_.use_alternate_protocols = true;
+ session_deps_.next_protos = SpdyNextProtos();
// Set up a special HttpNetworkSession with a MockCachingHostResolver.
session_deps_.host_resolver.reset(new MockCachingHostResolver());
@@ -10710,10 +11181,9 @@ WRAPPED_TEST_P(HttpNetworkTransactionTest,
// prefix doesn't work with parametrized tests).
#if defined(OS_WIN)
return;
-#endif
-
- HttpStreamFactory::set_use_alternate_protocols(true);
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
+#else
+ session_deps_.use_alternate_protocols = true;
+ session_deps_.next_protos = SpdyNextProtos();
// Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
@@ -10813,56 +11283,10 @@ WRAPPED_TEST_P(HttpNetworkTransactionTest,
EXPECT_TRUE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
EXPECT_EQ("hello!", response_data);
+#endif
}
#undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
-TEST_P(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
- MockRead data_reads1[] = {
- MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
- };
- MockRead data_reads2[] = {
- MockRead("HTTP/1.0 200 OK\r\n\r\n"),
- MockRead("hello world"),
- MockRead(SYNCHRONOUS, OK),
- };
- StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
- StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
- StaticSocketDataProvider* data[] = { &data1, &data2 };
-
- SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
-
- EXPECT_EQ(OK, out.rv);
- EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
- EXPECT_EQ("hello world", out.response_data);
-}
-
-TEST_P(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
- MockWrite data_writes1[] = {
- MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
- };
- MockWrite data_writes2[] = {
- MockWrite("GET / HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead data_reads2[] = {
- MockRead("HTTP/1.0 200 OK\r\n\r\n"),
- MockRead("hello world"),
- MockRead(SYNCHRONOUS, OK),
- };
- StaticSocketDataProvider data1(NULL, 0,
- data_writes1, arraysize(data_writes1));
- StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
- data_writes2, arraysize(data_writes2));
- StaticSocketDataProvider* data[] = { &data1, &data2 };
-
- SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
-
- EXPECT_EQ(OK, out.rv);
- EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
- EXPECT_EQ("hello world", out.response_data);
-}
-
TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
const std::string https_url = "https://www.google.com/";
const std::string http_url = "http://www.google.com:443/";
@@ -10953,20 +11377,21 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
LOWEST));
scoped_ptr<SpdyFrame> req1(
spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
-
- // SPDY GET for HTTP URL (through the proxy, but not the tunnel)
scoped_ptr<SpdyFrame> wrapped_req1(
spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
- const char* const headers[] = {
- spdy_util_.GetMethodKey(), "GET",
- spdy_util_.GetPathKey(), spdy_util_.is_spdy2() ? http_url.c_str() : "/",
- spdy_util_.GetHostKey(), "www.google.com:443",
- spdy_util_.GetSchemeKey(), "http",
- spdy_util_.GetVersionKey(), "HTTP/1.1"
- };
- scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyControlFrame(
- NULL, 0, false, 3, MEDIUM, SYN_STREAM, CONTROL_FLAG_FIN,
- headers, arraysize(headers), 0));
+
+ // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
+ SpdySynStreamIR req2_ir(3);
+ spdy_util_.SetPriority(MEDIUM, &req2_ir);
+ req2_ir.set_fin(true);
+ req2_ir.SetHeader(spdy_util_.GetMethodKey(), "GET");
+ req2_ir.SetHeader(spdy_util_.GetPathKey(),
+ spdy_util_.is_spdy2() ? http_url.c_str() : "/");
+ req2_ir.SetHeader(spdy_util_.GetHostKey(), "www.google.com:443");
+ req2_ir.SetHeader(spdy_util_.GetSchemeKey(), "http");
+ spdy_util_.MaybeAddVersionHeader(&req2_ir);
+ scoped_ptr<SpdyFrame> req2(
+ spdy_util_.CreateFramer(false)->SerializeFrame(req2_ir));
MockWrite writes1[] = {
CreateMockWrite(*connect, 0),
@@ -11058,7 +11483,7 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
}
TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) {
- HttpStreamFactory::set_force_spdy_always(true);
+ session_deps_.force_spdy_always = true;
const std::string https_url = "https://www.google.com/";
const std::string http_url = "http://www.google.com:443/";
@@ -11333,7 +11758,7 @@ TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
}
TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
- HttpStreamFactory::SetNextProtos(SpdyNextProtos());
+ session_deps_.next_protos = SpdyNextProtos();
ClientSocketPoolManager::set_max_sockets_per_group(
HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
ClientSocketPoolManager::set_max_sockets_per_pool(
@@ -11411,7 +11836,7 @@ TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
HostPortPair host_port_pair_a("www.a.com", 443);
SpdySessionKey spdy_session_key_a(
- host_port_pair_a, ProxyServer::Direct(), kPrivacyModeDisabled);
+ host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
EXPECT_FALSE(
HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
@@ -11443,7 +11868,7 @@ TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
HostPortPair host_port_pair_b("www.b.com", 443);
SpdySessionKey spdy_session_key_b(
- host_port_pair_b, ProxyServer::Direct(), kPrivacyModeDisabled);
+ host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
EXPECT_FALSE(
HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
HttpRequestInfo request2;
@@ -11471,7 +11896,7 @@ TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
HostPortPair host_port_pair_a1("www.a.com", 80);
SpdySessionKey spdy_session_key_a1(
- host_port_pair_a1, ProxyServer::Direct(), kPrivacyModeDisabled);
+ host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
EXPECT_FALSE(
HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
HttpRequestInfo request3;
@@ -11779,11 +12204,6 @@ class FakeStream : public HttpStreamBase,
return ERR_UNEXPECTED;
}
- virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE {
- ADD_FAILURE();
- return NULL;
- }
-
virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
const CompletionCallback& callback) OVERRIDE {
ADD_FAILURE();
@@ -11973,11 +12393,6 @@ class FakeStreamFactory : public HttpStreamFactory {
ADD_FAILURE();
}
- virtual base::Value* PipelineInfoToValue() const OVERRIDE {
- ADD_FAILURE();
- return NULL;
- }
-
virtual const HostMappingRules* GetHostMappingRules() const OVERRIDE {
ADD_FAILURE();
return NULL;
@@ -12289,4 +12704,487 @@ TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
}
+TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+
+ EXPECT_TRUE(response->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
+
+ std::string response_data;
+ rv = ReadTransaction(trans.get(), &response_data);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("hello world", response_data);
+}
+
+// This test makes sure the retry logic doesn't trigger when reading an error
+// response from a server that rejected a POST with a CONNECTION_RESET.
+TEST_P(HttpNetworkTransactionTest,
+ PostReadsErrorResponseAfterResetOnReusedSocket) {
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ MockWrite data_writes[] = {
+ MockWrite("GET / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n\r\n"),
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 Peachy\r\n"
+ "Content-Length: 14\r\n\r\n"),
+ MockRead("first response"),
+ MockRead("HTTP/1.1 400 Not OK\r\n"
+ "Content-Length: 15\r\n\r\n"),
+ MockRead("second response"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+ HttpRequestInfo request1;
+ request1.method = "GET";
+ request1.url = GURL("http://www.foo.com/");
+ request1.load_flags = 0;
+
+ scoped_ptr<HttpTransaction> trans1(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response1 = trans1->GetResponseInfo();
+ ASSERT_TRUE(response1 != NULL);
+
+ EXPECT_TRUE(response1->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
+
+ std::string response_data1;
+ rv = ReadTransaction(trans1.get(), &response_data1);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("first response", response_data1);
+ // Delete the transaction to release the socket back into the socket pool.
+ trans1.reset();
+
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request2;
+ request2.method = "POST";
+ request2.url = GURL("http://www.foo.com/");
+ request2.upload_data_stream = &upload_data_stream;
+ request2.load_flags = 0;
+
+ scoped_ptr<HttpTransaction> trans2(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response2 = trans2->GetResponseInfo();
+ ASSERT_TRUE(response2 != NULL);
+
+ EXPECT_TRUE(response2->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
+
+ std::string response_data2;
+ rv = ReadTransaction(trans2.get(), &response_data2);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("second response", response_data2);
+}
+
+TEST_P(HttpNetworkTransactionTest,
+ PostReadsErrorResponseAfterResetPartialBodySent) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"
+ "fo"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+
+ EXPECT_TRUE(response->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
+
+ std::string response_data;
+ rv = ReadTransaction(trans.get(), &response_data);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("hello world", response_data);
+}
+
+// This tests the more common case than the previous test, where headers and
+// body are not merged into a single request.
+TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Transfer-Encoding: chunked\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ // Make sure the headers are sent before adding a chunk. This ensures that
+ // they can't be merged with the body in a single send. Not currently
+ // necessary since a chunked body is never merged with headers, but this makes
+ // the test more future proof.
+ base::RunLoop().RunUntilIdle();
+
+ upload_data_stream.AppendChunk("last chunk", 10, true);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+
+ EXPECT_TRUE(response->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
+
+ std::string response_data;
+ rv = ReadTransaction(trans.get(), &response_data);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("hello world", response_data);
+}
+
+TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
+ MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != NULL);
+
+ EXPECT_TRUE(response->headers.get() != NULL);
+ EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
+
+ std::string response_data;
+ rv = ReadTransaction(trans.get(), &response_data);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("hello world", response_data);
+}
+
+TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ EXPECT_TRUE(response == NULL);
+}
+
+TEST_P(HttpNetworkTransactionTest,
+ PostIgnoresNonErrorResponseAfterResetAnd100) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
+ MockRead("HTTP/1.0 302 Redirect\r\n"),
+ MockRead("Location: http://somewhere-else.com/\r\n"),
+ MockRead("Content-Length: 0\r\n\r\n"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ EXPECT_TRUE(response == NULL);
+}
+
+TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP 0.9 rocks!"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ EXPECT_TRUE(response == NULL);
+}
+
+TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(new UploadBytesElementReader("foo", 3));
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.foo.com/");
+ request.upload_data_stream = &upload_data_stream;
+ request.load_flags = 0;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+ // Send headers successfully, but get an error while sending the body.
+ MockWrite data_writes[] = {
+ MockWrite("POST / HTTP/1.1\r\n"
+ "Host: www.foo.com\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 3\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
+ arraysize(data_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ EXPECT_TRUE(response == NULL);
+}
+
} // namespace net
diff --git a/chromium/net/http/http_pipelined_connection.h b/chromium/net/http/http_pipelined_connection.h
deleted file mode 100644
index d0d3599e3f1..00000000000
--- a/chromium/net/http/http_pipelined_connection.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2012 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_HTTP_HTTP_PIPELINED_CONNECTION_H_
-#define NET_HTTP_HTTP_PIPELINED_CONNECTION_H_
-
-#include "net/base/net_export.h"
-#include "net/base/net_log.h"
-#include "net/socket/ssl_client_socket.h"
-
-namespace net {
-
-class BoundNetLog;
-class ClientSocketHandle;
-class HostPortPair;
-class HttpPipelinedStream;
-class ProxyInfo;
-struct SSLConfig;
-
-class NET_EXPORT_PRIVATE HttpPipelinedConnection {
- public:
- enum Feedback {
- OK,
- PIPELINE_SOCKET_ERROR,
- OLD_HTTP_VERSION,
- MUST_CLOSE_CONNECTION,
- AUTHENTICATION_REQUIRED,
- };
-
- class Delegate {
- public:
- // Called when a pipeline has newly available capacity. This may be because
- // the first request has been sent and the pipeline is now active. Or, it
- // may be because a request successfully completed.
- virtual void OnPipelineHasCapacity(HttpPipelinedConnection* pipeline) = 0;
-
- // Called every time a pipeline receives headers. Lets the delegate know if
- // the headers indicate that pipelining can be used.
- virtual void OnPipelineFeedback(HttpPipelinedConnection* pipeline,
- Feedback feedback) = 0;
- };
-
- class Factory {
- public:
- virtual ~Factory() {}
-
- virtual HttpPipelinedConnection* CreateNewPipeline(
- ClientSocketHandle* connection,
- Delegate* delegate,
- const HostPortPair& origin,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated) = 0;
- };
-
- virtual ~HttpPipelinedConnection() {}
-
- // Returns a new stream that uses this pipeline.
- virtual HttpPipelinedStream* CreateNewStream() = 0;
-
- // The number of streams currently associated with this pipeline.
- virtual int depth() const = 0;
-
- // True if this pipeline can accept new HTTP requests. False if a fatal error
- // has occurred.
- virtual bool usable() const = 0;
-
- // True if this pipeline has bound one request and is ready for additional
- // requests.
- virtual bool active() const = 0;
-
- // The SSLConfig used to establish this connection.
- virtual const SSLConfig& used_ssl_config() const = 0;
-
- // The ProxyInfo used to establish this connection.
- virtual const ProxyInfo& used_proxy_info() const = 0;
-
- // The BoundNetLog of this pipelined connection.
- virtual const BoundNetLog& net_log() const = 0;
-
- // True if this connection was NPN negotiated.
- virtual bool was_npn_negotiated() const = 0;
-
- // Protocol negotiated with the server.
- virtual NextProto protocol_negotiated() const = 0;
-};
-
-} // namespace net
-
-#endif // NET_HTTP_HTTP_PIPELINED_CONNECTION_H_
diff --git a/chromium/net/http/http_pipelined_connection_impl.cc b/chromium/net/http/http_pipelined_connection_impl.cc
deleted file mode 100644
index 284b25406d8..00000000000
--- a/chromium/net/http/http_pipelined_connection_impl.cc
+++ /dev/null
@@ -1,845 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_connection_impl.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/message_loop/message_loop.h"
-#include "base/stl_util.h"
-#include "base/values.h"
-#include "net/base/io_buffer.h"
-#include "net/http/http_pipelined_stream.h"
-#include "net/http/http_request_info.h"
-#include "net/http/http_response_body_drainer.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_stream_parser.h"
-#include "net/http/http_version.h"
-#include "net/socket/client_socket_handle.h"
-
-namespace net {
-
-namespace {
-
-base::Value* NetLogReceivedHeadersCallback(const NetLog::Source& source,
- const std::string* feedback,
- NetLog::LogLevel /* log_level */) {
- base::DictionaryValue* dict = new base::DictionaryValue;
- source.AddToEventParameters(dict);
- dict->SetString("feedback", *feedback);
- return dict;
-}
-
-base::Value* NetLogStreamClosedCallback(const NetLog::Source& source,
- bool not_reusable,
- NetLog::LogLevel /* log_level */) {
- base::DictionaryValue* dict = new base::DictionaryValue;
- source.AddToEventParameters(dict);
- dict->SetBoolean("not_reusable", not_reusable);
- return dict;
-}
-
-base::Value* NetLogHostPortPairCallback(const HostPortPair* host_port_pair,
- NetLog::LogLevel /* log_level */) {
- base::DictionaryValue* dict = new base::DictionaryValue;
- dict->SetString("host_and_port", host_port_pair->ToString());
- return dict;
-}
-
-} // anonymous namespace
-
-HttpPipelinedConnection*
-HttpPipelinedConnectionImpl::Factory::CreateNewPipeline(
- ClientSocketHandle* connection,
- HttpPipelinedConnection::Delegate* delegate,
- const HostPortPair& origin,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated) {
- return new HttpPipelinedConnectionImpl(connection, delegate, origin,
- used_ssl_config, used_proxy_info,
- net_log, was_npn_negotiated,
- protocol_negotiated);
-}
-
-HttpPipelinedConnectionImpl::HttpPipelinedConnectionImpl(
- ClientSocketHandle* connection,
- HttpPipelinedConnection::Delegate* delegate,
- const HostPortPair& origin,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated)
- : delegate_(delegate),
- connection_(connection),
- used_ssl_config_(used_ssl_config),
- used_proxy_info_(used_proxy_info),
- net_log_(BoundNetLog::Make(net_log.net_log(),
- NetLog::SOURCE_HTTP_PIPELINED_CONNECTION)),
- was_npn_negotiated_(was_npn_negotiated),
- protocol_negotiated_(protocol_negotiated),
- read_buf_(new GrowableIOBuffer()),
- next_pipeline_id_(1),
- active_(false),
- usable_(true),
- completed_one_request_(false),
- weak_factory_(this),
- send_next_state_(SEND_STATE_NONE),
- send_still_on_call_stack_(false),
- read_next_state_(READ_STATE_NONE),
- active_read_id_(0),
- read_still_on_call_stack_(false) {
- CHECK(connection_.get());
- net_log_.BeginEvent(
- NetLog::TYPE_HTTP_PIPELINED_CONNECTION,
- base::Bind(&NetLogHostPortPairCallback, &origin));
-}
-
-HttpPipelinedConnectionImpl::~HttpPipelinedConnectionImpl() {
- CHECK_EQ(depth(), 0);
- CHECK(stream_info_map_.empty());
- CHECK(pending_send_request_queue_.empty());
- CHECK(request_order_.empty());
- CHECK_EQ(send_next_state_, SEND_STATE_NONE);
- CHECK_EQ(read_next_state_, READ_STATE_NONE);
- CHECK(!active_send_request_.get());
- CHECK(!active_read_id_);
- if (!usable_) {
- connection_->socket()->Disconnect();
- }
- connection_->Reset();
- net_log_.EndEvent(NetLog::TYPE_HTTP_PIPELINED_CONNECTION);
-}
-
-HttpPipelinedStream* HttpPipelinedConnectionImpl::CreateNewStream() {
- int pipeline_id = next_pipeline_id_++;
- CHECK(pipeline_id);
- HttpPipelinedStream* stream = new HttpPipelinedStream(this, pipeline_id);
- stream_info_map_.insert(std::make_pair(pipeline_id, StreamInfo()));
- return stream;
-}
-
-void HttpPipelinedConnectionImpl::InitializeParser(
- int pipeline_id,
- const HttpRequestInfo* request,
- const BoundNetLog& net_log) {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK(!stream_info_map_[pipeline_id].parser.get());
- stream_info_map_[pipeline_id].state = STREAM_BOUND;
- stream_info_map_[pipeline_id].parser.reset(new HttpStreamParser(
- connection_.get(), request, read_buf_.get(), net_log));
- stream_info_map_[pipeline_id].source = net_log.source();
-
- // In case our first stream doesn't SendRequest() immediately, we should still
- // allow others to use this pipeline.
- if (pipeline_id == 1) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&HttpPipelinedConnectionImpl::ActivatePipeline,
- weak_factory_.GetWeakPtr()));
- }
-}
-
-void HttpPipelinedConnectionImpl::ActivatePipeline() {
- if (!active_) {
- active_ = true;
- delegate_->OnPipelineHasCapacity(this);
- }
-}
-
-void HttpPipelinedConnectionImpl::OnStreamDeleted(int pipeline_id) {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- Close(pipeline_id, false);
-
- if (stream_info_map_[pipeline_id].state != STREAM_CREATED &&
- stream_info_map_[pipeline_id].state != STREAM_UNUSED) {
- CHECK_EQ(stream_info_map_[pipeline_id].state, STREAM_CLOSED);
- CHECK(stream_info_map_[pipeline_id].parser.get());
- stream_info_map_[pipeline_id].parser.reset();
- }
- CHECK(!stream_info_map_[pipeline_id].parser.get());
- stream_info_map_.erase(pipeline_id);
-
- delegate_->OnPipelineHasCapacity(this);
-}
-
-int HttpPipelinedConnectionImpl::SendRequest(
- int pipeline_id,
- const std::string& request_line,
- const HttpRequestHeaders& headers,
- HttpResponseInfo* response,
- const CompletionCallback& callback) {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK_EQ(stream_info_map_[pipeline_id].state, STREAM_BOUND);
- if (!usable_) {
- return ERR_PIPELINE_EVICTION;
- }
-
- PendingSendRequest* send_request = new PendingSendRequest;
- send_request->pipeline_id = pipeline_id;
- send_request->request_line = request_line;
- send_request->headers = headers;
- send_request->response = response;
- send_request->callback = callback;
- pending_send_request_queue_.push(send_request);
-
- int rv;
- if (send_next_state_ == SEND_STATE_NONE) {
- send_next_state_ = SEND_STATE_START_IMMEDIATELY;
- rv = DoSendRequestLoop(OK);
- } else {
- rv = ERR_IO_PENDING;
- }
- ActivatePipeline();
- return rv;
-}
-
-int HttpPipelinedConnectionImpl::DoSendRequestLoop(int result) {
- int rv = result;
- do {
- SendRequestState state = send_next_state_;
- send_next_state_ = SEND_STATE_NONE;
- switch (state) {
- case SEND_STATE_START_IMMEDIATELY:
- rv = DoStartRequestImmediately(rv);
- break;
- case SEND_STATE_START_NEXT_DEFERRED_REQUEST:
- rv = DoStartNextDeferredRequest(rv);
- break;
- case SEND_STATE_SEND_ACTIVE_REQUEST:
- rv = DoSendActiveRequest(rv);
- break;
- case SEND_STATE_COMPLETE:
- rv = DoSendComplete(rv);
- break;
- case SEND_STATE_EVICT_PENDING_REQUESTS:
- rv = DoEvictPendingSendRequests(rv);
- break;
- default:
- CHECK(false) << "bad send state: " << state;
- rv = ERR_FAILED;
- break;
- }
- } while (rv != ERR_IO_PENDING && send_next_state_ != SEND_STATE_NONE);
- send_still_on_call_stack_ = false;
- return rv;
-}
-
-void HttpPipelinedConnectionImpl::OnSendIOCallback(int result) {
- CHECK(active_send_request_.get());
- DoSendRequestLoop(result);
-}
-
-int HttpPipelinedConnectionImpl::DoStartRequestImmediately(int result) {
- CHECK(!active_send_request_.get());
- CHECK_EQ(static_cast<size_t>(1), pending_send_request_queue_.size());
- // If SendRequest() completes synchronously, then we need to return the value
- // directly to the caller. |send_still_on_call_stack_| will track this.
- // Otherwise, asynchronous completions will notify the caller via callback.
- send_still_on_call_stack_ = true;
- active_send_request_.reset(pending_send_request_queue_.front());
- pending_send_request_queue_.pop();
- send_next_state_ = SEND_STATE_SEND_ACTIVE_REQUEST;
- return OK;
-}
-
-int HttpPipelinedConnectionImpl::DoStartNextDeferredRequest(int result) {
- CHECK(!send_still_on_call_stack_);
- CHECK(!active_send_request_.get());
-
- while (!pending_send_request_queue_.empty()) {
- scoped_ptr<PendingSendRequest> next_request(
- pending_send_request_queue_.front());
- pending_send_request_queue_.pop();
- CHECK(ContainsKey(stream_info_map_, next_request->pipeline_id));
- if (stream_info_map_[next_request->pipeline_id].state != STREAM_CLOSED) {
- active_send_request_.reset(next_request.release());
- send_next_state_ = SEND_STATE_SEND_ACTIVE_REQUEST;
- return OK;
- }
- }
-
- send_next_state_ = SEND_STATE_NONE;
- return OK;
-}
-
-int HttpPipelinedConnectionImpl::DoSendActiveRequest(int result) {
- CHECK(stream_info_map_[active_send_request_->pipeline_id].parser.get());
- int rv = stream_info_map_[active_send_request_->pipeline_id].parser->
- SendRequest(active_send_request_->request_line,
- active_send_request_->headers,
- active_send_request_->response,
- base::Bind(&HttpPipelinedConnectionImpl::OnSendIOCallback,
- base::Unretained(this)));
- stream_info_map_[active_send_request_->pipeline_id].state = STREAM_SENDING;
- send_next_state_ = SEND_STATE_COMPLETE;
- return rv;
-}
-
-int HttpPipelinedConnectionImpl::DoSendComplete(int result) {
- CHECK(active_send_request_.get());
- CHECK_EQ(STREAM_SENDING,
- stream_info_map_[active_send_request_->pipeline_id].state);
-
- request_order_.push(active_send_request_->pipeline_id);
- stream_info_map_[active_send_request_->pipeline_id].state = STREAM_SENT;
- net_log_.AddEvent(
- NetLog::TYPE_HTTP_PIPELINED_CONNECTION_SENT_REQUEST,
- stream_info_map_[active_send_request_->pipeline_id].source.
- ToEventParametersCallback());
-
- if (result == ERR_SOCKET_NOT_CONNECTED && completed_one_request_) {
- result = ERR_PIPELINE_EVICTION;
- }
- if (result < OK) {
- usable_ = false;
- }
-
- if (!send_still_on_call_stack_) {
- QueueUserCallback(active_send_request_->pipeline_id,
- active_send_request_->callback, result, FROM_HERE);
- }
-
- active_send_request_.reset();
-
- if (send_still_on_call_stack_) {
- // It should be impossible for another request to appear on the queue while
- // this send was on the call stack.
- CHECK(pending_send_request_queue_.empty());
- send_next_state_ = SEND_STATE_NONE;
- } else if (!usable_) {
- send_next_state_ = SEND_STATE_EVICT_PENDING_REQUESTS;
- } else {
- send_next_state_ = SEND_STATE_START_NEXT_DEFERRED_REQUEST;
- }
-
- return result;
-}
-
-int HttpPipelinedConnectionImpl::DoEvictPendingSendRequests(int result) {
- while (!pending_send_request_queue_.empty()) {
- scoped_ptr<PendingSendRequest> evicted_send(
- pending_send_request_queue_.front());
- pending_send_request_queue_.pop();
- if (ContainsKey(stream_info_map_, evicted_send->pipeline_id) &&
- stream_info_map_[evicted_send->pipeline_id].state != STREAM_CLOSED) {
- evicted_send->callback.Run(ERR_PIPELINE_EVICTION);
- }
- }
- send_next_state_ = SEND_STATE_NONE;
- return result;
-}
-
-int HttpPipelinedConnectionImpl::ReadResponseHeaders(
- int pipeline_id, const CompletionCallback& callback) {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK_EQ(STREAM_SENT, stream_info_map_[pipeline_id].state);
- CHECK(stream_info_map_[pipeline_id].read_headers_callback.is_null());
-
- if (!usable_)
- return ERR_PIPELINE_EVICTION;
-
- stream_info_map_[pipeline_id].state = STREAM_READ_PENDING;
- stream_info_map_[pipeline_id].read_headers_callback = callback;
- if (read_next_state_ == READ_STATE_NONE &&
- pipeline_id == request_order_.front()) {
- read_next_state_ = READ_STATE_START_IMMEDIATELY;
- return DoReadHeadersLoop(OK);
- }
- return ERR_IO_PENDING;
-}
-
-void HttpPipelinedConnectionImpl::StartNextDeferredRead() {
- if (read_next_state_ == READ_STATE_NONE) {
- read_next_state_ = READ_STATE_START_NEXT_DEFERRED_READ;
- DoReadHeadersLoop(OK);
- }
-}
-
-int HttpPipelinedConnectionImpl::DoReadHeadersLoop(int result) {
- int rv = result;
- do {
- ReadHeadersState state = read_next_state_;
- read_next_state_ = READ_STATE_NONE;
- switch (state) {
- case READ_STATE_START_IMMEDIATELY:
- rv = DoStartReadImmediately(rv);
- break;
- case READ_STATE_START_NEXT_DEFERRED_READ:
- rv = DoStartNextDeferredRead(rv);
- break;
- case READ_STATE_READ_HEADERS:
- rv = DoReadHeaders(rv);
- break;
- case READ_STATE_READ_HEADERS_COMPLETE:
- rv = DoReadHeadersComplete(rv);
- break;
- case READ_STATE_WAITING_FOR_CLOSE:
- // This is a holding state. We return instead of continuing to run hte
- // loop. The state will advance when the stream calls Close().
- rv = DoReadWaitForClose(rv);
- read_still_on_call_stack_ = false;
- return rv;
- case READ_STATE_STREAM_CLOSED:
- rv = DoReadStreamClosed();
- break;
- case READ_STATE_EVICT_PENDING_READS:
- rv = DoEvictPendingReadHeaders(rv);
- break;
- case READ_STATE_NONE:
- break;
- default:
- CHECK(false) << "bad read state";
- rv = ERR_FAILED;
- break;
- }
- } while (rv != ERR_IO_PENDING && read_next_state_ != READ_STATE_NONE);
- read_still_on_call_stack_ = false;
- return rv;
-}
-
-void HttpPipelinedConnectionImpl::OnReadIOCallback(int result) {
- DoReadHeadersLoop(result);
-}
-
-int HttpPipelinedConnectionImpl::DoStartReadImmediately(int result) {
- CHECK(!active_read_id_);
- CHECK(!read_still_on_call_stack_);
- CHECK(!request_order_.empty());
- // If ReadResponseHeaders() completes synchronously, then we need to return
- // the value directly to the caller. |read_still_on_call_stack_| will track
- // this. Otherwise, asynchronous completions will notify the caller via
- // callback.
- read_still_on_call_stack_ = true;
- read_next_state_ = READ_STATE_READ_HEADERS;
- active_read_id_ = request_order_.front();
- request_order_.pop();
- return OK;
-}
-
-int HttpPipelinedConnectionImpl::DoStartNextDeferredRead(int result) {
- CHECK(!active_read_id_);
- CHECK(!read_still_on_call_stack_);
-
- if (request_order_.empty()) {
- read_next_state_ = READ_STATE_NONE;
- return OK;
- }
-
- int next_id = request_order_.front();
- CHECK(ContainsKey(stream_info_map_, next_id));
- switch (stream_info_map_[next_id].state) {
- case STREAM_READ_PENDING:
- read_next_state_ = READ_STATE_READ_HEADERS;
- active_read_id_ = next_id;
- request_order_.pop();
- break;
-
- case STREAM_CLOSED:
- // Since nobody will read whatever data is on the pipeline associated with
- // this closed request, we must shut down the rest of the pipeline.
- read_next_state_ = READ_STATE_EVICT_PENDING_READS;
- break;
-
- case STREAM_SENT:
- read_next_state_ = READ_STATE_NONE;
- break;
-
- default:
- CHECK(false) << "Unexpected read state: "
- << stream_info_map_[next_id].state;
- }
-
- return OK;
-}
-
-int HttpPipelinedConnectionImpl::DoReadHeaders(int result) {
- CHECK(active_read_id_);
- CHECK(ContainsKey(stream_info_map_, active_read_id_));
- CHECK_EQ(STREAM_READ_PENDING, stream_info_map_[active_read_id_].state);
- stream_info_map_[active_read_id_].state = STREAM_ACTIVE;
- int rv = stream_info_map_[active_read_id_].parser->ReadResponseHeaders(
- base::Bind(&HttpPipelinedConnectionImpl::OnReadIOCallback,
- base::Unretained(this)));
- read_next_state_ = READ_STATE_READ_HEADERS_COMPLETE;
- return rv;
-}
-
-int HttpPipelinedConnectionImpl::DoReadHeadersComplete(int result) {
- CHECK(active_read_id_);
- CHECK(ContainsKey(stream_info_map_, active_read_id_));
- CHECK_EQ(STREAM_ACTIVE, stream_info_map_[active_read_id_].state);
-
- read_next_state_ = READ_STATE_WAITING_FOR_CLOSE;
- if (result < OK) {
- if (completed_one_request_ &&
- (result == ERR_CONNECTION_CLOSED ||
- result == ERR_EMPTY_RESPONSE ||
- result == ERR_SOCKET_NOT_CONNECTED)) {
- // These usually indicate that pipelining failed on the server side. In
- // that case, we should retry without pipelining.
- result = ERR_PIPELINE_EVICTION;
- }
- usable_ = false;
- }
-
- CheckHeadersForPipelineCompatibility(active_read_id_, result);
-
- if (!read_still_on_call_stack_) {
- QueueUserCallback(active_read_id_,
- stream_info_map_[active_read_id_].read_headers_callback,
- result, FROM_HERE);
- }
-
- return result;
-}
-
-int HttpPipelinedConnectionImpl::DoReadWaitForClose(int result) {
- read_next_state_ = READ_STATE_WAITING_FOR_CLOSE;
- return result;
-}
-
-int HttpPipelinedConnectionImpl::DoReadStreamClosed() {
- CHECK(active_read_id_);
- CHECK(ContainsKey(stream_info_map_, active_read_id_));
- CHECK_EQ(stream_info_map_[active_read_id_].state, STREAM_CLOSED);
- active_read_id_ = 0;
- if (!usable_) {
- // TODO(simonjam): Don't wait this long to evict.
- read_next_state_ = READ_STATE_EVICT_PENDING_READS;
- return OK;
- }
- completed_one_request_ = true;
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&HttpPipelinedConnectionImpl::StartNextDeferredRead,
- weak_factory_.GetWeakPtr()));
- read_next_state_ = READ_STATE_NONE;
- return OK;
-}
-
-int HttpPipelinedConnectionImpl::DoEvictPendingReadHeaders(int result) {
- while (!request_order_.empty()) {
- int evicted_id = request_order_.front();
- request_order_.pop();
- if (!ContainsKey(stream_info_map_, evicted_id)) {
- continue;
- }
- if (stream_info_map_[evicted_id].state == STREAM_READ_PENDING) {
- stream_info_map_[evicted_id].state = STREAM_READ_EVICTED;
- stream_info_map_[evicted_id].read_headers_callback.Run(
- ERR_PIPELINE_EVICTION);
- }
- }
- read_next_state_ = READ_STATE_NONE;
- return result;
-}
-
-void HttpPipelinedConnectionImpl::Close(int pipeline_id,
- bool not_reusable) {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- net_log_.AddEvent(
- NetLog::TYPE_HTTP_PIPELINED_CONNECTION_STREAM_CLOSED,
- base::Bind(&NetLogStreamClosedCallback,
- stream_info_map_[pipeline_id].source, not_reusable));
- switch (stream_info_map_[pipeline_id].state) {
- case STREAM_CREATED:
- stream_info_map_[pipeline_id].state = STREAM_UNUSED;
- break;
-
- case STREAM_BOUND:
- stream_info_map_[pipeline_id].state = STREAM_CLOSED;
- break;
-
- case STREAM_SENDING:
- usable_ = false;
- stream_info_map_[pipeline_id].state = STREAM_CLOSED;
- active_send_request_.reset();
- send_next_state_ = SEND_STATE_EVICT_PENDING_REQUESTS;
- DoSendRequestLoop(OK);
- break;
-
- case STREAM_SENT:
- case STREAM_READ_PENDING:
- usable_ = false;
- stream_info_map_[pipeline_id].state = STREAM_CLOSED;
- if (!request_order_.empty() &&
- pipeline_id == request_order_.front() &&
- read_next_state_ == READ_STATE_NONE) {
- read_next_state_ = READ_STATE_EVICT_PENDING_READS;
- DoReadHeadersLoop(OK);
- }
- break;
-
- case STREAM_ACTIVE:
- stream_info_map_[pipeline_id].state = STREAM_CLOSED;
- if (not_reusable) {
- usable_ = false;
- }
- read_next_state_ = READ_STATE_STREAM_CLOSED;
- DoReadHeadersLoop(OK);
- break;
-
- case STREAM_READ_EVICTED:
- stream_info_map_[pipeline_id].state = STREAM_CLOSED;
- break;
-
- case STREAM_CLOSED:
- case STREAM_UNUSED:
- // TODO(simonjam): Why is Close() sometimes called twice?
- break;
-
- default:
- CHECK(false);
- break;
- }
-}
-
-int HttpPipelinedConnectionImpl::ReadResponseBody(
- int pipeline_id, IOBuffer* buf, int buf_len,
- const CompletionCallback& callback) {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK_EQ(active_read_id_, pipeline_id);
- CHECK(stream_info_map_[pipeline_id].parser.get());
- return stream_info_map_[pipeline_id].parser->ReadResponseBody(
- buf, buf_len, callback);
-}
-
-UploadProgress HttpPipelinedConnectionImpl::GetUploadProgress(
- int pipeline_id) const {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK(stream_info_map_.find(pipeline_id)->second.parser.get());
- return stream_info_map_.find(pipeline_id)->second.parser->GetUploadProgress();
-}
-
-HttpResponseInfo* HttpPipelinedConnectionImpl::GetResponseInfo(
- int pipeline_id) {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK(stream_info_map_.find(pipeline_id)->second.parser.get());
- return stream_info_map_.find(pipeline_id)->second.parser->GetResponseInfo();
-}
-
-bool HttpPipelinedConnectionImpl::IsResponseBodyComplete(
- int pipeline_id) const {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK(stream_info_map_.find(pipeline_id)->second.parser.get());
- return stream_info_map_.find(pipeline_id)->second.parser->
- IsResponseBodyComplete();
-}
-
-bool HttpPipelinedConnectionImpl::CanFindEndOfResponse(int pipeline_id) const {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK(stream_info_map_.find(pipeline_id)->second.parser.get());
- return stream_info_map_.find(pipeline_id)->second.parser->
- CanFindEndOfResponse();
-}
-
-bool HttpPipelinedConnectionImpl::IsConnectionReused(int pipeline_id) const {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- if (pipeline_id > 1) {
- return true;
- }
- ClientSocketHandle::SocketReuseType reuse_type = connection_->reuse_type();
- return connection_->is_reused() ||
- reuse_type == ClientSocketHandle::UNUSED_IDLE;
-}
-
-void HttpPipelinedConnectionImpl::SetConnectionReused(int pipeline_id) {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- connection_->set_is_reused(true);
-}
-
-int64 HttpPipelinedConnectionImpl::GetTotalReceivedBytes(
- int pipeline_id) const {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK(stream_info_map_.find(pipeline_id)->second.parser.get());
- return stream_info_map_.find(pipeline_id)->second.parser->received_bytes();
-}
-
-bool HttpPipelinedConnectionImpl::GetLoadTimingInfo(
- int pipeline_id, LoadTimingInfo* load_timing_info) const {
- return connection_->GetLoadTimingInfo(IsConnectionReused(pipeline_id),
- load_timing_info);
-}
-
-void HttpPipelinedConnectionImpl::GetSSLInfo(int pipeline_id,
- SSLInfo* ssl_info) {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK(stream_info_map_[pipeline_id].parser.get());
- stream_info_map_[pipeline_id].parser->GetSSLInfo(ssl_info);
-}
-
-void HttpPipelinedConnectionImpl::GetSSLCertRequestInfo(
- int pipeline_id,
- SSLCertRequestInfo* cert_request_info) {
- CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK(stream_info_map_[pipeline_id].parser.get());
- stream_info_map_[pipeline_id].parser->GetSSLCertRequestInfo(
- cert_request_info);
-}
-
-void HttpPipelinedConnectionImpl::Drain(HttpPipelinedStream* stream,
- HttpNetworkSession* session) {
- HttpResponseHeaders* headers = stream->GetResponseInfo()->headers.get();
- if (!stream->CanFindEndOfResponse() || headers->IsChunkEncoded() ||
- !usable_) {
- // TODO(simonjam): Drain chunk-encoded responses if they're relatively
- // common.
- stream->Close(true);
- delete stream;
- return;
- }
- HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(stream);
- drainer->StartWithSize(session, headers->GetContentLength());
- // |drainer| will delete itself when done.
-}
-
-void HttpPipelinedConnectionImpl::CheckHeadersForPipelineCompatibility(
- int pipeline_id,
- int result) {
- if (result < OK) {
- switch (result) {
- // TODO(simonjam): Ignoring specific errors like this may not work.
- // Collect metrics to see if this code is useful.
- case ERR_ABORTED:
- case ERR_INTERNET_DISCONNECTED:
- case ERR_NETWORK_CHANGED:
- // These errors are no fault of the server.
- break;
-
- default:
- ReportPipelineFeedback(pipeline_id, PIPELINE_SOCKET_ERROR);
- break;
- }
- return;
- }
- HttpResponseInfo* info = GetResponseInfo(pipeline_id);
- const HttpVersion required_version(1, 1);
- if (info->headers->GetParsedHttpVersion() < required_version) {
- ReportPipelineFeedback(pipeline_id, OLD_HTTP_VERSION);
- return;
- }
- if (!info->headers->IsKeepAlive() || !CanFindEndOfResponse(pipeline_id)) {
- usable_ = false;
- ReportPipelineFeedback(pipeline_id, MUST_CLOSE_CONNECTION);
- return;
- }
- if (info->headers->HasHeader(
- HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_SERVER))) {
- ReportPipelineFeedback(pipeline_id, AUTHENTICATION_REQUIRED);
- return;
- }
- ReportPipelineFeedback(pipeline_id, OK);
-}
-
-void HttpPipelinedConnectionImpl::ReportPipelineFeedback(int pipeline_id,
- Feedback feedback) {
- std::string feedback_str;
- switch (feedback) {
- case OK:
- feedback_str = "OK";
- break;
-
- case PIPELINE_SOCKET_ERROR:
- feedback_str = "PIPELINE_SOCKET_ERROR";
- break;
-
- case OLD_HTTP_VERSION:
- feedback_str = "OLD_HTTP_VERSION";
- break;
-
- case MUST_CLOSE_CONNECTION:
- feedback_str = "MUST_CLOSE_CONNECTION";
- break;
-
- case AUTHENTICATION_REQUIRED:
- feedback_str = "AUTHENTICATION_REQUIRED";
- break;
-
- default:
- NOTREACHED();
- feedback_str = "UNKNOWN";
- break;
- }
- net_log_.AddEvent(
- NetLog::TYPE_HTTP_PIPELINED_CONNECTION_RECEIVED_HEADERS,
- base::Bind(&NetLogReceivedHeadersCallback,
- stream_info_map_[pipeline_id].source, &feedback_str));
- delegate_->OnPipelineFeedback(this, feedback);
-}
-
-void HttpPipelinedConnectionImpl::QueueUserCallback(
- int pipeline_id, const CompletionCallback& callback, int rv,
- const tracked_objects::Location& from_here) {
- CHECK(stream_info_map_[pipeline_id].pending_user_callback.is_null());
- stream_info_map_[pipeline_id].pending_user_callback = callback;
- base::MessageLoop::current()->PostTask(
- from_here,
- base::Bind(&HttpPipelinedConnectionImpl::FireUserCallback,
- weak_factory_.GetWeakPtr(), pipeline_id, rv));
-}
-
-void HttpPipelinedConnectionImpl::FireUserCallback(int pipeline_id,
- int result) {
- if (ContainsKey(stream_info_map_, pipeline_id)) {
- CHECK(!stream_info_map_[pipeline_id].pending_user_callback.is_null());
- CompletionCallback callback =
- stream_info_map_[pipeline_id].pending_user_callback;
- stream_info_map_[pipeline_id].pending_user_callback.Reset();
- callback.Run(result);
- }
-}
-
-int HttpPipelinedConnectionImpl::depth() const {
- return stream_info_map_.size();
-}
-
-bool HttpPipelinedConnectionImpl::usable() const {
- return usable_;
-}
-
-bool HttpPipelinedConnectionImpl::active() const {
- return active_;
-}
-
-const SSLConfig& HttpPipelinedConnectionImpl::used_ssl_config() const {
- return used_ssl_config_;
-}
-
-const ProxyInfo& HttpPipelinedConnectionImpl::used_proxy_info() const {
- return used_proxy_info_;
-}
-
-const BoundNetLog& HttpPipelinedConnectionImpl::net_log() const {
- return net_log_;
-}
-
-bool HttpPipelinedConnectionImpl::was_npn_negotiated() const {
- return was_npn_negotiated_;
-}
-
-NextProto HttpPipelinedConnectionImpl::protocol_negotiated()
- const {
- return protocol_negotiated_;
-}
-
-HttpPipelinedConnectionImpl::PendingSendRequest::PendingSendRequest()
- : pipeline_id(0),
- response(NULL) {
-}
-
-HttpPipelinedConnectionImpl::PendingSendRequest::~PendingSendRequest() {
-}
-
-HttpPipelinedConnectionImpl::StreamInfo::StreamInfo()
- : state(STREAM_CREATED) {
-}
-
-HttpPipelinedConnectionImpl::StreamInfo::~StreamInfo() {
-}
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_connection_impl.h b/chromium/net/http/http_pipelined_connection_impl.h
deleted file mode 100644
index d558e47eb0b..00000000000
--- a/chromium/net/http/http_pipelined_connection_impl.h
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright (c) 2012 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_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_
-#define NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_
-
-#include <map>
-#include <queue>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/location.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "net/base/completion_callback.h"
-#include "net/base/net_export.h"
-#include "net/base/net_log.h"
-#include "net/http/http_pipelined_connection.h"
-#include "net/http/http_request_info.h"
-#include "net/http/http_stream_parser.h"
-#include "net/proxy/proxy_info.h"
-#include "net/ssl/ssl_config_service.h"
-
-namespace net {
-
-class ClientSocketHandle;
-class GrowableIOBuffer;
-class HostPortPair;
-class HttpNetworkSession;
-class HttpRequestHeaders;
-class HttpResponseInfo;
-class IOBuffer;
-struct LoadTimingInfo;
-class SSLCertRequestInfo;
-class SSLInfo;
-
-// This class manages all of the state for a single pipelined connection. It
-// tracks the order that HTTP requests are sent and enforces that the
-// subsequent reads occur in the appropriate order.
-//
-// If an error occurs related to pipelining, ERR_PIPELINE_EVICTION will be
-// returned to the client. This indicates the client should retry the request
-// without pipelining.
-class NET_EXPORT_PRIVATE HttpPipelinedConnectionImpl
- : public HttpPipelinedConnection {
- public:
- class Factory : public HttpPipelinedConnection::Factory {
- public:
- virtual HttpPipelinedConnection* CreateNewPipeline(
- ClientSocketHandle* connection,
- HttpPipelinedConnection::Delegate* delegate,
- const HostPortPair& origin,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated) OVERRIDE;
- };
-
- HttpPipelinedConnectionImpl(ClientSocketHandle* connection,
- Delegate* delegate,
- const HostPortPair& origin,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated);
- virtual ~HttpPipelinedConnectionImpl();
-
- // HttpPipelinedConnection interface.
-
- // Used by HttpStreamFactoryImpl and friends.
- virtual HttpPipelinedStream* CreateNewStream() OVERRIDE;
-
- // Used by HttpPipelinedHost.
- virtual int depth() const OVERRIDE;
- virtual bool usable() const OVERRIDE;
- virtual bool active() const OVERRIDE;
-
- // Used by HttpStreamFactoryImpl.
- virtual const SSLConfig& used_ssl_config() const OVERRIDE;
- virtual const ProxyInfo& used_proxy_info() const OVERRIDE;
- virtual const BoundNetLog& net_log() const OVERRIDE;
- virtual bool was_npn_negotiated() const OVERRIDE;
- virtual NextProto protocol_negotiated() const OVERRIDE;
-
- // Used by HttpPipelinedStream.
-
- // Notifies this pipeline that a stream is no longer using it.
- void OnStreamDeleted(int pipeline_id);
-
- // Effective implementation of HttpStream. Note that we don't directly
- // implement that interface. Instead, these functions will be called by the
- // pass-through methods in HttpPipelinedStream.
- void InitializeParser(int pipeline_id,
- const HttpRequestInfo* request,
- const BoundNetLog& net_log);
-
- int SendRequest(int pipeline_id,
- const std::string& request_line,
- const HttpRequestHeaders& headers,
- HttpResponseInfo* response,
- const CompletionCallback& callback);
-
- int ReadResponseHeaders(int pipeline_id,
- const CompletionCallback& callback);
-
- int ReadResponseBody(int pipeline_id,
- IOBuffer* buf, int buf_len,
- const CompletionCallback& callback);
-
- void Close(int pipeline_id,
- bool not_reusable);
-
- UploadProgress GetUploadProgress(int pipeline_id) const;
-
- HttpResponseInfo* GetResponseInfo(int pipeline_id);
-
- bool IsResponseBodyComplete(int pipeline_id) const;
-
- bool CanFindEndOfResponse(int pipeline_id) const;
-
- bool IsConnectionReused(int pipeline_id) const;
-
- void SetConnectionReused(int pipeline_id);
-
- int64 GetTotalReceivedBytes(int pipeline_id) const;
-
- bool GetLoadTimingInfo(int pipeline_id,
- LoadTimingInfo* load_timing_info) const;
-
- void GetSSLInfo(int pipeline_id, SSLInfo* ssl_info);
-
- void GetSSLCertRequestInfo(int pipeline_id,
- SSLCertRequestInfo* cert_request_info);
-
- // Attempts to drain the response body for |stream| so that the pipeline may
- // be reused.
- void Drain(HttpPipelinedStream* stream, HttpNetworkSession* session);
-
- private:
- enum StreamState {
- STREAM_CREATED,
- STREAM_BOUND,
- STREAM_SENDING,
- STREAM_SENT,
- STREAM_READ_PENDING,
- STREAM_ACTIVE,
- STREAM_CLOSED,
- STREAM_READ_EVICTED,
- STREAM_UNUSED,
- };
- enum SendRequestState {
- SEND_STATE_START_IMMEDIATELY,
- SEND_STATE_START_NEXT_DEFERRED_REQUEST,
- SEND_STATE_SEND_ACTIVE_REQUEST,
- SEND_STATE_COMPLETE,
- SEND_STATE_EVICT_PENDING_REQUESTS,
- SEND_STATE_NONE,
- };
- enum ReadHeadersState {
- READ_STATE_START_IMMEDIATELY,
- READ_STATE_START_NEXT_DEFERRED_READ,
- READ_STATE_READ_HEADERS,
- READ_STATE_READ_HEADERS_COMPLETE,
- READ_STATE_WAITING_FOR_CLOSE,
- READ_STATE_STREAM_CLOSED,
- READ_STATE_NONE,
- READ_STATE_EVICT_PENDING_READS,
- };
-
- struct PendingSendRequest {
- PendingSendRequest();
- ~PendingSendRequest();
-
- int pipeline_id;
- std::string request_line;
- HttpRequestHeaders headers;
- HttpResponseInfo* response;
- CompletionCallback callback;
- };
-
- struct StreamInfo {
- StreamInfo();
- ~StreamInfo();
-
- linked_ptr<HttpStreamParser> parser;
- CompletionCallback read_headers_callback;
- CompletionCallback pending_user_callback;
- StreamState state;
- NetLog::Source source;
- };
-
- typedef std::map<int, StreamInfo> StreamInfoMap;
-
- // Called after the first request is sent or in a task sometime after the
- // first stream is added to this pipeline. This gives the first request
- // priority to send, but doesn't hold up other requests if it doesn't.
- // When called the first time, notifies the |delegate_| that we can accept new
- // requests.
- void ActivatePipeline();
-
- // Responsible for sending one request at a time and waiting until each
- // comepletes.
- int DoSendRequestLoop(int result);
-
- // Called when an asynchronous Send() completes.
- void OnSendIOCallback(int result);
-
- // Activates the only request in |pending_send_request_queue_|. This should
- // only be called via SendRequest() when the send loop is idle.
- int DoStartRequestImmediately(int result);
-
- // Activates the first request in |pending_send_request_queue_| that hasn't
- // been closed, if any. This is called via DoSendComplete() after a prior
- // request complets.
- int DoStartNextDeferredRequest(int result);
-
- // Sends the active request.
- int DoSendActiveRequest(int result);
-
- // Notifies the user that the send has completed. This may be called directly
- // after SendRequest() for a synchronous request, or it may be called in
- // response to OnSendIOCallback for an asynchronous request.
- int DoSendComplete(int result);
-
- // Evicts all unsent deferred requests. This is called if there is a Send()
- // error or one of our streams informs us the connection is no longer
- // reusable.
- int DoEvictPendingSendRequests(int result);
-
- // Ensures that only the active request's HttpPipelinedSocket can read from
- // the underlying socket until it completes. A HttpPipelinedSocket informs us
- // that it's done by calling Close().
- int DoReadHeadersLoop(int result);
-
- // Called when the pending asynchronous ReadResponseHeaders() completes.
- void OnReadIOCallback(int result);
-
- // Invokes DoStartNextDeferredRead() if the read loop is idle. This is called
- // via a task queued when the previous |active_read_id_| closes its stream
- // after a succesful response.
- void StartNextDeferredRead();
-
- // Activates the next read request immediately. This is called via
- // ReadResponseHeaders() if that stream is at the front of |request_order_|
- // and the read loop is idle.
- int DoStartReadImmediately(int result);
-
- // Activates the next read request in |request_order_| if it's ready to go.
- // This is called via StartNextDeferredRead().
- int DoStartNextDeferredRead(int result);
-
- // Calls ReadResponseHeaders() on the active request's parser.
- int DoReadHeaders(int result);
-
- // Notifies the user that reading the headers has completed. This may happen
- // directly after DoReadNextHeaders() if the response is already available.
- // Otherwise, it is called in response to OnReadIOCallback().
- int DoReadHeadersComplete(int result);
-
- // Halts the read loop until Close() is called by the active stream.
- int DoReadWaitForClose(int result);
-
- // Cleans up the state associated with the active request. Invokes
- // DoReadNextHeaders() in a new task to start the next response. This is
- // called after the active request's HttpPipelinedSocket calls Close().
- int DoReadStreamClosed();
-
- // Removes all pending ReadResponseHeaders() requests from the queue. This may
- // happen if there is an error with the pipeline or one of our
- // HttpPipelinedSockets indicates the connection was suddenly closed.
- int DoEvictPendingReadHeaders(int result);
-
- // Determines if the response headers indicate pipelining will work. This is
- // called every time we receive headers.
- void CheckHeadersForPipelineCompatibility(int pipeline_id, int result);
-
- // Reports back to |delegate_| whether pipelining will work.
- void ReportPipelineFeedback(int pipeline_id, Feedback feedback);
-
- // Posts a task to fire the user's callback in response to SendRequest() or
- // ReadResponseHeaders() completing on an underlying parser. This might be
- // invoked in response to our own IO callbacks, or it may be invoked if the
- // underlying parser completes SendRequest() or ReadResponseHeaders()
- // synchronously, but we've already returned ERR_IO_PENDING to the user's
- // SendRequest() or ReadResponseHeaders() call into us.
- void QueueUserCallback(int pipeline_id,
- const CompletionCallback& callback,
- int rv,
- const tracked_objects::Location& from_here);
-
- // Invokes the callback queued in QueueUserCallback().
- void FireUserCallback(int pipeline_id, int result);
-
- Delegate* delegate_;
- scoped_ptr<ClientSocketHandle> connection_;
- SSLConfig used_ssl_config_;
- ProxyInfo used_proxy_info_;
- BoundNetLog net_log_;
- bool was_npn_negotiated_;
- // Protocol negotiated with the server.
- NextProto protocol_negotiated_;
- scoped_refptr<GrowableIOBuffer> read_buf_;
- int next_pipeline_id_;
- bool active_;
- bool usable_;
- bool completed_one_request_;
- base::WeakPtrFactory<HttpPipelinedConnectionImpl> weak_factory_;
-
- StreamInfoMap stream_info_map_;
-
- std::queue<int> request_order_;
-
- std::queue<PendingSendRequest*> pending_send_request_queue_;
- scoped_ptr<PendingSendRequest> active_send_request_;
- SendRequestState send_next_state_;
- bool send_still_on_call_stack_;
-
- ReadHeadersState read_next_state_;
- int active_read_id_;
- bool read_still_on_call_stack_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpPipelinedConnectionImpl);
-};
-
-} // namespace net
-
-#endif // NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_
diff --git a/chromium/net/http/http_pipelined_connection_impl_unittest.cc b/chromium/net/http/http_pipelined_connection_impl_unittest.cc
deleted file mode 100644
index 296194ecd63..00000000000
--- a/chromium/net/http/http_pipelined_connection_impl_unittest.cc
+++ /dev/null
@@ -1,1597 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_connection_impl.h"
-
-#include <string>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "net/base/capturing_net_log.h"
-#include "net/base/io_buffer.h"
-#include "net/base/load_timing_info.h"
-#include "net/base/load_timing_info_test_util.h"
-#include "net/base/net_errors.h"
-#include "net/base/request_priority.h"
-#include "net/http/http_pipelined_stream.h"
-#include "net/socket/client_socket_handle.h"
-#include "net/socket/client_socket_pool_histograms.h"
-#include "net/socket/socket_test_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::_;
-using testing::NiceMock;
-using testing::StrEq;
-
-namespace net {
-
-namespace {
-
-// Tests the load timing of a stream that's connected and is not the first
-// request sent on a connection.
-void TestLoadTimingReused(const HttpStream& stream) {
- LoadTimingInfo load_timing_info;
- EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info));
-
- EXPECT_TRUE(load_timing_info.socket_reused);
- EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
-
- ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
- ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
-}
-
-// Tests the load timing of a stream that's connected and using a fresh
-// connection.
-void TestLoadTimingNotReused(const HttpStream& stream) {
- LoadTimingInfo load_timing_info;
- EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info));
-
- EXPECT_FALSE(load_timing_info.socket_reused);
- EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
-
- ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
- CONNECT_TIMING_HAS_DNS_TIMES);
- ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
-}
-
-class MockPipelineDelegate : public HttpPipelinedConnection::Delegate {
- public:
- MOCK_METHOD1(OnPipelineHasCapacity, void(HttpPipelinedConnection* pipeline));
- MOCK_METHOD2(OnPipelineFeedback, void(
- HttpPipelinedConnection* pipeline,
- HttpPipelinedConnection::Feedback feedback));
-};
-
-class SuddenCloseObserver : public base::MessageLoop::TaskObserver {
- public:
- SuddenCloseObserver(HttpStream* stream, int close_before_task)
- : stream_(stream),
- close_before_task_(close_before_task),
- current_task_(0) { }
-
- virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
- ++current_task_;
- if (current_task_ == close_before_task_) {
- stream_->Close(false);
- base::MessageLoop::current()->RemoveTaskObserver(this);
- }
- }
-
- virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {}
-
- private:
- HttpStream* stream_;
- int close_before_task_;
- int current_task_;
-};
-
-class HttpPipelinedConnectionImplTest : public testing::Test {
- public:
- HttpPipelinedConnectionImplTest()
- : histograms_("a"),
- pool_(1, 1, &histograms_, &factory_),
- origin_("host", 123) {
- }
-
- void TearDown() {
- base::MessageLoop::current()->RunUntilIdle();
- }
-
- void Initialize(MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count) {
- data_.reset(new DeterministicSocketData(reads, reads_count,
- writes, writes_count));
- data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
- if (reads_count || writes_count) {
- data_->StopAfter(reads_count + writes_count);
- }
- factory_.AddSocketDataProvider(data_.get());
- scoped_refptr<MockTransportSocketParams> params;
- ClientSocketHandle* connection = new ClientSocketHandle;
- // Only give the connection a real NetLog to make sure that LoadTiming uses
- // the connection's ID, rather than the pipeline's. Since pipelines are
- // destroyed when they've responded to all requests, but the connection
- // lives on, this is an important behavior.
- connection->Init("a", params, MEDIUM, CompletionCallback(), &pool_,
- net_log_.bound());
- pipeline_.reset(new HttpPipelinedConnectionImpl(
- connection, &delegate_, origin_, ssl_config_, proxy_info_,
- BoundNetLog(), false, kProtoUnknown));
- }
-
- HttpRequestInfo* GetRequestInfo(const std::string& filename) {
- HttpRequestInfo* request_info = new HttpRequestInfo;
- request_info->url = GURL("http://localhost/" + filename);
- request_info->method = "GET";
- request_info_vector_.push_back(request_info);
- return request_info;
- }
-
- HttpStream* NewTestStream(const std::string& filename) {
- HttpStream* stream = pipeline_->CreateNewStream();
- HttpRequestInfo* request_info = GetRequestInfo(filename);
- int rv = stream->InitializeStream(
- request_info, DEFAULT_PRIORITY, BoundNetLog(), CompletionCallback());
- DCHECK_EQ(OK, rv);
- return stream;
- }
-
- void ExpectResponse(const std::string& expected,
- scoped_ptr<HttpStream>& stream, bool async) {
- scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size()));
-
- if (async) {
- EXPECT_EQ(ERR_IO_PENDING,
- stream->ReadResponseBody(buffer.get(), expected.size(),
- callback_.callback()));
- data_->RunFor(1);
- EXPECT_EQ(static_cast<int>(expected.size()), callback_.WaitForResult());
- } else {
- EXPECT_EQ(static_cast<int>(expected.size()),
- stream->ReadResponseBody(buffer.get(), expected.size(),
- callback_.callback()));
- }
- std::string actual(buffer->data(), expected.size());
- EXPECT_THAT(actual, StrEq(expected));
- }
-
- void TestSyncRequest(scoped_ptr<HttpStream>& stream,
- const std::string& filename) {
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, stream->SendRequest(headers, &response,
- callback_.callback()));
- EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback()));
- ExpectResponse(filename, stream, false);
-
- stream->Close(false);
- }
-
- CapturingBoundNetLog net_log_;
- DeterministicMockClientSocketFactory factory_;
- ClientSocketPoolHistograms histograms_;
- MockTransportClientSocketPool pool_;
- scoped_ptr<DeterministicSocketData> data_;
-
- HostPortPair origin_;
- SSLConfig ssl_config_;
- ProxyInfo proxy_info_;
- NiceMock<MockPipelineDelegate> delegate_;
- TestCompletionCallback callback_;
- scoped_ptr<HttpPipelinedConnectionImpl> pipeline_;
- ScopedVector<HttpRequestInfo> request_info_vector_;
-};
-
-TEST_F(HttpPipelinedConnectionImplTest, PipelineNotUsed) {
- Initialize(NULL, 0, NULL, 0);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, StreamNotUsed) {
- Initialize(NULL, 0, NULL, 0);
-
- scoped_ptr<HttpStream> stream(pipeline_->CreateNewStream());
-
- stream->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, StreamBoundButNotUsed) {
- Initialize(NULL, 0, NULL, 0);
-
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
-
- TestLoadTimingNotReused(*stream);
- stream->Close(false);
- TestLoadTimingNotReused(*stream);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, SyncSingleRequest) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "ok.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
- TestLoadTimingNotReused(*stream);
- TestSyncRequest(stream, "ok.html");
- TestLoadTimingNotReused(*stream);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, AsyncSingleRequest) {
- MockWrite writes[] = {
- MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"),
- MockRead(ASYNC, 3, "ok.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(headers, &response,
- callback_.callback()));
- data_->RunFor(1);
- EXPECT_LE(OK, callback_.WaitForResult());
- TestLoadTimingNotReused(*stream);
-
- EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
- data_->RunFor(2);
- EXPECT_LE(OK, callback_.WaitForResult());
- TestLoadTimingNotReused(*stream);
-
- ExpectResponse("ok.html", stream, true);
- TestLoadTimingNotReused(*stream);
-
- stream->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, LockStepAsyncRequests) {
- MockWrite writes[] = {
- MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(ASYNC, 1, "GET /ko.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"),
- MockRead(ASYNC, 4, "ok.html"),
- MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 6, "Content-Length: 7\r\n\r\n"),
- MockRead(ASYNC, 7, "ko.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream1(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> stream2(NewTestStream("ko.html"));
-
- HttpRequestHeaders headers1;
- HttpResponseInfo response1;
- EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(headers1, &response1,
- callback_.callback()));
- TestLoadTimingNotReused(*stream1);
-
- HttpRequestHeaders headers2;
- HttpResponseInfo response2;
- EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(headers2, &response2,
- callback_.callback()));
- TestLoadTimingReused(*stream2);
-
- data_->RunFor(1);
- EXPECT_LE(OK, callback_.WaitForResult());
- data_->RunFor(1);
- EXPECT_LE(OK, callback_.WaitForResult());
-
- EXPECT_EQ(ERR_IO_PENDING, stream1->ReadResponseHeaders(callback_.callback()));
- EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(callback_.callback()));
-
- data_->RunFor(2);
- EXPECT_LE(OK, callback_.WaitForResult());
-
- ExpectResponse("ok.html", stream1, true);
-
- TestLoadTimingNotReused(*stream1);
- LoadTimingInfo load_timing_info1;
- EXPECT_TRUE(stream1->GetLoadTimingInfo(&load_timing_info1));
- stream1->Close(false);
-
- data_->RunFor(2);
- EXPECT_LE(OK, callback_.WaitForResult());
-
- ExpectResponse("ko.html", stream2, true);
-
- TestLoadTimingReused(*stream2);
- LoadTimingInfo load_timing_info2;
- EXPECT_TRUE(stream2->GetLoadTimingInfo(&load_timing_info2));
- EXPECT_EQ(load_timing_info1.socket_log_id,
- load_timing_info2.socket_log_id);
- stream2->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, TwoResponsesInOnePacket) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /ko.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2,
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 7\r\n\r\n"
- "ok.html"
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 7\r\n\r\n"
- "ko.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream1(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> stream2(NewTestStream("ko.html"));
-
- HttpRequestHeaders headers1;
- HttpResponseInfo response1;
- EXPECT_EQ(OK, stream1->SendRequest(headers1,
- &response1, callback_.callback()));
- HttpRequestHeaders headers2;
- HttpResponseInfo response2;
- EXPECT_EQ(OK, stream2->SendRequest(headers2,
- &response2, callback_.callback()));
-
- EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback()));
- ExpectResponse("ok.html", stream1, false);
- stream1->Close(false);
-
- EXPECT_EQ(OK, stream2->ReadResponseHeaders(callback_.callback()));
- ExpectResponse("ko.html", stream2, false);
- stream2->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, SendOrderSwapped) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ko.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 4, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "ko.html"),
- MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 7, "ok.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream1(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> stream2(NewTestStream("ko.html"));
-
- TestSyncRequest(stream2, "ko.html");
- TestSyncRequest(stream1, "ok.html");
- TestLoadTimingNotReused(*stream1);
- TestLoadTimingReused(*stream2);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, ReadOrderSwapped) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /ko.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "ok.html"),
- MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 7, "ko.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream1(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> stream2(NewTestStream("ko.html"));
-
- HttpRequestHeaders headers1;
- HttpResponseInfo response1;
- EXPECT_EQ(OK, stream1->SendRequest(headers1,
- &response1, callback_.callback()));
-
- HttpRequestHeaders headers2;
- HttpResponseInfo response2;
- EXPECT_EQ(OK, stream2->SendRequest(headers2,
- &response2, callback_.callback()));
-
- EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(callback_.callback()));
-
- EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback()));
- ExpectResponse("ok.html", stream1, false);
-
- stream1->Close(false);
-
- EXPECT_LE(OK, callback_.WaitForResult());
- ExpectResponse("ko.html", stream2, false);
-
- stream2->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, SendWhileReading) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 3, "GET /ko.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "ok.html"),
- MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 7, "ko.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream1(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> stream2(NewTestStream("ko.html"));
-
- HttpRequestHeaders headers1;
- HttpResponseInfo response1;
- EXPECT_EQ(OK, stream1->SendRequest(headers1,
- &response1, callback_.callback()));
- EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback()));
-
- HttpRequestHeaders headers2;
- HttpResponseInfo response2;
- EXPECT_EQ(OK, stream2->SendRequest(headers2,
- &response2, callback_.callback()));
-
- ExpectResponse("ok.html", stream1, false);
- stream1->Close(false);
-
- EXPECT_EQ(OK, stream2->ReadResponseHeaders(callback_.callback()));
- ExpectResponse("ko.html", stream2, false);
- stream2->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, AsyncSendWhileAsyncReadBlocked) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(ASYNC, 3, "GET /ko.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"),
- MockRead(ASYNC, 4, "ok.html"),
- MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 7, "ko.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream1(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> stream2(NewTestStream("ko.html"));
-
- HttpRequestHeaders headers1;
- HttpResponseInfo response1;
- EXPECT_EQ(OK, stream1->SendRequest(headers1,
- &response1, callback_.callback()));
- EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback()));
- TestCompletionCallback callback1;
- std::string expected = "ok.html";
- scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size()));
- EXPECT_EQ(ERR_IO_PENDING,
- stream1->ReadResponseBody(buffer.get(), expected.size(),
- callback1.callback()));
-
- HttpRequestHeaders headers2;
- HttpResponseInfo response2;
- TestCompletionCallback callback2;
- EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(headers2, &response2,
- callback2.callback()));
-
- data_->RunFor(1);
- EXPECT_LE(OK, callback2.WaitForResult());
- EXPECT_EQ(ERR_IO_PENDING, stream2->ReadResponseHeaders(callback2.callback()));
-
- data_->RunFor(1);
- EXPECT_EQ(static_cast<int>(expected.size()), callback1.WaitForResult());
- std::string actual(buffer->data(), expected.size());
- EXPECT_THAT(actual, StrEq(expected));
- stream1->Close(false);
-
- data_->StopAfter(8);
- EXPECT_LE(OK, callback2.WaitForResult());
- ExpectResponse("ko.html", stream2, false);
- stream2->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, UnusedStreamAllowsLaterUse) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "ok.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> unused_stream(NewTestStream("unused.html"));
- unused_stream->Close(false);
-
- scoped_ptr<HttpStream> later_stream(NewTestStream("ok.html"));
- TestSyncRequest(later_stream, "ok.html");
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, UnsentStreamAllowsLaterUse) {
- MockWrite writes[] = {
- MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 4, "GET /ko.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"),
- MockRead(ASYNC, 3, "ok.html"),
- MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 6, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 7, "ko.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(headers, &response,
- callback_.callback()));
-
- scoped_ptr<HttpStream> unsent_stream(NewTestStream("unsent.html"));
- HttpRequestHeaders unsent_headers;
- HttpResponseInfo unsent_response;
- EXPECT_EQ(ERR_IO_PENDING, unsent_stream->SendRequest(unsent_headers,
- &unsent_response,
- callback_.callback()));
- unsent_stream->Close(false);
-
- data_->RunFor(1);
- EXPECT_LE(OK, callback_.WaitForResult());
-
- EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
- data_->RunFor(2);
- EXPECT_LE(OK, callback_.WaitForResult());
-
- ExpectResponse("ok.html", stream, true);
-
- stream->Close(false);
-
- data_->StopAfter(8);
- scoped_ptr<HttpStream> later_stream(NewTestStream("ko.html"));
- TestSyncRequest(later_stream, "ko.html");
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, FailedSend) {
- MockWrite writes[] = {
- MockWrite(ASYNC, ERR_FAILED),
- };
- Initialize(NULL, 0, writes, arraysize(writes));
-
- scoped_ptr<HttpStream> failed_stream(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html"));
- scoped_ptr<HttpStream> closed_stream(NewTestStream("closed.html"));
- scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- TestCompletionCallback failed_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- failed_stream->SendRequest(headers, &response,
- failed_callback.callback()));
- TestCompletionCallback evicted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- evicted_stream->SendRequest(headers, &response,
- evicted_callback.callback()));
- EXPECT_EQ(ERR_IO_PENDING, closed_stream->SendRequest(headers, &response,
- callback_.callback()));
- closed_stream->Close(false);
-
- data_->RunFor(1);
- EXPECT_EQ(ERR_FAILED, failed_callback.WaitForResult());
- EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult());
- EXPECT_EQ(ERR_PIPELINE_EVICTION,
- rejected_stream->SendRequest(headers, &response,
- callback_.callback()));
-
- failed_stream->Close(true);
- evicted_stream->Close(true);
- rejected_stream->Close(true);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, ConnectionSuddenlyClosedAfterResponse) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /read_evicted.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 2, "GET /read_rejected.html HTTP/1.1\r\n\r\n"),
- MockWrite(ASYNC, ERR_SOCKET_NOT_CONNECTED, 5),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "ok.html"),
- MockRead(ASYNC, OK, 6), // Connection closed message. Not read before the
- // ERR_SOCKET_NOT_CONNECTED.
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> closed_stream(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> read_evicted_stream(
- NewTestStream("read_evicted.html"));
- scoped_ptr<HttpStream> read_rejected_stream(
- NewTestStream("read_rejected.html"));
- scoped_ptr<HttpStream> send_closed_stream(
- NewTestStream("send_closed.html"));
- scoped_ptr<HttpStream> send_evicted_stream(
- NewTestStream("send_evicted.html"));
- scoped_ptr<HttpStream> send_rejected_stream(
- NewTestStream("send_rejected.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, closed_stream->SendRequest(headers,
- &response, callback_.callback()));
- EXPECT_EQ(OK, read_evicted_stream->SendRequest(headers, &response,
- callback_.callback()));
- EXPECT_EQ(OK, read_rejected_stream->SendRequest(headers, &response,
- callback_.callback()));
- TestCompletionCallback send_closed_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- send_closed_stream->SendRequest(headers, &response,
- send_closed_callback.callback()));
- TestCompletionCallback send_evicted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- send_evicted_stream->SendRequest(headers, &response,
- send_evicted_callback.callback()));
-
- TestCompletionCallback read_evicted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- read_evicted_stream->ReadResponseHeaders(
- read_evicted_callback.callback()));
-
- EXPECT_EQ(OK, closed_stream->ReadResponseHeaders(callback_.callback()));
- ExpectResponse("ok.html", closed_stream, false);
- closed_stream->Close(true);
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION, read_evicted_callback.WaitForResult());
- read_evicted_stream->Close(true);
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION,
- read_rejected_stream->ReadResponseHeaders(callback_.callback()));
- read_rejected_stream->Close(true);
-
- data_->RunFor(1);
- EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, send_closed_callback.WaitForResult());
- send_closed_stream->Close(true);
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION, send_evicted_callback.WaitForResult());
- send_evicted_stream->Close(true);
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION,
- send_rejected_stream->SendRequest(headers, &response,
- callback_.callback()));
- send_rejected_stream->Close(true);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, AbortWhileSending) {
- MockWrite writes[] = {
- MockWrite(ASYNC, 0, "GET /aborts.html HTTP/1.1\r\n\r\n"),
- };
- Initialize(NULL, 0, writes, arraysize(writes));
-
- scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html"));
- scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- TestCompletionCallback aborted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- aborted_stream->SendRequest(headers, &response,
- aborted_callback.callback()));
- TestCompletionCallback evicted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- evicted_stream->SendRequest(headers, &response,
- evicted_callback.callback()));
-
- aborted_stream->Close(true);
- EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult());
- evicted_stream->Close(true);
- EXPECT_FALSE(aborted_callback.have_result());
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, AbortWhileSendingSecondRequest) {
- MockWrite writes[] = {
- MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(ASYNC, 1, "GET /aborts.html HTTP/1.1\r\n\r\n"),
- };
- Initialize(NULL, 0, writes, arraysize(writes));
-
- scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html"));
- scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- TestCompletionCallback ok_callback;
- EXPECT_EQ(ERR_IO_PENDING, ok_stream->SendRequest(headers, &response,
- ok_callback.callback()));
- TestCompletionCallback aborted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- aborted_stream->SendRequest(headers, &response,
- aborted_callback.callback()));
- TestCompletionCallback evicted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- evicted_stream->SendRequest(headers, &response,
- evicted_callback.callback()));
-
- data_->RunFor(1);
- EXPECT_LE(OK, ok_callback.WaitForResult());
- base::MessageLoop::current()->RunUntilIdle();
- aborted_stream->Close(true);
- EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult());
- evicted_stream->Close(true);
- EXPECT_FALSE(aborted_callback.have_result());
- ok_stream->Close(true);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, AbortWhileReadingHeaders) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /aborts.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(ASYNC, ERR_FAILED, 2),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> aborted_stream(NewTestStream("aborts.html"));
- scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html"));
- scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK,
- aborted_stream->SendRequest(headers, &response,
- callback_.callback()));
- EXPECT_EQ(OK,
- evicted_stream->SendRequest(headers, &response,
- callback_.callback()));
-
- EXPECT_EQ(ERR_IO_PENDING,
- aborted_stream->ReadResponseHeaders(callback_.callback()));
- TestCompletionCallback evicted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- evicted_stream->ReadResponseHeaders(evicted_callback.callback()));
-
- aborted_stream->Close(true);
- EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult());
- evicted_stream->Close(true);
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION,
- rejected_stream->SendRequest(headers, &response,
- callback_.callback()));
- rejected_stream->Close(true);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, PendingResponseAbandoned) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /abandoned.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 2, "GET /evicted.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 4, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 5, "ok.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> abandoned_stream(NewTestStream("abandoned.html"));
- scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, ok_stream->SendRequest(headers, &response,
- callback_.callback()));
- EXPECT_EQ(OK, abandoned_stream->SendRequest(headers, &response,
- callback_.callback()));
- EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response,
- callback_.callback()));
-
- EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback()));
- TestCompletionCallback abandoned_callback;
- EXPECT_EQ(ERR_IO_PENDING, abandoned_stream->ReadResponseHeaders(
- abandoned_callback.callback()));
- TestCompletionCallback evicted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- evicted_stream->ReadResponseHeaders(evicted_callback.callback()));
-
- abandoned_stream->Close(false);
-
- ExpectResponse("ok.html", ok_stream, false);
- ok_stream->Close(false);
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult());
- evicted_stream->Close(true);
- EXPECT_FALSE(evicted_stream->IsConnectionReusable());
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, DisconnectedAfterOneRequestRecovery) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /rejected.html HTTP/1.1\r\n\r\n"),
- MockWrite(ASYNC, ERR_SOCKET_NOT_CONNECTED, 5),
- MockWrite(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 7),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "ok.html"),
- MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 6),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> rejected_read_stream(NewTestStream("rejected.html"));
- scoped_ptr<HttpStream> evicted_send_stream(NewTestStream("evicted.html"));
- scoped_ptr<HttpStream> rejected_send_stream(NewTestStream("rejected.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, ok_stream->SendRequest(headers,
- &response, callback_.callback()));
- EXPECT_EQ(OK, rejected_read_stream->SendRequest(headers, &response,
- callback_.callback()));
-
- EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback()));
- ExpectResponse("ok.html", ok_stream, false);
- ok_stream->Close(false);
-
- TestCompletionCallback read_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- evicted_send_stream->SendRequest(headers, &response,
- read_callback.callback()));
- data_->RunFor(1);
- EXPECT_EQ(ERR_PIPELINE_EVICTION, read_callback.WaitForResult());
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION,
- rejected_read_stream->ReadResponseHeaders(callback_.callback()));
- EXPECT_EQ(ERR_PIPELINE_EVICTION,
- rejected_send_stream->SendRequest(headers, &response,
- callback_.callback()));
-
- rejected_read_stream->Close(true);
- rejected_send_stream->Close(true);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, DisconnectedPendingReadRecovery) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "ok.html"),
- MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, ok_stream->SendRequest(headers,
- &response, callback_.callback()));
- EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response,
- callback_.callback()));
-
- EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback()));
- ExpectResponse("ok.html", ok_stream, false);
-
- TestCompletionCallback evicted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- evicted_stream->ReadResponseHeaders(evicted_callback.callback()));
-
- ok_stream->Close(false);
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult());
- evicted_stream->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, CloseCalledBeforeNextReadLoop) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "ok.html"),
- MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, ok_stream->SendRequest(headers,
- &response, callback_.callback()));
- EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response,
- callback_.callback()));
-
- EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback()));
- ExpectResponse("ok.html", ok_stream, false);
-
- TestCompletionCallback evicted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- evicted_stream->ReadResponseHeaders(evicted_callback.callback()));
-
- ok_stream->Close(false);
- evicted_stream->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, CloseCalledBeforeReadCallback) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "ok.html"),
- MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, ok_stream->SendRequest(headers,
- &response, callback_.callback()));
- EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response,
- callback_.callback()));
-
- EXPECT_EQ(OK, ok_stream->ReadResponseHeaders(callback_.callback()));
- ExpectResponse("ok.html", ok_stream, false);
-
- TestCompletionCallback evicted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- evicted_stream->ReadResponseHeaders(evicted_callback.callback()));
-
- ok_stream->Close(false);
-
- // The posted tasks should be:
- // 1. DoReadHeadersLoop, which will post:
- // 2. InvokeUserCallback
- SuddenCloseObserver observer(evicted_stream.get(), 2);
- base::MessageLoop::current()->AddTaskObserver(&observer);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_FALSE(evicted_callback.have_result());
-}
-
-class StreamDeleter {
- public:
- StreamDeleter(HttpStream* stream)
- : stream_(stream),
- callback_(base::Bind(&StreamDeleter::OnIOComplete,
- base::Unretained(this))) {
- }
-
- ~StreamDeleter() {
- EXPECT_FALSE(stream_);
- }
-
- const CompletionCallback& callback() { return callback_; }
-
- private:
- void OnIOComplete(int result) {
- stream_->Close(true);
- stream_.reset();
- }
-
- scoped_ptr<HttpStream> stream_;
- CompletionCallback callback_;
-};
-
-TEST_F(HttpPipelinedConnectionImplTest, CloseCalledDuringSendCallback) {
- MockWrite writes[] = {
- MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- Initialize(NULL, 0, writes, arraysize(writes));
-
- HttpStream* stream(NewTestStream("ok.html"));
-
- StreamDeleter deleter(stream);
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(headers, &response,
- deleter.callback()));
- data_->RunFor(1);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, CloseCalledDuringReadCallback) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- HttpStream* stream(NewTestStream("ok.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, stream->SendRequest(headers,
- &response, callback_.callback()));
-
- StreamDeleter deleter(stream);
- EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(deleter.callback()));
- data_->RunFor(1);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest,
- CloseCalledDuringReadCallbackWithPendingRead) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /failed.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- HttpStream* failed_stream(NewTestStream("failed.html"));
- HttpStream* evicted_stream(NewTestStream("evicted.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, failed_stream->SendRequest(headers, &response,
- callback_.callback()));
- EXPECT_EQ(OK, evicted_stream->SendRequest(headers, &response,
- callback_.callback()));
-
- StreamDeleter failed_deleter(failed_stream);
- EXPECT_EQ(ERR_IO_PENDING,
- failed_stream->ReadResponseHeaders(failed_deleter.callback()));
- StreamDeleter evicted_deleter(evicted_stream);
- EXPECT_EQ(ERR_IO_PENDING,
- evicted_stream->ReadResponseHeaders(evicted_deleter.callback()));
- data_->RunFor(1);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, CloseOtherDuringReadCallback) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /deleter.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /deleted.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> deleter_stream(NewTestStream("deleter.html"));
- HttpStream* deleted_stream(NewTestStream("deleted.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, deleter_stream->SendRequest(headers,
- &response, callback_.callback()));
- EXPECT_EQ(OK, deleted_stream->SendRequest(headers,
- &response, callback_.callback()));
-
- StreamDeleter deleter(deleted_stream);
- EXPECT_EQ(ERR_IO_PENDING,
- deleter_stream->ReadResponseHeaders(deleter.callback()));
- EXPECT_EQ(ERR_IO_PENDING,
- deleted_stream->ReadResponseHeaders(callback_.callback()));
- data_->RunFor(1);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, CloseBeforeSendCallbackRuns) {
- MockWrite writes[] = {
- MockWrite(ASYNC, 0, "GET /close.html HTTP/1.1\r\n\r\n"),
- MockWrite(ASYNC, 1, "GET /dummy.html HTTP/1.1\r\n\r\n"),
- };
- Initialize(NULL, 0, writes, arraysize(writes));
-
- scoped_ptr<HttpStream> close_stream(NewTestStream("close.html"));
- scoped_ptr<HttpStream> dummy_stream(NewTestStream("dummy.html"));
-
- scoped_ptr<TestCompletionCallback> close_callback(
- new TestCompletionCallback);
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(ERR_IO_PENDING,
- close_stream->SendRequest(headers,
- &response, close_callback->callback()));
-
- data_->RunFor(1);
- EXPECT_FALSE(close_callback->have_result());
-
- close_stream->Close(false);
- close_stream.reset();
- close_callback.reset();
-
- base::MessageLoop::current()->RunUntilIdle();
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, CloseBeforeReadCallbackRuns) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /close.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 3, "GET /dummy.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 2, "Content-Length: 7\r\n\r\n"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> close_stream(NewTestStream("close.html"));
- scoped_ptr<HttpStream> dummy_stream(NewTestStream("dummy.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, close_stream->SendRequest(headers,
- &response, callback_.callback()));
-
- scoped_ptr<TestCompletionCallback> close_callback(
- new TestCompletionCallback);
- EXPECT_EQ(ERR_IO_PENDING,
- close_stream->ReadResponseHeaders(close_callback->callback()));
-
- data_->RunFor(1);
- EXPECT_FALSE(close_callback->have_result());
-
- close_stream->Close(false);
- close_stream.reset();
- close_callback.reset();
-
- base::MessageLoop::current()->RunUntilIdle();
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, AbortWhileSendQueued) {
- MockWrite writes[] = {
- MockWrite(ASYNC, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(ASYNC, 1, "GET /ko.html HTTP/1.1\r\n\r\n"),
- };
- Initialize(NULL, 0, writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream1(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> stream2(NewTestStream("ko.html"));
-
- HttpRequestHeaders headers1;
- HttpResponseInfo response1;
- TestCompletionCallback callback1;
- EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(headers1, &response1,
- callback1.callback()));
-
- HttpRequestHeaders headers2;
- HttpResponseInfo response2;
- TestCompletionCallback callback2;
- EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(headers2, &response2,
- callback2.callback()));
-
- stream2.reset();
- stream1->Close(true);
-
- EXPECT_FALSE(callback2.have_result());
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, NoGapBetweenCloseAndEviction) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /close.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 2, "GET /dummy.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 3, "Content-Length: 7\r\n\r\n"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> close_stream(NewTestStream("close.html"));
- scoped_ptr<HttpStream> dummy_stream(NewTestStream("dummy.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, close_stream->SendRequest(headers, &response,
- callback_.callback()));
-
- TestCompletionCallback close_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- close_stream->ReadResponseHeaders(close_callback.callback()));
-
- EXPECT_EQ(OK, dummy_stream->SendRequest(headers, &response,
- callback_.callback()));
-
- TestCompletionCallback dummy_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- dummy_stream->ReadResponseHeaders(dummy_callback.callback()));
-
- close_stream->Close(true);
- close_stream.reset();
-
- EXPECT_TRUE(dummy_callback.have_result());
- EXPECT_EQ(ERR_PIPELINE_EVICTION, dummy_callback.WaitForResult());
- dummy_stream->Close(true);
- dummy_stream.reset();
- pipeline_.reset();
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, RecoverFromDrainOnRedirect) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2,
- "HTTP/1.1 302 OK\r\n"
- "Content-Length: 8\r\n\r\n"
- "redirect"),
- MockRead(SYNCHRONOUS, 3,
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 7\r\n\r\n"
- "ok.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html"));
- scoped_ptr<HttpStream> stream2(NewTestStream("ok.html"));
-
- HttpRequestHeaders headers1;
- HttpResponseInfo response1;
- EXPECT_EQ(OK, stream1->SendRequest(headers1,
- &response1, callback_.callback()));
- HttpRequestHeaders headers2;
- HttpResponseInfo response2;
- EXPECT_EQ(OK, stream2->SendRequest(headers2,
- &response2, callback_.callback()));
-
- EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback()));
- stream1.release()->Drain(NULL);
-
- EXPECT_EQ(OK, stream2->ReadResponseHeaders(callback_.callback()));
- ExpectResponse("ok.html", stream2, false);
- stream2->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, EvictAfterDrainOfUnknownSize) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2,
- "HTTP/1.1 302 OK\r\n\r\n"
- "redirect"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html"));
- scoped_ptr<HttpStream> stream2(NewTestStream("ok.html"));
-
- HttpRequestHeaders headers1;
- HttpResponseInfo response1;
- EXPECT_EQ(OK, stream1->SendRequest(headers1,
- &response1, callback_.callback()));
- HttpRequestHeaders headers2;
- HttpResponseInfo response2;
- EXPECT_EQ(OK, stream2->SendRequest(headers2,
- &response2, callback_.callback()));
-
- EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback()));
- stream1.release()->Drain(NULL);
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION,
- stream2->ReadResponseHeaders(callback_.callback()));
- stream2->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, EvictAfterFailedDrain) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2,
- "HTTP/1.1 302 OK\r\n"
- "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 3),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html"));
- scoped_ptr<HttpStream> stream2(NewTestStream("ok.html"));
-
- HttpRequestHeaders headers1;
- HttpResponseInfo response1;
- EXPECT_EQ(OK, stream1->SendRequest(headers1,
- &response1, callback_.callback()));
- HttpRequestHeaders headers2;
- HttpResponseInfo response2;
- EXPECT_EQ(OK, stream2->SendRequest(headers2,
- &response2, callback_.callback()));
-
-
- EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback()));
- stream1.release()->Drain(NULL);
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION,
- stream2->ReadResponseHeaders(callback_.callback()));
- stream2->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, EvictIfDrainingChunkedEncoding) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 2,
- "HTTP/1.1 302 OK\r\n"
- "Transfer-Encoding: chunked\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3,
- "jibberish"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> stream1(NewTestStream("redirect.html"));
- scoped_ptr<HttpStream> stream2(NewTestStream("ok.html"));
-
- HttpRequestHeaders headers1;
- HttpResponseInfo response1;
- EXPECT_EQ(OK, stream1->SendRequest(headers1,
- &response1, callback_.callback()));
- HttpRequestHeaders headers2;
- HttpResponseInfo response2;
- EXPECT_EQ(OK, stream2->SendRequest(headers2,
- &response2, callback_.callback()));
-
-
- EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback()));
- stream1.release()->Drain(NULL);
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION,
- stream2->ReadResponseHeaders(callback_.callback()));
- stream2->Close(false);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, EvictionDueToMissingContentLength) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 1, "GET /evicted.html HTTP/1.1\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 2, "GET /rejected.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "ok.html"),
- MockRead(SYNCHRONOUS, OK, 5),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpStream> ok_stream(NewTestStream("ok.html"));
- scoped_ptr<HttpStream> evicted_stream(NewTestStream("evicted.html"));
- scoped_ptr<HttpStream> rejected_stream(NewTestStream("rejected.html"));
-
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, ok_stream->SendRequest(headers,
- &response, callback_.callback()));
- EXPECT_EQ(OK, evicted_stream->SendRequest(headers,
- &response, callback_.callback()));
- EXPECT_EQ(OK, rejected_stream->SendRequest(headers,
- &response, callback_.callback()));
-
- TestCompletionCallback ok_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- ok_stream->ReadResponseHeaders(ok_callback.callback()));
-
- TestCompletionCallback evicted_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- evicted_stream->ReadResponseHeaders(evicted_callback.callback()));
-
- data_->RunFor(1);
- EXPECT_LE(OK, ok_callback.WaitForResult());
- data_->StopAfter(10);
-
- ExpectResponse("ok.html", ok_stream, false);
- ok_stream->Close(false);
-
- EXPECT_EQ(ERR_PIPELINE_EVICTION,
- rejected_stream->ReadResponseHeaders(callback_.callback()));
- rejected_stream->Close(true);
- EXPECT_EQ(ERR_PIPELINE_EVICTION, evicted_callback.WaitForResult());
- evicted_stream->Close(true);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnSocketError) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, ERR_FAILED, 1),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- EXPECT_CALL(delegate_,
- OnPipelineFeedback(
- pipeline_.get(),
- HttpPipelinedConnection::PIPELINE_SOCKET_ERROR))
- .Times(1);
-
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, stream->SendRequest(headers,
- &response, callback_.callback()));
- EXPECT_EQ(ERR_FAILED, stream->ReadResponseHeaders(callback_.callback()));
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnNoInternetConnection) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, ERR_INTERNET_DISCONNECTED, 1),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- EXPECT_CALL(delegate_, OnPipelineFeedback(_, _))
- .Times(0);
-
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, stream->SendRequest(headers,
- &response, callback_.callback()));
- EXPECT_EQ(ERR_INTERNET_DISCONNECTED,
- stream->ReadResponseHeaders(callback_.callback()));
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnHttp10) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.0 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n"),
- MockRead(SYNCHRONOUS, 3, "Connection: keep-alive\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "ok.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- EXPECT_CALL(delegate_,
- OnPipelineFeedback(pipeline_.get(),
- HttpPipelinedConnection::OLD_HTTP_VERSION))
- .Times(1);
-
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
- TestSyncRequest(stream, "ok.html");
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnMustClose) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 7\r\n"),
- MockRead(SYNCHRONOUS, 3, "Connection: close\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "ok.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- EXPECT_CALL(delegate_,
- OnPipelineFeedback(
- pipeline_.get(),
- HttpPipelinedConnection::MUST_CLOSE_CONNECTION))
- .Times(1);
-
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
- TestSyncRequest(stream, "ok.html");
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnNoContentLength) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"),
- MockRead(SYNCHRONOUS, 2, "ok.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- EXPECT_CALL(delegate_,
- OnPipelineFeedback(
- pipeline_.get(),
- HttpPipelinedConnection::MUST_CLOSE_CONNECTION))
- .Times(1);
-
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
- TestSyncRequest(stream, "ok.html");
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, FeedbackOnAuthenticationRequired) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 401 Unauthorized\r\n"),
- MockRead(SYNCHRONOUS, 2, "WWW-Authenticate: NTLM\r\n"),
- MockRead(SYNCHRONOUS, 3, "Content-Length: 7\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "ok.html"),
- };
- Initialize(reads, arraysize(reads), writes, arraysize(writes));
-
- EXPECT_CALL(delegate_,
- OnPipelineFeedback(
- pipeline_.get(),
- HttpPipelinedConnection::AUTHENTICATION_REQUIRED))
- .Times(1);
-
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
- TestSyncRequest(stream, "ok.html");
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, OnPipelineHasCapacity) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- Initialize(NULL, 0, writes, arraysize(writes));
-
- EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0);
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
-
- EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1);
- HttpRequestHeaders headers;
- HttpResponseInfo response;
- EXPECT_EQ(OK, stream->SendRequest(headers,
- &response, callback_.callback()));
-
- EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0);
- base::MessageLoop::current()->RunUntilIdle();
-
- stream->Close(false);
- EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1);
- stream.reset(NULL);
-}
-
-TEST_F(HttpPipelinedConnectionImplTest, OnPipelineHasCapacityWithoutSend) {
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /ok.html HTTP/1.1\r\n\r\n"),
- };
- Initialize(NULL, 0, writes, arraysize(writes));
-
- EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(0);
- scoped_ptr<HttpStream> stream(NewTestStream("ok.html"));
-
- EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1);
- base::MessageLoop::current()->RunUntilIdle();
-
- stream->Close(false);
- EXPECT_CALL(delegate_, OnPipelineHasCapacity(pipeline_.get())).Times(1);
- stream.reset(NULL);
-}
-
-} // anonymous namespace
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_host.cc b/chromium/net/http/http_pipelined_host.cc
deleted file mode 100644
index ca477808e9b..00000000000
--- a/chromium/net/http/http_pipelined_host.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_host.h"
-
-namespace net {
-
-HttpPipelinedHost::Key::Key(const HostPortPair& origin)
- : origin_(origin) {
-}
-
-bool HttpPipelinedHost::Key::operator<(const Key& rhs) const {
- return origin_ < rhs.origin_;
-}
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_host.h b/chromium/net/http/http_pipelined_host.h
deleted file mode 100644
index b7732e60a8b..00000000000
--- a/chromium/net/http/http_pipelined_host.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2012 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_HTTP_HTTP_PIPELINED_HOST_H_
-#define NET_HTTP_HTTP_PIPELINED_HOST_H_
-
-#include "net/base/host_port_pair.h"
-#include "net/base/net_export.h"
-#include "net/http/http_pipelined_connection.h"
-#include "net/http/http_pipelined_host_capability.h"
-
-namespace base {
-class Value;
-}
-
-namespace net {
-
-class BoundNetLog;
-class ClientSocketHandle;
-class HostPortPair;
-class HttpPipelinedStream;
-class ProxyInfo;
-struct SSLConfig;
-
-// Manages all of the pipelining state for specific host with active pipelined
-// HTTP requests. Manages connection jobs, constructs pipelined streams, and
-// assigns requests to the least loaded pipelined connection.
-class NET_EXPORT_PRIVATE HttpPipelinedHost {
- public:
- class NET_EXPORT_PRIVATE Key {
- public:
- Key(const HostPortPair& origin);
-
- // The host and port associated with this key.
- const HostPortPair& origin() const { return origin_; }
-
- bool operator<(const Key& rhs) const;
-
- private:
- const HostPortPair origin_;
- };
-
- class Delegate {
- public:
- // Called when a pipelined host has no outstanding requests on any of its
- // pipelined connections.
- virtual void OnHostIdle(HttpPipelinedHost* host) = 0;
-
- // Called when a pipelined host has newly available pipeline capacity, like
- // when a request completes.
- virtual void OnHostHasAdditionalCapacity(HttpPipelinedHost* host) = 0;
-
- // Called when a host determines if pipelining can be used.
- virtual void OnHostDeterminedCapability(
- HttpPipelinedHost* host,
- HttpPipelinedHostCapability capability) = 0;
- };
-
- class Factory {
- public:
- virtual ~Factory() {}
-
- // Returns a new HttpPipelinedHost.
- virtual HttpPipelinedHost* CreateNewHost(
- Delegate* delegate, const Key& key,
- HttpPipelinedConnection::Factory* factory,
- HttpPipelinedHostCapability capability,
- bool force_pipelining) = 0;
- };
-
- virtual ~HttpPipelinedHost() {}
-
- // Constructs a new pipeline on |connection| and returns a new
- // HttpPipelinedStream that uses it.
- virtual HttpPipelinedStream* CreateStreamOnNewPipeline(
- ClientSocketHandle* connection,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated) = 0;
-
- // Tries to find an existing pipeline with capacity for a new request. If
- // successful, returns a new stream on that pipeline. Otherwise, returns NULL.
- virtual HttpPipelinedStream* CreateStreamOnExistingPipeline() = 0;
-
- // Returns true if we have a pipelined connection that can accept new
- // requests.
- virtual bool IsExistingPipelineAvailable() const = 0;
-
- // Returns a Key that uniquely identifies this host.
- virtual const Key& GetKey() const = 0;
-
- // Creates a Value summary of this host's pipelines. Caller assumes
- // ownership of the returned Value.
- virtual base::Value* PipelineInfoToValue() const = 0;
-};
-
-} // namespace net
-
-#endif // NET_HTTP_HTTP_PIPELINED_HOST_H_
diff --git a/chromium/net/http/http_pipelined_host_capability.h b/chromium/net/http/http_pipelined_host_capability.h
deleted file mode 100644
index d03a20893ea..00000000000
--- a/chromium/net/http/http_pipelined_host_capability.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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_HTTP_HTTP_PIPELINED_HOST_CAPABILITY_H_
-#define NET_HTTP_HTTP_PIPELINED_HOST_CAPABILITY_H_
-
-namespace net {
-
-// These values are serialized in Preferences. Do not change these values and
-// only add new ones at the end.
-enum HttpPipelinedHostCapability {
- PIPELINE_UNKNOWN = 0,
- PIPELINE_INCAPABLE = 1,
- PIPELINE_CAPABLE = 2,
- PIPELINE_PROBABLY_CAPABLE = 3, // We are using pipelining, but haven't
- // processed enough requests to record this
- // host as known to be capable.
-};
-
-} // namespace net
-
-#endif // NET_HTTP_HTTP_PIPELINED_HOST_CAPABILITY_H_
diff --git a/chromium/net/http/http_pipelined_host_forced.cc b/chromium/net/http/http_pipelined_host_forced.cc
deleted file mode 100644
index 8059d848d73..00000000000
--- a/chromium/net/http/http_pipelined_host_forced.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_host_forced.h"
-
-#include "base/values.h"
-#include "net/http/http_pipelined_connection_impl.h"
-#include "net/http/http_pipelined_stream.h"
-#include "net/socket/buffered_write_stream_socket.h"
-#include "net/socket/client_socket_handle.h"
-
-namespace net {
-
-HttpPipelinedHostForced::HttpPipelinedHostForced(
- HttpPipelinedHost::Delegate* delegate,
- const Key& key,
- HttpPipelinedConnection::Factory* factory)
- : delegate_(delegate),
- key_(key),
- factory_(factory) {
- if (!factory) {
- factory_.reset(new HttpPipelinedConnectionImpl::Factory());
- }
-}
-
-HttpPipelinedHostForced::~HttpPipelinedHostForced() {
- CHECK(!pipeline_.get());
-}
-
-HttpPipelinedStream* HttpPipelinedHostForced::CreateStreamOnNewPipeline(
- ClientSocketHandle* connection,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated) {
- CHECK(!pipeline_.get());
- scoped_ptr<BufferedWriteStreamSocket> buffered_socket(
- new BufferedWriteStreamSocket(connection->PassSocket()));
- connection->SetSocket(buffered_socket.PassAs<StreamSocket>());
- pipeline_.reset(factory_->CreateNewPipeline(
- connection, this, key_.origin(), used_ssl_config, used_proxy_info,
- net_log, was_npn_negotiated, protocol_negotiated));
- return pipeline_->CreateNewStream();
-}
-
-HttpPipelinedStream* HttpPipelinedHostForced::CreateStreamOnExistingPipeline() {
- if (!pipeline_.get()) {
- return NULL;
- }
- return pipeline_->CreateNewStream();
-}
-
-bool HttpPipelinedHostForced::IsExistingPipelineAvailable() const {
- return pipeline_.get() != NULL;
-}
-
-const HttpPipelinedHost::Key& HttpPipelinedHostForced::GetKey() const {
- return key_;
-}
-
-void HttpPipelinedHostForced::OnPipelineEmpty(
- HttpPipelinedConnection* pipeline) {
- CHECK_EQ(pipeline_.get(), pipeline);
- pipeline_.reset();
- delegate_->OnHostIdle(this);
- // WARNING: We'll probably be deleted here.
-}
-
-void HttpPipelinedHostForced::OnPipelineHasCapacity(
- HttpPipelinedConnection* pipeline) {
- CHECK_EQ(pipeline_.get(), pipeline);
- delegate_->OnHostHasAdditionalCapacity(this);
- if (!pipeline->depth()) {
- OnPipelineEmpty(pipeline);
- // WARNING: We might be deleted here.
- }
-}
-
-void HttpPipelinedHostForced::OnPipelineFeedback(
- HttpPipelinedConnection* pipeline,
- HttpPipelinedConnection::Feedback feedback) {
- // We don't care. We always pipeline.
-}
-
-base::Value* HttpPipelinedHostForced::PipelineInfoToValue() const {
- base::ListValue* list_value = new base::ListValue();
- if (pipeline_.get()) {
- base::DictionaryValue* pipeline_dict = new base::DictionaryValue;
- pipeline_dict->SetString("host", key_.origin().ToString());
- pipeline_dict->SetBoolean("forced", true);
- pipeline_dict->SetInteger("depth", pipeline_->depth());
- pipeline_dict->SetInteger("capacity", 1000);
- pipeline_dict->SetBoolean("usable", pipeline_->usable());
- pipeline_dict->SetBoolean("active", pipeline_->active());
- pipeline_dict->SetInteger("source_id", pipeline_->net_log().source().id);
- list_value->Append(pipeline_dict);
- }
- return list_value;
-}
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_host_forced.h b/chromium/net/http/http_pipelined_host_forced.h
deleted file mode 100644
index 2c3c9159342..00000000000
--- a/chromium/net/http/http_pipelined_host_forced.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2012 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_HTTP_HTTP_PIPELINED_HOST_FORCED_H_
-#define NET_HTTP_HTTP_PIPELINED_HOST_FORCED_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/base/host_port_pair.h"
-#include "net/base/net_export.h"
-#include "net/http/http_pipelined_connection.h"
-#include "net/http/http_pipelined_host.h"
-#include "net/http/http_pipelined_host_capability.h"
-
-namespace base {
-class Value;
-}
-
-namespace net {
-
-class BoundNetLog;
-class ClientSocketHandle;
-class HttpPipelinedStream;
-class ProxyInfo;
-struct SSLConfig;
-
-// Manages a single pipelined connection for requests to a host that are forced
-// to use pipelining. Note that this is normally not used. It is intended to
-// test the user's connection for pipelining compatibility.
-class NET_EXPORT_PRIVATE HttpPipelinedHostForced
- : public HttpPipelinedHost,
- public HttpPipelinedConnection::Delegate {
- public:
- HttpPipelinedHostForced(HttpPipelinedHost::Delegate* delegate,
- const Key& key,
- HttpPipelinedConnection::Factory* factory);
- virtual ~HttpPipelinedHostForced();
-
- // HttpPipelinedHost interface
- virtual HttpPipelinedStream* CreateStreamOnNewPipeline(
- ClientSocketHandle* connection,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated) OVERRIDE;
-
- virtual HttpPipelinedStream* CreateStreamOnExistingPipeline() OVERRIDE;
-
- virtual bool IsExistingPipelineAvailable() const OVERRIDE;
-
- virtual const Key& GetKey() const OVERRIDE;
-
- virtual base::Value* PipelineInfoToValue() const OVERRIDE;
-
- // HttpPipelinedConnection::Delegate interface
-
- virtual void OnPipelineHasCapacity(
- HttpPipelinedConnection* pipeline) OVERRIDE;
-
- virtual void OnPipelineFeedback(
- HttpPipelinedConnection* pipeline,
- HttpPipelinedConnection::Feedback feedback) OVERRIDE;
-
- private:
- // Called when a pipeline is empty and there are no pending requests. Closes
- // the connection.
- void OnPipelineEmpty(HttpPipelinedConnection* pipeline);
-
- HttpPipelinedHost::Delegate* delegate_;
- const Key key_;
- scoped_ptr<HttpPipelinedConnection> pipeline_;
- scoped_ptr<HttpPipelinedConnection::Factory> factory_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpPipelinedHostForced);
-};
-
-} // namespace net
-
-#endif // NET_HTTP_HTTP_PIPELINED_HOST_FORCED_H_
diff --git a/chromium/net/http/http_pipelined_host_forced_unittest.cc b/chromium/net/http/http_pipelined_host_forced_unittest.cc
deleted file mode 100644
index b86dd96d50a..00000000000
--- a/chromium/net/http/http_pipelined_host_forced_unittest.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_host_forced.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "net/http/http_pipelined_host_test_util.h"
-#include "net/proxy/proxy_info.h"
-#include "net/socket/client_socket_handle.h"
-#include "net/ssl/ssl_config_service.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::NiceMock;
-using testing::Ref;
-using testing::Return;
-
-namespace net {
-
-namespace {
-
-HttpPipelinedStream* kDummyStream =
- reinterpret_cast<HttpPipelinedStream*>(24);
-
-class HttpPipelinedHostForcedTest : public testing::Test {
- public:
- HttpPipelinedHostForcedTest()
- : key_(HostPortPair("host", 123)),
- factory_(new MockPipelineFactory), // Owned by |host_|.
- host_(new HttpPipelinedHostForced(&delegate_, key_, factory_)) {
- }
-
- MockPipeline* AddTestPipeline() {
- MockPipeline* pipeline = new MockPipeline(0, true, true);
- EXPECT_CALL(*factory_, CreateNewPipeline(&connection_, host_.get(),
- MatchesOrigin(key_.origin()),
- Ref(ssl_config_), Ref(proxy_info_),
- Ref(net_log_), true,
- kProtoSPDY3))
- .Times(1)
- .WillOnce(Return(pipeline));
- EXPECT_CALL(*pipeline, CreateNewStream())
- .Times(1)
- .WillOnce(Return(kDummyStream));
- EXPECT_EQ(kDummyStream, host_->CreateStreamOnNewPipeline(
- &connection_, ssl_config_, proxy_info_, net_log_, true,
- kProtoSPDY3));
- return pipeline;
- }
-
- ClientSocketHandle connection_;
- NiceMock<MockHostDelegate> delegate_;
- HttpPipelinedHost::Key key_;
- MockPipelineFactory* factory_;
- scoped_ptr<HttpPipelinedHostForced> host_;
-
- SSLConfig ssl_config_;
- ProxyInfo proxy_info_;
- BoundNetLog net_log_;
-};
-
-TEST_F(HttpPipelinedHostForcedTest, Delegate) {
- EXPECT_TRUE(key_.origin().Equals(host_->GetKey().origin()));
-}
-
-TEST_F(HttpPipelinedHostForcedTest, SingleUser) {
- EXPECT_FALSE(host_->IsExistingPipelineAvailable());
-
- MockPipeline* pipeline = AddTestPipeline();
- EXPECT_TRUE(host_->IsExistingPipelineAvailable());
-
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- EXPECT_CALL(delegate_, OnHostIdle(host_.get()))
- .Times(1);
- host_->OnPipelineHasCapacity(pipeline);
-}
-
-TEST_F(HttpPipelinedHostForcedTest, ReuseExisting) {
- EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
-
- MockPipeline* pipeline = AddTestPipeline();
- EXPECT_CALL(*pipeline, CreateNewStream())
- .Times(1)
- .WillOnce(Return(kDummyStream));
- EXPECT_EQ(kDummyStream, host_->CreateStreamOnExistingPipeline());
-
- pipeline->SetState(1, true, true);
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- EXPECT_CALL(delegate_, OnHostIdle(host_.get()))
- .Times(0);
- host_->OnPipelineHasCapacity(pipeline);
-
- pipeline->SetState(0, true, true);
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- EXPECT_CALL(delegate_, OnHostIdle(host_.get()))
- .Times(1);
- host_->OnPipelineHasCapacity(pipeline);
-}
-
-} // anonymous namespace
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_host_impl.cc b/chromium/net/http/http_pipelined_host_impl.cc
deleted file mode 100644
index 2a41ca41a85..00000000000
--- a/chromium/net/http/http_pipelined_host_impl.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_host_impl.h"
-
-#include "base/stl_util.h"
-#include "base/values.h"
-#include "net/http/http_pipelined_connection_impl.h"
-#include "net/http/http_pipelined_stream.h"
-
-namespace net {
-
-// TODO(simonjam): Run experiments to see what value minimizes evictions without
-// costing too much performance. Until then, this is just a bad guess.
-static const int kNumKnownSuccessesThreshold = 3;
-
-HttpPipelinedHostImpl::HttpPipelinedHostImpl(
- HttpPipelinedHost::Delegate* delegate,
- const HttpPipelinedHost::Key& key,
- HttpPipelinedConnection::Factory* factory,
- HttpPipelinedHostCapability capability)
- : delegate_(delegate),
- key_(key),
- factory_(factory),
- capability_(capability) {
- if (!factory) {
- factory_.reset(new HttpPipelinedConnectionImpl::Factory());
- }
-}
-
-HttpPipelinedHostImpl::~HttpPipelinedHostImpl() {
- CHECK(pipelines_.empty());
-}
-
-HttpPipelinedStream* HttpPipelinedHostImpl::CreateStreamOnNewPipeline(
- ClientSocketHandle* connection,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated) {
- if (capability_ == PIPELINE_INCAPABLE) {
- return NULL;
- }
- HttpPipelinedConnection* pipeline = factory_->CreateNewPipeline(
- connection, this, key_.origin(), used_ssl_config, used_proxy_info,
- net_log, was_npn_negotiated, protocol_negotiated);
- PipelineInfo info;
- pipelines_.insert(std::make_pair(pipeline, info));
- return pipeline->CreateNewStream();
-}
-
-HttpPipelinedStream* HttpPipelinedHostImpl::CreateStreamOnExistingPipeline() {
- HttpPipelinedConnection* available_pipeline = NULL;
- for (PipelineInfoMap::iterator it = pipelines_.begin();
- it != pipelines_.end(); ++it) {
- if (CanPipelineAcceptRequests(it->first) &&
- (!available_pipeline ||
- it->first->depth() < available_pipeline->depth())) {
- available_pipeline = it->first;
- }
- }
- if (!available_pipeline) {
- return NULL;
- }
- return available_pipeline->CreateNewStream();
-}
-
-bool HttpPipelinedHostImpl::IsExistingPipelineAvailable() const {
- for (PipelineInfoMap::const_iterator it = pipelines_.begin();
- it != pipelines_.end(); ++it) {
- if (CanPipelineAcceptRequests(it->first)) {
- return true;
- }
- }
- return false;
-}
-
-const HttpPipelinedHost::Key& HttpPipelinedHostImpl::GetKey() const {
- return key_;
-}
-
-void HttpPipelinedHostImpl::OnPipelineEmpty(HttpPipelinedConnection* pipeline) {
- CHECK(ContainsKey(pipelines_, pipeline));
- pipelines_.erase(pipeline);
- delete pipeline;
- if (pipelines_.empty()) {
- delegate_->OnHostIdle(this);
- // WARNING: We'll probably be deleted here.
- }
-}
-
-void HttpPipelinedHostImpl::OnPipelineHasCapacity(
- HttpPipelinedConnection* pipeline) {
- CHECK(ContainsKey(pipelines_, pipeline));
- if (CanPipelineAcceptRequests(pipeline)) {
- delegate_->OnHostHasAdditionalCapacity(this);
- }
- if (!pipeline->depth()) {
- OnPipelineEmpty(pipeline);
- // WARNING: We might be deleted here.
- }
-}
-
-void HttpPipelinedHostImpl::OnPipelineFeedback(
- HttpPipelinedConnection* pipeline,
- HttpPipelinedConnection::Feedback feedback) {
- CHECK(ContainsKey(pipelines_, pipeline));
- switch (feedback) {
- case HttpPipelinedConnection::OK:
- ++pipelines_[pipeline].num_successes;
- if (capability_ == PIPELINE_UNKNOWN) {
- capability_ = PIPELINE_PROBABLY_CAPABLE;
- NotifyAllPipelinesHaveCapacity();
- } else if (capability_ == PIPELINE_PROBABLY_CAPABLE &&
- pipelines_[pipeline].num_successes >=
- kNumKnownSuccessesThreshold) {
- capability_ = PIPELINE_CAPABLE;
- delegate_->OnHostDeterminedCapability(this, PIPELINE_CAPABLE);
- }
- break;
-
- case HttpPipelinedConnection::PIPELINE_SOCKET_ERROR:
- // Socket errors on the initial request - when no other requests are
- // pipelined - can't be due to pipelining.
- if (pipelines_[pipeline].num_successes > 0 || pipeline->depth() > 1) {
- // TODO(simonjam): This may be needlessly harsh. For example, pogo.com
- // only returns a socket error once after the root document, but is
- // otherwise able to pipeline just fine. Consider being more persistent
- // and only give up on pipelining if we get a couple of failures.
- capability_ = PIPELINE_INCAPABLE;
- delegate_->OnHostDeterminedCapability(this, PIPELINE_INCAPABLE);
- }
- break;
-
- case HttpPipelinedConnection::OLD_HTTP_VERSION:
- case HttpPipelinedConnection::AUTHENTICATION_REQUIRED:
- capability_ = PIPELINE_INCAPABLE;
- delegate_->OnHostDeterminedCapability(this, PIPELINE_INCAPABLE);
- break;
-
- case HttpPipelinedConnection::MUST_CLOSE_CONNECTION:
- break;
- }
-}
-
-int HttpPipelinedHostImpl::GetPipelineCapacity() const {
- int capacity = 0;
- switch (capability_) {
- case PIPELINE_CAPABLE:
- case PIPELINE_PROBABLY_CAPABLE:
- capacity = max_pipeline_depth();
- break;
-
- case PIPELINE_INCAPABLE:
- CHECK(false);
-
- case PIPELINE_UNKNOWN:
- capacity = 1;
- break;
-
- default:
- CHECK(false) << "Unkown pipeline capability: " << capability_;
- }
- return capacity;
-}
-
-bool HttpPipelinedHostImpl::CanPipelineAcceptRequests(
- HttpPipelinedConnection* pipeline) const {
- return capability_ != PIPELINE_INCAPABLE &&
- pipeline->usable() &&
- pipeline->active() &&
- pipeline->depth() < GetPipelineCapacity();
-}
-
-void HttpPipelinedHostImpl::NotifyAllPipelinesHaveCapacity() {
- // Calling OnPipelineHasCapacity() can have side effects that include
- // deleting and removing entries from |pipelines_|.
- PipelineInfoMap pipelines_to_notify = pipelines_;
- for (PipelineInfoMap::iterator it = pipelines_to_notify.begin();
- it != pipelines_to_notify.end(); ++it) {
- if (pipelines_.find(it->first) != pipelines_.end()) {
- OnPipelineHasCapacity(it->first);
- }
- }
-}
-
-base::Value* HttpPipelinedHostImpl::PipelineInfoToValue() const {
- base::ListValue* list_value = new base::ListValue();
- for (PipelineInfoMap::const_iterator it = pipelines_.begin();
- it != pipelines_.end(); ++it) {
- base::DictionaryValue* pipeline_dict = new base::DictionaryValue;
- pipeline_dict->SetString("host", key_.origin().ToString());
- pipeline_dict->SetBoolean("forced", false);
- pipeline_dict->SetInteger("depth", it->first->depth());
- pipeline_dict->SetInteger("capacity", GetPipelineCapacity());
- pipeline_dict->SetBoolean("usable", it->first->usable());
- pipeline_dict->SetBoolean("active", it->first->active());
- pipeline_dict->SetInteger("source_id", it->first->net_log().source().id);
- list_value->Append(pipeline_dict);
- }
- return list_value;
-}
-
-HttpPipelinedHostImpl::PipelineInfo::PipelineInfo()
- : num_successes(0) {
-}
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_host_impl.h b/chromium/net/http/http_pipelined_host_impl.h
deleted file mode 100644
index e2e53c93c37..00000000000
--- a/chromium/net/http/http_pipelined_host_impl.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (c) 2012 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_HTTP_HTTP_PIPELINED_HOST_IMPL_H_
-#define NET_HTTP_HTTP_PIPELINED_HOST_IMPL_H_
-
-#include <map>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/base/host_port_pair.h"
-#include "net/base/net_export.h"
-#include "net/http/http_pipelined_connection.h"
-#include "net/http/http_pipelined_host.h"
-#include "net/http/http_pipelined_host_capability.h"
-
-namespace base {
-class Value;
-}
-
-namespace net {
-
-class BoundNetLog;
-class ClientSocketHandle;
-class HttpPipelinedStream;
-class ProxyInfo;
-struct SSLConfig;
-
-// Manages all of the pipelining state for specific host with active pipelined
-// HTTP requests. Manages connection jobs, constructs pipelined streams, and
-// assigns requests to the least loaded pipelined connection.
-class NET_EXPORT_PRIVATE HttpPipelinedHostImpl
- : public HttpPipelinedHost,
- public HttpPipelinedConnection::Delegate {
- public:
- HttpPipelinedHostImpl(HttpPipelinedHost::Delegate* delegate,
- const HttpPipelinedHost::Key& key,
- HttpPipelinedConnection::Factory* factory,
- HttpPipelinedHostCapability capability);
- virtual ~HttpPipelinedHostImpl();
-
- // HttpPipelinedHost interface
- virtual HttpPipelinedStream* CreateStreamOnNewPipeline(
- ClientSocketHandle* connection,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated) OVERRIDE;
-
- virtual HttpPipelinedStream* CreateStreamOnExistingPipeline() OVERRIDE;
-
- virtual bool IsExistingPipelineAvailable() const OVERRIDE;
-
- // HttpPipelinedConnection::Delegate interface
-
- // Called when a pipelined connection completes a request. Adds a pending
- // request to the pipeline if the pipeline is still usable.
- virtual void OnPipelineHasCapacity(
- HttpPipelinedConnection* pipeline) OVERRIDE;
-
- virtual void OnPipelineFeedback(
- HttpPipelinedConnection* pipeline,
- HttpPipelinedConnection::Feedback feedback) OVERRIDE;
-
- virtual const Key& GetKey() const OVERRIDE;
-
- // Creates a Value summary of this host's |pipelines_|. Caller assumes
- // ownership of the returned Value.
- virtual base::Value* PipelineInfoToValue() const OVERRIDE;
-
- // Returns the maximum number of in-flight pipelined requests we'll allow on a
- // single connection.
- static int max_pipeline_depth() { return 3; }
-
- private:
- struct PipelineInfo {
- PipelineInfo();
-
- int num_successes;
- };
- typedef std::map<HttpPipelinedConnection*, PipelineInfo> PipelineInfoMap;
-
- // Called when a pipeline is empty and there are no pending requests. Closes
- // the connection.
- void OnPipelineEmpty(HttpPipelinedConnection* pipeline);
-
- // Adds the next pending request to the pipeline if it's still usuable.
- void AddRequestToPipeline(HttpPipelinedConnection* pipeline);
-
- // Returns the current pipeline capacity based on |capability_|. This should
- // not be called if |capability_| is INCAPABLE.
- int GetPipelineCapacity() const;
-
- // Returns true if |pipeline| can handle a new request. This is true if the
- // |pipeline| is active, usable, has capacity, and |capability_| is
- // sufficient.
- bool CanPipelineAcceptRequests(HttpPipelinedConnection* pipeline) const;
-
- // Called when |this| moves from UNKNOWN |capability_| to PROBABLY_CAPABLE.
- // Causes all pipelines to increase capacity to start pipelining.
- void NotifyAllPipelinesHaveCapacity();
-
- HttpPipelinedHost::Delegate* delegate_;
- const Key key_;
- PipelineInfoMap pipelines_;
- scoped_ptr<HttpPipelinedConnection::Factory> factory_;
- HttpPipelinedHostCapability capability_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpPipelinedHostImpl);
-};
-
-} // namespace net
-
-#endif // NET_HTTP_HTTP_PIPELINED_HOST_IMPL_H_
diff --git a/chromium/net/http/http_pipelined_host_impl_unittest.cc b/chromium/net/http/http_pipelined_host_impl_unittest.cc
deleted file mode 100644
index 2658472138d..00000000000
--- a/chromium/net/http/http_pipelined_host_impl_unittest.cc
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_host_impl.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "net/http/http_pipelined_connection.h"
-#include "net/http/http_pipelined_host_test_util.h"
-#include "net/proxy/proxy_info.h"
-#include "net/ssl/ssl_config_service.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::_;
-using testing::NiceMock;
-using testing::Ref;
-using testing::Return;
-using testing::ReturnNull;
-
-namespace net {
-
-namespace {
-
-ClientSocketHandle* kDummyConnection =
- reinterpret_cast<ClientSocketHandle*>(84);
-HttpPipelinedStream* kDummyStream =
- reinterpret_cast<HttpPipelinedStream*>(42);
-
-class HttpPipelinedHostImplTest : public testing::Test {
- public:
- HttpPipelinedHostImplTest()
- : key_(HostPortPair("host", 123)),
- factory_(new MockPipelineFactory), // Owned by host_.
- host_(new HttpPipelinedHostImpl(&delegate_, key_, factory_,
- PIPELINE_CAPABLE)) {
- }
-
- void SetCapability(HttpPipelinedHostCapability capability) {
- factory_ = new MockPipelineFactory;
- host_.reset(new HttpPipelinedHostImpl(
- &delegate_, key_, factory_, capability));
- }
-
- MockPipeline* AddTestPipeline(int depth, bool usable, bool active) {
- MockPipeline* pipeline = new MockPipeline(depth, usable, active);
- EXPECT_CALL(*factory_, CreateNewPipeline(kDummyConnection, host_.get(),
- MatchesOrigin(key_.origin()),
- Ref(ssl_config_), Ref(proxy_info_),
- Ref(net_log_), true,
- kProtoSPDY3))
- .Times(1)
- .WillOnce(Return(pipeline));
- EXPECT_CALL(*pipeline, CreateNewStream())
- .Times(1)
- .WillOnce(Return(kDummyStream));
- EXPECT_EQ(kDummyStream, host_->CreateStreamOnNewPipeline(
- kDummyConnection, ssl_config_, proxy_info_, net_log_, true,
- kProtoSPDY3));
- return pipeline;
- }
-
- void ClearTestPipeline(MockPipeline* pipeline) {
- pipeline->SetState(0, true, true);
- host_->OnPipelineHasCapacity(pipeline);
- }
-
- NiceMock<MockHostDelegate> delegate_;
- HttpPipelinedHost::Key key_;
- MockPipelineFactory* factory_;
- scoped_ptr<HttpPipelinedHostImpl> host_;
-
- SSLConfig ssl_config_;
- ProxyInfo proxy_info_;
- BoundNetLog net_log_;
-};
-
-TEST_F(HttpPipelinedHostImplTest, Delegate) {
- EXPECT_TRUE(key_.origin().Equals(host_->GetKey().origin()));
-}
-
-TEST_F(HttpPipelinedHostImplTest, OnUnusablePipelineHasCapacity) {
- MockPipeline* pipeline = AddTestPipeline(0, false, true);
-
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(0);
- EXPECT_CALL(delegate_, OnHostIdle(host_.get()))
- .Times(1);
- host_->OnPipelineHasCapacity(pipeline);
-}
-
-TEST_F(HttpPipelinedHostImplTest, OnUsablePipelineHasCapacity) {
- MockPipeline* pipeline = AddTestPipeline(1, true, true);
-
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- EXPECT_CALL(delegate_, OnHostIdle(host_.get()))
- .Times(0);
-
- host_->OnPipelineHasCapacity(pipeline);
-
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- EXPECT_CALL(delegate_, OnHostIdle(host_.get()))
- .Times(1);
- ClearTestPipeline(pipeline);
-}
-
-TEST_F(HttpPipelinedHostImplTest, IgnoresUnusablePipeline) {
- MockPipeline* pipeline = AddTestPipeline(1, false, true);
-
- EXPECT_FALSE(host_->IsExistingPipelineAvailable());
- EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
-
- ClearTestPipeline(pipeline);
-}
-
-TEST_F(HttpPipelinedHostImplTest, IgnoresInactivePipeline) {
- MockPipeline* pipeline = AddTestPipeline(1, true, false);
-
- EXPECT_FALSE(host_->IsExistingPipelineAvailable());
- EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
-
- ClearTestPipeline(pipeline);
-}
-
-TEST_F(HttpPipelinedHostImplTest, IgnoresFullPipeline) {
- MockPipeline* pipeline = AddTestPipeline(
- HttpPipelinedHostImpl::max_pipeline_depth(), true, true);
-
- EXPECT_FALSE(host_->IsExistingPipelineAvailable());
- EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
-
- ClearTestPipeline(pipeline);
-}
-
-TEST_F(HttpPipelinedHostImplTest, PicksLeastLoadedPipeline) {
- MockPipeline* full_pipeline = AddTestPipeline(
- HttpPipelinedHostImpl::max_pipeline_depth(), true, true);
- MockPipeline* usable_pipeline = AddTestPipeline(
- HttpPipelinedHostImpl::max_pipeline_depth() - 1, true, true);
- MockPipeline* empty_pipeline = AddTestPipeline(0, true, true);
-
- EXPECT_TRUE(host_->IsExistingPipelineAvailable());
- EXPECT_CALL(*empty_pipeline, CreateNewStream())
- .Times(1)
- .WillOnce(ReturnNull());
- EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
-
- ClearTestPipeline(full_pipeline);
- ClearTestPipeline(usable_pipeline);
- ClearTestPipeline(empty_pipeline);
-}
-
-TEST_F(HttpPipelinedHostImplTest, OpensUpOnPipelineSuccess) {
- SetCapability(PIPELINE_UNKNOWN);
- MockPipeline* pipeline = AddTestPipeline(1, true, true);
-
- EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- host_->OnPipelineFeedback(pipeline, HttpPipelinedConnection::OK);
-
- EXPECT_CALL(*pipeline, CreateNewStream())
- .Times(1)
- .WillOnce(Return(kDummyStream));
- EXPECT_EQ(kDummyStream, host_->CreateStreamOnExistingPipeline());
-
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- ClearTestPipeline(pipeline);
-}
-
-TEST_F(HttpPipelinedHostImplTest, OpensAllPipelinesOnPipelineSuccess) {
- SetCapability(PIPELINE_UNKNOWN);
- MockPipeline* pipeline1 = AddTestPipeline(1, false, true);
- MockPipeline* pipeline2 = AddTestPipeline(1, true, true);
-
- EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- host_->OnPipelineFeedback(pipeline1, HttpPipelinedConnection::OK);
-
- EXPECT_CALL(*pipeline2, CreateNewStream())
- .Times(1)
- .WillOnce(Return(kDummyStream));
- EXPECT_EQ(kDummyStream, host_->CreateStreamOnExistingPipeline());
-
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(2);
- ClearTestPipeline(pipeline1);
- ClearTestPipeline(pipeline2);
-}
-
-TEST_F(HttpPipelinedHostImplTest, ShutsDownOnOldVersion) {
- SetCapability(PIPELINE_UNKNOWN);
- MockPipeline* pipeline = AddTestPipeline(1, true, true);
-
- EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(0);
- EXPECT_CALL(delegate_,
- OnHostDeterminedCapability(host_.get(), PIPELINE_INCAPABLE))
- .Times(1);
- host_->OnPipelineFeedback(pipeline,
- HttpPipelinedConnection::OLD_HTTP_VERSION);
-
- ClearTestPipeline(pipeline);
- EXPECT_EQ(NULL, host_->CreateStreamOnNewPipeline(
- kDummyConnection, ssl_config_, proxy_info_, net_log_, true,
- kProtoSPDY3));
-}
-
-TEST_F(HttpPipelinedHostImplTest, ShutsDownOnAuthenticationRequired) {
- SetCapability(PIPELINE_UNKNOWN);
- MockPipeline* pipeline = AddTestPipeline(1, true, true);
-
- EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(0);
- EXPECT_CALL(delegate_,
- OnHostDeterminedCapability(host_.get(), PIPELINE_INCAPABLE))
- .Times(1);
- host_->OnPipelineFeedback(pipeline,
- HttpPipelinedConnection::AUTHENTICATION_REQUIRED);
-
- ClearTestPipeline(pipeline);
- EXPECT_EQ(NULL, host_->CreateStreamOnNewPipeline(
- kDummyConnection, ssl_config_, proxy_info_, net_log_, true,
- kProtoSPDY3));
-}
-
-TEST_F(HttpPipelinedHostImplTest, ConnectionCloseHasNoEffect) {
- SetCapability(PIPELINE_UNKNOWN);
- MockPipeline* pipeline = AddTestPipeline(1, true, true);
-
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(0);
- EXPECT_CALL(delegate_, OnHostDeterminedCapability(host_.get(), _))
- .Times(0);
- host_->OnPipelineFeedback(pipeline,
- HttpPipelinedConnection::MUST_CLOSE_CONNECTION);
- EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
-
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- ClearTestPipeline(pipeline);
-}
-
-TEST_F(HttpPipelinedHostImplTest, SuccessesLeadToCapable) {
- SetCapability(PIPELINE_UNKNOWN);
- MockPipeline* pipeline = AddTestPipeline(1, true, true);
-
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- EXPECT_CALL(delegate_,
- OnHostDeterminedCapability(host_.get(), PIPELINE_CAPABLE))
- .Times(1);
- host_->OnPipelineFeedback(pipeline, HttpPipelinedConnection::OK);
-
- pipeline->SetState(3, true, true);
- host_->OnPipelineFeedback(pipeline, HttpPipelinedConnection::OK);
- host_->OnPipelineFeedback(pipeline, HttpPipelinedConnection::OK);
-
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- ClearTestPipeline(pipeline);
-}
-
-TEST_F(HttpPipelinedHostImplTest, IgnoresSocketErrorOnFirstRequest) {
- SetCapability(PIPELINE_UNKNOWN);
- MockPipeline* pipeline = AddTestPipeline(1, true, true);
-
- EXPECT_CALL(delegate_, OnHostDeterminedCapability(host_.get(), _))
- .Times(0);
- host_->OnPipelineFeedback(pipeline,
- HttpPipelinedConnection::PIPELINE_SOCKET_ERROR);
-
- EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
- .Times(1);
- host_->OnPipelineFeedback(pipeline,
- HttpPipelinedConnection::OK);
-
- EXPECT_CALL(delegate_,
- OnHostDeterminedCapability(host_.get(), PIPELINE_INCAPABLE))
- .Times(1);
- host_->OnPipelineFeedback(pipeline,
- HttpPipelinedConnection::PIPELINE_SOCKET_ERROR);
-
- ClearTestPipeline(pipeline);
-}
-
-TEST_F(HttpPipelinedHostImplTest, HeedsSocketErrorOnFirstRequestWithPipeline) {
- SetCapability(PIPELINE_UNKNOWN);
- MockPipeline* pipeline = AddTestPipeline(2, true, true);
-
- EXPECT_CALL(delegate_,
- OnHostDeterminedCapability(host_.get(), PIPELINE_INCAPABLE))
- .Times(1);
- host_->OnPipelineFeedback(pipeline,
- HttpPipelinedConnection::PIPELINE_SOCKET_ERROR);
-
- ClearTestPipeline(pipeline);
-}
-
-} // anonymous namespace
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_host_pool.cc b/chromium/net/http/http_pipelined_host_pool.cc
deleted file mode 100644
index ee37e74c29d..00000000000
--- a/chromium/net/http/http_pipelined_host_pool.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_host_pool.h"
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "base/values.h"
-#include "net/http/http_pipelined_host_capability.h"
-#include "net/http/http_pipelined_host_forced.h"
-#include "net/http/http_pipelined_host_impl.h"
-#include "net/http/http_server_properties.h"
-
-namespace net {
-
-class HttpPipelinedHostImplFactory : public HttpPipelinedHost::Factory {
- public:
- virtual HttpPipelinedHost* CreateNewHost(
- HttpPipelinedHost::Delegate* delegate,
- const HttpPipelinedHost::Key& key,
- HttpPipelinedConnection::Factory* factory,
- HttpPipelinedHostCapability capability,
- bool force_pipelining) OVERRIDE {
- if (force_pipelining) {
- return new HttpPipelinedHostForced(delegate, key, factory);
- } else {
- return new HttpPipelinedHostImpl(delegate, key, factory, capability);
- }
- }
-};
-
-HttpPipelinedHostPool::HttpPipelinedHostPool(
- Delegate* delegate,
- HttpPipelinedHost::Factory* factory,
- const base::WeakPtr<HttpServerProperties>& http_server_properties,
- bool force_pipelining)
- : delegate_(delegate),
- factory_(factory),
- http_server_properties_(http_server_properties),
- force_pipelining_(force_pipelining) {
- if (!factory) {
- factory_.reset(new HttpPipelinedHostImplFactory);
- }
-}
-
-HttpPipelinedHostPool::~HttpPipelinedHostPool() {
- CHECK(host_map_.empty());
-}
-
-bool HttpPipelinedHostPool::IsKeyEligibleForPipelining(
- const HttpPipelinedHost::Key& key) {
- HttpPipelinedHostCapability capability =
- http_server_properties_->GetPipelineCapability(key.origin());
- return capability != PIPELINE_INCAPABLE;
-}
-
-HttpPipelinedStream* HttpPipelinedHostPool::CreateStreamOnNewPipeline(
- const HttpPipelinedHost::Key& key,
- ClientSocketHandle* connection,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated) {
- HttpPipelinedHost* host = GetPipelinedHost(key, true);
- if (!host) {
- return NULL;
- }
- return host->CreateStreamOnNewPipeline(connection, used_ssl_config,
- used_proxy_info, net_log,
- was_npn_negotiated,
- protocol_negotiated);
-}
-
-HttpPipelinedStream* HttpPipelinedHostPool::CreateStreamOnExistingPipeline(
- const HttpPipelinedHost::Key& key) {
- HttpPipelinedHost* host = GetPipelinedHost(key, false);
- if (!host) {
- return NULL;
- }
- return host->CreateStreamOnExistingPipeline();
-}
-
-bool HttpPipelinedHostPool::IsExistingPipelineAvailableForKey(
- const HttpPipelinedHost::Key& key) {
- HttpPipelinedHost* host = GetPipelinedHost(key, false);
- if (!host) {
- return false;
- }
- return host->IsExistingPipelineAvailable();
-}
-
-HttpPipelinedHost* HttpPipelinedHostPool::GetPipelinedHost(
- const HttpPipelinedHost::Key& key, bool create_if_not_found) {
- HostMap::iterator host_it = host_map_.find(key);
- if (host_it != host_map_.end()) {
- CHECK(host_it->second);
- return host_it->second;
- } else if (!create_if_not_found) {
- return NULL;
- }
-
- HttpPipelinedHostCapability capability =
- http_server_properties_->GetPipelineCapability(key.origin());
- if (capability == PIPELINE_INCAPABLE) {
- return NULL;
- }
-
- HttpPipelinedHost* host = factory_->CreateNewHost(
- this, key, NULL, capability, force_pipelining_);
- host_map_[key] = host;
- return host;
-}
-
-void HttpPipelinedHostPool::OnHostIdle(HttpPipelinedHost* host) {
- const HttpPipelinedHost::Key& key = host->GetKey();
- CHECK(ContainsKey(host_map_, key));
- host_map_.erase(key);
- delete host;
-}
-
-void HttpPipelinedHostPool::OnHostHasAdditionalCapacity(
- HttpPipelinedHost* host) {
- delegate_->OnHttpPipelinedHostHasAdditionalCapacity(host);
-}
-
-void HttpPipelinedHostPool::OnHostDeterminedCapability(
- HttpPipelinedHost* host,
- HttpPipelinedHostCapability capability) {
- http_server_properties_->SetPipelineCapability(host->GetKey().origin(),
- capability);
-}
-
-base::Value* HttpPipelinedHostPool::PipelineInfoToValue() const {
- base::ListValue* list = new base::ListValue();
- for (HostMap::const_iterator it = host_map_.begin();
- it != host_map_.end(); ++it) {
- base::Value* value = it->second->PipelineInfoToValue();
- list->Append(value);
- }
- return list;
-}
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_host_pool.h b/chromium/net/http/http_pipelined_host_pool.h
deleted file mode 100644
index 45cb38cedf6..00000000000
--- a/chromium/net/http/http_pipelined_host_pool.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2012 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_HTTP_HTTP_PIPELINED_HOST_POOL_H_
-#define NET_HTTP_HTTP_PIPELINED_HOST_POOL_H_
-
-#include <map>
-
-#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "net/http/http_pipelined_host.h"
-#include "net/http/http_pipelined_host_capability.h"
-
-namespace base {
-class Value;
-}
-
-namespace net {
-
-class HostPortPair;
-class HttpPipelinedStream;
-class HttpServerProperties;
-
-// Manages all of the pipelining state for specific host with active pipelined
-// HTTP requests. Manages connection jobs, constructs pipelined streams, and
-// assigns requests to the least loaded pipelined connection.
-class NET_EXPORT_PRIVATE HttpPipelinedHostPool
- : public HttpPipelinedHost::Delegate {
- public:
- class Delegate {
- public:
- // Called when a HttpPipelinedHost has new capacity. Attempts to allocate
- // any pending pipeline-capable requests to pipelines.
- virtual void OnHttpPipelinedHostHasAdditionalCapacity(
- HttpPipelinedHost* host) = 0;
- };
-
- HttpPipelinedHostPool(
- Delegate* delegate,
- HttpPipelinedHost::Factory* factory,
- const base::WeakPtr<HttpServerProperties>& http_server_properties,
- bool force_pipelining);
- virtual ~HttpPipelinedHostPool();
-
- // Returns true if pipelining might work for |key|. Generally, this returns
- // true, unless |key| is known to have failed pipelining recently.
- bool IsKeyEligibleForPipelining(const HttpPipelinedHost::Key& key);
-
- // Constructs a new pipeline on |connection| and returns a new
- // HttpPipelinedStream that uses it.
- HttpPipelinedStream* CreateStreamOnNewPipeline(
- const HttpPipelinedHost::Key& key,
- ClientSocketHandle* connection,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated);
-
- // Tries to find an existing pipeline with capacity for a new request. If
- // successful, returns a new stream on that pipeline. Otherwise, returns NULL.
- HttpPipelinedStream* CreateStreamOnExistingPipeline(
- const HttpPipelinedHost::Key& key);
-
- // Returns true if a pipelined connection already exists for |key| and
- // can accept new requests.
- bool IsExistingPipelineAvailableForKey(const HttpPipelinedHost::Key& key);
-
- // Callbacks for HttpPipelinedHost.
- virtual void OnHostIdle(HttpPipelinedHost* host) OVERRIDE;
-
- virtual void OnHostHasAdditionalCapacity(HttpPipelinedHost* host) OVERRIDE;
-
- virtual void OnHostDeterminedCapability(
- HttpPipelinedHost* host,
- HttpPipelinedHostCapability capability) OVERRIDE;
-
- // Creates a Value summary of this pool's |host_map_|. Caller assumes
- // ownership of the returned Value.
- base::Value* PipelineInfoToValue() const;
-
- private:
- typedef std::map<HttpPipelinedHost::Key, HttpPipelinedHost*> HostMap;
-
- HttpPipelinedHost* GetPipelinedHost(const HttpPipelinedHost::Key& key,
- bool create_if_not_found);
-
- Delegate* delegate_;
- scoped_ptr<HttpPipelinedHost::Factory> factory_;
- HostMap host_map_;
- const base::WeakPtr<HttpServerProperties> http_server_properties_;
- bool force_pipelining_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpPipelinedHostPool);
-};
-
-} // namespace net
-
-#endif // NET_HTTP_HTTP_PIPELINED_HOST_POOL_H_
diff --git a/chromium/net/http/http_pipelined_host_pool_unittest.cc b/chromium/net/http/http_pipelined_host_pool_unittest.cc
deleted file mode 100644
index fa8d93facb1..00000000000
--- a/chromium/net/http/http_pipelined_host_pool_unittest.cc
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_host_pool.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "base/rand_util.h"
-#include "net/http/http_pipelined_host.h"
-#include "net/http/http_pipelined_host_capability.h"
-#include "net/http/http_server_properties_impl.h"
-#include "net/proxy/proxy_info.h"
-#include "net/ssl/ssl_config_service.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::_;
-using testing::Ref;
-using testing::Return;
-using testing::ReturnNull;
-
-namespace net {
-
-namespace {
-
-ClientSocketHandle* kDummyConnection =
- reinterpret_cast<ClientSocketHandle*>(188);
-HttpPipelinedStream* kDummyStream =
- reinterpret_cast<HttpPipelinedStream*>(99);
-
-class MockPoolDelegate : public HttpPipelinedHostPool::Delegate {
- public:
- MOCK_METHOD1(OnHttpPipelinedHostHasAdditionalCapacity,
- void(HttpPipelinedHost* host));
-};
-
-class MockHostFactory : public HttpPipelinedHost::Factory {
- public:
- MOCK_METHOD5(CreateNewHost, HttpPipelinedHost*(
- HttpPipelinedHost::Delegate* delegate,
- const HttpPipelinedHost::Key& key,
- HttpPipelinedConnection::Factory* factory,
- HttpPipelinedHostCapability capability,
- bool force_pipelining));
-};
-
-class MockHost : public HttpPipelinedHost {
- public:
- MockHost(const Key& key)
- : key_(key) {
- }
-
- MOCK_METHOD6(CreateStreamOnNewPipeline, HttpPipelinedStream*(
- ClientSocketHandle* connection,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated));
- MOCK_METHOD0(CreateStreamOnExistingPipeline, HttpPipelinedStream*());
- MOCK_CONST_METHOD0(IsExistingPipelineAvailable, bool());
- MOCK_CONST_METHOD0(PipelineInfoToValue, base::Value*());
-
- virtual const Key& GetKey() const OVERRIDE { return key_; }
-
- private:
- Key key_;
-};
-
-class HttpPipelinedHostPoolTest : public testing::Test {
- public:
- HttpPipelinedHostPoolTest()
- : key_(HostPortPair("host", 123)),
- factory_(new MockHostFactory), // Owned by pool_.
- host_(new MockHost(key_)), // Owned by pool_.
- http_server_properties_(new HttpServerPropertiesImpl()),
- pool_(new HttpPipelinedHostPool(
- &delegate_, factory_,
- http_server_properties_->GetWeakPtr(), false)),
- was_npn_negotiated_(false),
- protocol_negotiated_(kProtoUnknown) {
- }
-
- void CreateDummyStream(const HttpPipelinedHost::Key& key,
- ClientSocketHandle* connection,
- HttpPipelinedStream* stream,
- MockHost* host) {
- EXPECT_CALL(*host, CreateStreamOnNewPipeline(connection,
- Ref(ssl_config_),
- Ref(proxy_info_),
- Ref(net_log_),
- was_npn_negotiated_,
- protocol_negotiated_))
- .Times(1)
- .WillOnce(Return(stream));
- EXPECT_EQ(stream,
- pool_->CreateStreamOnNewPipeline(key, connection,
- ssl_config_, proxy_info_,
- net_log_, was_npn_negotiated_,
- protocol_negotiated_));
- }
-
- MockHost* CreateDummyHost(const HttpPipelinedHost::Key& key) {
- MockHost* mock_host = new MockHost(key);
- EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key), _,
- PIPELINE_UNKNOWN, false))
- .Times(1)
- .WillOnce(Return(mock_host));
- ClientSocketHandle* dummy_connection =
- reinterpret_cast<ClientSocketHandle*>(base::RandUint64());
- HttpPipelinedStream* dummy_stream =
- reinterpret_cast<HttpPipelinedStream*>(base::RandUint64());
- CreateDummyStream(key, dummy_connection, dummy_stream, mock_host);
- return mock_host;
- }
-
- HttpPipelinedHost::Key key_;
- MockPoolDelegate delegate_;
- MockHostFactory* factory_;
- MockHost* host_;
- scoped_ptr<HttpServerPropertiesImpl> http_server_properties_;
- scoped_ptr<HttpPipelinedHostPool> pool_;
-
- const SSLConfig ssl_config_;
- const ProxyInfo proxy_info_;
- const BoundNetLog net_log_;
- bool was_npn_negotiated_;
- NextProto protocol_negotiated_;
-};
-
-TEST_F(HttpPipelinedHostPoolTest, DefaultUnknown) {
- EXPECT_TRUE(pool_->IsKeyEligibleForPipelining(key_));
- EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _,
- PIPELINE_UNKNOWN, false))
- .Times(1)
- .WillOnce(Return(host_));
-
- CreateDummyStream(key_, kDummyConnection, kDummyStream, host_);
- pool_->OnHostIdle(host_);
-}
-
-TEST_F(HttpPipelinedHostPoolTest, RemembersIncapable) {
- EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _,
- PIPELINE_UNKNOWN, false))
- .Times(1)
- .WillOnce(Return(host_));
-
- CreateDummyStream(key_, kDummyConnection, kDummyStream, host_);
- pool_->OnHostDeterminedCapability(host_, PIPELINE_INCAPABLE);
- pool_->OnHostIdle(host_);
- EXPECT_FALSE(pool_->IsKeyEligibleForPipelining(key_));
- EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _,
- PIPELINE_INCAPABLE, false))
- .Times(0);
- EXPECT_EQ(NULL,
- pool_->CreateStreamOnNewPipeline(key_, kDummyConnection,
- ssl_config_, proxy_info_, net_log_,
- was_npn_negotiated_,
- protocol_negotiated_));
-}
-
-TEST_F(HttpPipelinedHostPoolTest, RemembersCapable) {
- EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _,
- PIPELINE_UNKNOWN, false))
- .Times(1)
- .WillOnce(Return(host_));
-
- CreateDummyStream(key_, kDummyConnection, kDummyStream, host_);
- pool_->OnHostDeterminedCapability(host_, PIPELINE_CAPABLE);
- pool_->OnHostIdle(host_);
- EXPECT_TRUE(pool_->IsKeyEligibleForPipelining(key_));
-
- host_ = new MockHost(key_);
- EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _,
- PIPELINE_CAPABLE, false))
- .Times(1)
- .WillOnce(Return(host_));
- CreateDummyStream(key_, kDummyConnection, kDummyStream, host_);
- pool_->OnHostIdle(host_);
-}
-
-TEST_F(HttpPipelinedHostPoolTest, IncapableIsSticky) {
- EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _,
- PIPELINE_UNKNOWN, false))
- .Times(1)
- .WillOnce(Return(host_));
-
- CreateDummyStream(key_, kDummyConnection, kDummyStream, host_);
- pool_->OnHostDeterminedCapability(host_, PIPELINE_CAPABLE);
- pool_->OnHostDeterminedCapability(host_, PIPELINE_INCAPABLE);
- pool_->OnHostDeterminedCapability(host_, PIPELINE_CAPABLE);
- pool_->OnHostIdle(host_);
- EXPECT_FALSE(pool_->IsKeyEligibleForPipelining(key_));
-}
-
-TEST_F(HttpPipelinedHostPoolTest, RemainsUnknownWithoutFeedback) {
- EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _,
- PIPELINE_UNKNOWN, false))
- .Times(1)
- .WillOnce(Return(host_));
-
- CreateDummyStream(key_, kDummyConnection, kDummyStream, host_);
- pool_->OnHostIdle(host_);
- EXPECT_TRUE(pool_->IsKeyEligibleForPipelining(key_));
-
- host_ = new MockHost(key_);
- EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(key_), _,
- PIPELINE_UNKNOWN, false))
- .Times(1)
- .WillOnce(Return(host_));
-
- CreateDummyStream(key_, kDummyConnection, kDummyStream, host_);
- pool_->OnHostIdle(host_);
-}
-
-TEST_F(HttpPipelinedHostPoolTest, PopulatesServerProperties) {
- EXPECT_EQ(PIPELINE_UNKNOWN,
- http_server_properties_->GetPipelineCapability(
- host_->GetKey().origin()));
- pool_->OnHostDeterminedCapability(host_, PIPELINE_CAPABLE);
- EXPECT_EQ(PIPELINE_CAPABLE,
- http_server_properties_->GetPipelineCapability(
- host_->GetKey().origin()));
- delete host_; // Must manually delete, because it's never added to |pool_|.
-}
-
-TEST_F(HttpPipelinedHostPoolTest, MultipleKeys) {
- HttpPipelinedHost::Key key1(HostPortPair("host", 123));
- HttpPipelinedHost::Key key2(HostPortPair("host", 456));
- HttpPipelinedHost::Key key3(HostPortPair("other", 456));
- HttpPipelinedHost::Key key4(HostPortPair("other", 789));
- MockHost* host1 = CreateDummyHost(key1);
- MockHost* host2 = CreateDummyHost(key2);
- MockHost* host3 = CreateDummyHost(key3);
-
- EXPECT_CALL(*host1, IsExistingPipelineAvailable())
- .Times(1)
- .WillOnce(Return(true));
- EXPECT_TRUE(pool_->IsExistingPipelineAvailableForKey(key1));
-
- EXPECT_CALL(*host2, IsExistingPipelineAvailable())
- .Times(1)
- .WillOnce(Return(false));
- EXPECT_FALSE(pool_->IsExistingPipelineAvailableForKey(key2));
-
- EXPECT_CALL(*host3, IsExistingPipelineAvailable())
- .Times(1)
- .WillOnce(Return(true));
- EXPECT_TRUE(pool_->IsExistingPipelineAvailableForKey(key3));
-
- EXPECT_FALSE(pool_->IsExistingPipelineAvailableForKey(key4));
-
- pool_->OnHostIdle(host1);
- pool_->OnHostIdle(host2);
- pool_->OnHostIdle(host3);
-
- delete host_; // Must manually delete, because it's never added to |pool_|.
-}
-
-} // anonymous namespace
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_host_test_util.cc b/chromium/net/http/http_pipelined_host_test_util.cc
deleted file mode 100644
index 5162e983708..00000000000
--- a/chromium/net/http/http_pipelined_host_test_util.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_host_test_util.h"
-
-#include "net/proxy/proxy_info.h"
-#include "net/ssl/ssl_config_service.h"
-
-namespace net {
-
-MockHostDelegate::MockHostDelegate() {
-}
-
-MockHostDelegate::~MockHostDelegate() {
-}
-
-MockPipelineFactory::MockPipelineFactory() {
-}
-
-MockPipelineFactory::~MockPipelineFactory() {
-}
-
-MockPipeline::MockPipeline(int depth, bool usable, bool active)
- : depth_(depth),
- usable_(usable),
- active_(active) {
-}
-
-MockPipeline::~MockPipeline() {
-}
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_host_test_util.h b/chromium/net/http/http_pipelined_host_test_util.h
deleted file mode 100644
index 245ff02c4d5..00000000000
--- a/chromium/net/http/http_pipelined_host_test_util.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_connection.h"
-#include "net/http/http_pipelined_host.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace net {
-
-class MockHostDelegate : public HttpPipelinedHost::Delegate {
- public:
- MockHostDelegate();
- virtual ~MockHostDelegate();
-
- MOCK_METHOD1(OnHostIdle, void(HttpPipelinedHost* host));
- MOCK_METHOD1(OnHostHasAdditionalCapacity, void(HttpPipelinedHost* host));
- MOCK_METHOD2(OnHostDeterminedCapability,
- void(HttpPipelinedHost* host,
- HttpPipelinedHostCapability capability));
-};
-
-class MockPipelineFactory : public HttpPipelinedConnection::Factory {
- public:
- MockPipelineFactory();
- virtual ~MockPipelineFactory();
-
- MOCK_METHOD8(CreateNewPipeline, HttpPipelinedConnection*(
- ClientSocketHandle* connection,
- HttpPipelinedConnection::Delegate* delegate,
- const HostPortPair& origin,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- const BoundNetLog& net_log,
- bool was_npn_negotiated,
- NextProto protocol_negotiated));
-};
-
-class MockPipeline : public HttpPipelinedConnection {
- public:
- MockPipeline(int depth, bool usable, bool active);
- virtual ~MockPipeline();
-
- void SetState(int depth, bool usable, bool active) {
- depth_ = depth;
- usable_ = usable;
- active_ = active;
- }
-
- virtual int depth() const OVERRIDE { return depth_; }
- virtual bool usable() const OVERRIDE { return usable_; }
- virtual bool active() const OVERRIDE { return active_; }
-
- MOCK_METHOD0(CreateNewStream, HttpPipelinedStream*());
- MOCK_METHOD1(OnStreamDeleted, void(int pipeline_id));
- MOCK_CONST_METHOD0(used_ssl_config, const SSLConfig&());
- MOCK_CONST_METHOD0(used_proxy_info, const ProxyInfo&());
- MOCK_CONST_METHOD0(net_log, const BoundNetLog&());
- MOCK_CONST_METHOD0(was_npn_negotiated, bool());
- MOCK_CONST_METHOD0(protocol_negotiated, NextProto());
-
- private:
- int depth_;
- bool usable_;
- bool active_;
-};
-
-MATCHER_P(MatchesOrigin, expected, "") { return expected.Equals(arg); }
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_network_transaction_unittest.cc b/chromium/net/http/http_pipelined_network_transaction_unittest.cc
deleted file mode 100644
index 80b74fd554b..00000000000
--- a/chromium/net/http/http_pipelined_network_transaction_unittest.cc
+++ /dev/null
@@ -1,1035 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include <string>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "net/base/address_list.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/base/request_priority.h"
-#include "net/dns/host_cache.h"
-#include "net/dns/mock_host_resolver.h"
-#include "net/http/http_auth_handler_mock.h"
-#include "net/http/http_network_session.h"
-#include "net/http/http_network_transaction.h"
-#include "net/http/http_request_info.h"
-#include "net/http/http_server_properties_impl.h"
-#include "net/proxy/proxy_config_service.h"
-#include "net/proxy/proxy_service.h"
-#include "net/socket/client_socket_handle.h"
-#include "net/socket/client_socket_pool_histograms.h"
-#include "net/socket/client_socket_pool_manager.h"
-#include "net/socket/socket_test_util.h"
-#include "net/ssl/ssl_config_service_defaults.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::StrEq;
-
-namespace net {
-
-namespace {
-
-class SimpleProxyConfigService : public ProxyConfigService {
- public:
- virtual void AddObserver(Observer* observer) OVERRIDE {
- observer_ = observer;
- }
-
- virtual void RemoveObserver(Observer* observer) OVERRIDE {
- if (observer_ == observer) {
- observer_ = NULL;
- }
- }
-
- virtual ConfigAvailability GetLatestProxyConfig(
- ProxyConfig* config) OVERRIDE {
- *config = config_;
- return CONFIG_VALID;
- }
-
- void IncrementConfigId() {
- config_.set_id(config_.id() + 1);
- observer_->OnProxyConfigChanged(config_, ProxyConfigService::CONFIG_VALID);
- }
-
- private:
- ProxyConfig config_;
- Observer* observer_;
-};
-
-class HttpPipelinedNetworkTransactionTest : public testing::Test {
- public:
- HttpPipelinedNetworkTransactionTest()
- : histograms_("a"),
- pool_(1, 1, &histograms_, &factory_) {
- }
-
- void Initialize(bool force_http_pipelining) {
- // Normally, this code could just go in SetUp(). For a few of these tests,
- // we change the default number of sockets per group. That needs to be done
- // before we construct the HttpNetworkSession.
- proxy_config_service_ = new SimpleProxyConfigService();
- proxy_service_.reset(new ProxyService(proxy_config_service_, NULL, NULL));
- ssl_config_ = new SSLConfigServiceDefaults;
- auth_handler_factory_.reset(new HttpAuthHandlerMock::Factory());
-
- HttpNetworkSession::Params session_params;
- session_params.client_socket_factory = &factory_;
- session_params.proxy_service = proxy_service_.get();
- session_params.host_resolver = &mock_resolver_;
- session_params.ssl_config_service = ssl_config_.get();
- session_params.http_auth_handler_factory = auth_handler_factory_.get();
- session_params.http_server_properties =
- http_server_properties_.GetWeakPtr();
- session_params.force_http_pipelining = force_http_pipelining;
- session_params.http_pipelining_enabled = true;
- session_ = new HttpNetworkSession(session_params);
- }
-
- void AddExpectedConnection(MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count) {
- DeterministicSocketData* data = new DeterministicSocketData(
- reads, reads_count, writes, writes_count);
- data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
- if (reads_count || writes_count) {
- data->StopAfter(reads_count + writes_count);
- }
- factory_.AddSocketDataProvider(data);
- data_vector_.push_back(data);
- }
-
- enum RequestInfoOptions {
- REQUEST_DEFAULT,
- REQUEST_MAIN_RESOURCE,
- };
-
- HttpRequestInfo* GetRequestInfo(
- const char* filename, RequestInfoOptions options = REQUEST_DEFAULT) {
- std::string url = base::StringPrintf("http://localhost/%s", filename);
- HttpRequestInfo* request_info = new HttpRequestInfo;
- request_info->url = GURL(url);
- request_info->method = "GET";
- if (options == REQUEST_MAIN_RESOURCE) {
- request_info->load_flags = LOAD_MAIN_FRAME;
- }
- request_info_vector_.push_back(request_info);
- return request_info;
- }
-
- void ExpectResponse(const std::string& expected,
- HttpNetworkTransaction& transaction,
- IoMode io_mode) {
- scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size()));
- if (io_mode == ASYNC) {
- EXPECT_EQ(ERR_IO_PENDING, transaction.Read(buffer.get(), expected.size(),
- callback_.callback()));
- data_vector_[0]->RunFor(1);
- EXPECT_EQ(static_cast<int>(expected.length()), callback_.WaitForResult());
- } else {
- EXPECT_EQ(static_cast<int>(expected.size()),
- transaction.Read(buffer.get(), expected.size(),
- callback_.callback()));
- }
- std::string actual(buffer->data(), expected.size());
- EXPECT_THAT(actual, StrEq(expected));
- EXPECT_EQ(OK, transaction.Read(buffer.get(), expected.size(),
- callback_.callback()));
- }
-
- void CompleteTwoRequests(int data_index, int stop_at_step) {
- scoped_ptr<HttpNetworkTransaction> one_transaction(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
- TestCompletionCallback one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction->Start(GetRequestInfo("one.html"),
- one_callback.callback(), BoundNetLog()));
- EXPECT_EQ(OK, one_callback.WaitForResult());
-
- HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback two_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- two_transaction.Start(GetRequestInfo("two.html"),
- two_callback.callback(), BoundNetLog()));
-
- TestCompletionCallback one_read_callback;
- scoped_refptr<IOBuffer> buffer(new IOBuffer(8));
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction->Read(buffer.get(), 8,
- one_read_callback.callback()));
-
- data_vector_[data_index]->SetStop(stop_at_step);
- data_vector_[data_index]->Run();
- EXPECT_EQ(8, one_read_callback.WaitForResult());
- data_vector_[data_index]->SetStop(10);
- std::string actual(buffer->data(), 8);
- EXPECT_THAT(actual, StrEq("one.html"));
- EXPECT_EQ(OK, one_transaction->Read(buffer.get(), 8,
- one_read_callback.callback()));
-
- EXPECT_EQ(OK, two_callback.WaitForResult());
- ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
- }
-
- void CompleteFourRequests(RequestInfoOptions options) {
- scoped_ptr<HttpNetworkTransaction> one_transaction(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
- TestCompletionCallback one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction->Start(GetRequestInfo("one.html", options),
- one_callback.callback(), BoundNetLog()));
- EXPECT_EQ(OK, one_callback.WaitForResult());
-
- HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback two_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- two_transaction.Start(GetRequestInfo("two.html", options),
- two_callback.callback(), BoundNetLog()));
-
- HttpNetworkTransaction three_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback three_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- three_transaction.Start(GetRequestInfo("three.html", options),
- three_callback.callback(),
- BoundNetLog()));
-
- HttpNetworkTransaction four_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback four_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- four_transaction.Start(GetRequestInfo("four.html", options),
- four_callback.callback(), BoundNetLog()));
-
- ExpectResponse("one.html", *one_transaction.get(), SYNCHRONOUS);
- EXPECT_EQ(OK, two_callback.WaitForResult());
- ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
- EXPECT_EQ(OK, three_callback.WaitForResult());
- ExpectResponse("three.html", three_transaction, SYNCHRONOUS);
-
- one_transaction.reset();
- EXPECT_EQ(OK, four_callback.WaitForResult());
- ExpectResponse("four.html", four_transaction, SYNCHRONOUS);
- }
-
- DeterministicMockClientSocketFactory factory_;
- ClientSocketPoolHistograms histograms_;
- MockTransportClientSocketPool pool_;
- ScopedVector<DeterministicSocketData> data_vector_;
- TestCompletionCallback callback_;
- ScopedVector<HttpRequestInfo> request_info_vector_;
-
- SimpleProxyConfigService* proxy_config_service_;
- scoped_ptr<ProxyService> proxy_service_;
- MockHostResolver mock_resolver_;
- scoped_refptr<SSLConfigService> ssl_config_;
- scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory_;
- HttpServerPropertiesImpl http_server_properties_;
- scoped_refptr<HttpNetworkSession> session_;
-};
-
-TEST_F(HttpPipelinedNetworkTransactionTest, OneRequest) {
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /test.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 9\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "test.html"),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get());
- EXPECT_EQ(ERR_IO_PENDING,
- transaction.Start(GetRequestInfo("test.html"), callback_.callback(),
- BoundNetLog()));
- EXPECT_EQ(OK, callback_.WaitForResult());
- ExpectResponse("test.html", transaction, SYNCHRONOUS);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, ReusePipeline) {
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(ASYNC, 4, "one.html"),
- MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 7, "two.html"),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- CompleteTwoRequests(0, 5);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, ReusesOnSpaceAvailable) {
- int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL);
- ClientSocketPoolManager::set_max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 7, "GET /three.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "one.html"),
- MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 8, "two.html"),
- MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"),
- MockRead(SYNCHRONOUS, 11, "three.html"),
- MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"),
- MockRead(SYNCHRONOUS, 15, "four.html"),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- CompleteFourRequests(REQUEST_DEFAULT);
-
- ClientSocketPoolManager::set_max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, WontPipelineMainResource) {
- int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL);
- ClientSocketPoolManager::set_max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 8, "GET /three.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "one.html"),
- MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 7, "two.html"),
- MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"),
- MockRead(SYNCHRONOUS, 11, "three.html"),
- MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"),
- MockRead(SYNCHRONOUS, 15, "four.html"),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- CompleteFourRequests(REQUEST_MAIN_RESOURCE);
-
- ClientSocketPoolManager::set_max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, UnknownSizeEvictsToNewPipeline) {
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"),
- MockRead(ASYNC, 2, "one.html"),
- MockRead(SYNCHRONOUS, OK, 3),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- MockWrite writes2[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads2[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "two.html"),
- };
- AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
-
- CompleteTwoRequests(0, 3);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, ConnectionCloseEvictToNewPipeline) {
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(ASYNC, 4, "one.html"),
- MockRead(SYNCHRONOUS, ERR_SOCKET_NOT_CONNECTED, 5),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- MockWrite writes2[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads2[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "two.html"),
- };
- AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
-
- CompleteTwoRequests(0, 5);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, ErrorEvictsToNewPipeline) {
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"),
- MockRead(SYNCHRONOUS, ERR_FAILED, 2),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- MockWrite writes2[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads2[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "two.html"),
- };
- AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
-
- HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction.Start(GetRequestInfo("one.html"),
- one_callback.callback(), BoundNetLog()));
- EXPECT_EQ(OK, one_callback.WaitForResult());
-
- HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback two_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- two_transaction.Start(GetRequestInfo("two.html"),
- two_callback.callback(), BoundNetLog()));
-
- scoped_refptr<IOBuffer> buffer(new IOBuffer(1));
- EXPECT_EQ(ERR_FAILED,
- one_transaction.Read(buffer.get(), 1, callback_.callback()));
- EXPECT_EQ(OK, two_callback.WaitForResult());
- ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, SendErrorEvictsToNewPipeline) {
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(ASYNC, ERR_FAILED, 0),
- };
- AddExpectedConnection(NULL, 0, writes, arraysize(writes));
-
- MockWrite writes2[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads2[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "two.html"),
- };
- AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
-
- HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction.Start(GetRequestInfo("one.html"),
- one_callback.callback(), BoundNetLog()));
-
- HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback two_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- two_transaction.Start(GetRequestInfo("two.html"),
- two_callback.callback(), BoundNetLog()));
-
- data_vector_[0]->RunFor(1);
- EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult());
-
- EXPECT_EQ(OK, two_callback.WaitForResult());
- ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, RedirectDrained) {
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /redirect.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 3, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 302 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(ASYNC, 4, "redirect"),
- MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 7, "two.html"),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpNetworkTransaction> one_transaction(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
- TestCompletionCallback one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction->Start(GetRequestInfo("redirect.html"),
- one_callback.callback(), BoundNetLog()));
- EXPECT_EQ(OK, one_callback.WaitForResult());
-
- HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback two_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- two_transaction.Start(GetRequestInfo("two.html"),
- two_callback.callback(), BoundNetLog()));
-
- one_transaction.reset();
- data_vector_[0]->RunFor(2);
- data_vector_[0]->SetStop(10);
-
- EXPECT_EQ(OK, two_callback.WaitForResult());
- ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, BasicHttpAuthentication) {
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 5, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n"
- "Authorization: auth_token\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 401 Authentication Required\r\n"),
- MockRead(SYNCHRONOUS, 2,
- "WWW-Authenticate: Basic realm=\"Secure Area\"\r\n"),
- MockRead(SYNCHRONOUS, 3, "Content-Length: 20\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "needs authentication"),
- MockRead(SYNCHRONOUS, 6, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 7, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 8, "one.html"),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- HttpAuthHandlerMock* mock_auth = new HttpAuthHandlerMock;
- std::string challenge_text = "Basic";
- HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
- challenge_text.end());
- GURL origin("localhost");
- EXPECT_TRUE(mock_auth->InitFromChallenge(&challenge,
- HttpAuth::AUTH_SERVER,
- origin,
- BoundNetLog()));
- auth_handler_factory_->AddMockHandler(mock_auth, HttpAuth::AUTH_SERVER);
-
- HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get());
- EXPECT_EQ(ERR_IO_PENDING,
- transaction.Start(GetRequestInfo("one.html"),
- callback_.callback(),
- BoundNetLog()));
- EXPECT_EQ(OK, callback_.WaitForResult());
-
- AuthCredentials credentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass"));
- EXPECT_EQ(OK, transaction.RestartWithAuth(credentials, callback_.callback()));
-
- ExpectResponse("one.html", transaction, SYNCHRONOUS);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, OldVersionDisablesPipelining) {
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /pipelined.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.0 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 14\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "pipelined.html"),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- MockWrite writes2[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads2[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(ASYNC, 3, "one.html"),
- MockRead(SYNCHRONOUS, OK, 4),
- };
- AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2));
-
- MockWrite writes3[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads3[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "two.html"),
- MockRead(SYNCHRONOUS, OK, 4),
- };
- AddExpectedConnection(reads3, arraysize(reads3), writes3, arraysize(writes3));
-
- HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction.Start(GetRequestInfo("pipelined.html"),
- one_callback.callback(), BoundNetLog()));
- EXPECT_EQ(OK, one_callback.WaitForResult());
- ExpectResponse("pipelined.html", one_transaction, SYNCHRONOUS);
-
- CompleteTwoRequests(1, 4);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, PipelinesImmediatelyIfKnownGood) {
- // The first request gets us an HTTP/1.1. The next 3 test pipelining. When the
- // 3rd request completes, we know pipelining is safe. After the first 4
- // complete, the 5th and 6th should then be immediately sent pipelined on a
- // new HttpPipelinedConnection.
- int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL);
- ClientSocketPoolManager::set_max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 4, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 7, "GET /three.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 12, "GET /four.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 16, "GET /second-pipeline-one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(SYNCHRONOUS, 17, "GET /second-pipeline-two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 3, "one.html"),
- MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 8, "two.html"),
- MockRead(SYNCHRONOUS, 9, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 10, "Content-Length: 10\r\n\r\n"),
- MockRead(SYNCHRONOUS, 11, "three.html"),
- MockRead(SYNCHRONOUS, 13, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 14, "Content-Length: 9\r\n\r\n"),
- MockRead(SYNCHRONOUS, 15, "four.html"),
- MockRead(ASYNC, 18, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 19, "Content-Length: 24\r\n\r\n"),
- MockRead(SYNCHRONOUS, 20, "second-pipeline-one.html"),
- MockRead(SYNCHRONOUS, 21, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 22, "Content-Length: 24\r\n\r\n"),
- MockRead(SYNCHRONOUS, 23, "second-pipeline-two.html"),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- CompleteFourRequests(REQUEST_DEFAULT);
-
- HttpNetworkTransaction second_one_transaction(
- DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback second_one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- second_one_transaction.Start(
- GetRequestInfo("second-pipeline-one.html"),
- second_one_callback.callback(), BoundNetLog()));
- base::MessageLoop::current()->RunUntilIdle();
-
- HttpNetworkTransaction second_two_transaction(
- DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback second_two_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- second_two_transaction.Start(
- GetRequestInfo("second-pipeline-two.html"),
- second_two_callback.callback(), BoundNetLog()));
-
- data_vector_[0]->RunFor(3);
- EXPECT_EQ(OK, second_one_callback.WaitForResult());
- data_vector_[0]->StopAfter(100);
- ExpectResponse("second-pipeline-one.html", second_one_transaction,
- SYNCHRONOUS);
- EXPECT_EQ(OK, second_two_callback.WaitForResult());
- ExpectResponse("second-pipeline-two.html", second_two_transaction,
- SYNCHRONOUS);
-
- ClientSocketPoolManager::set_max_sockets_per_group(
- HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_sockets);
-}
-
-class DataRunnerObserver : public base::MessageLoop::TaskObserver {
- public:
- DataRunnerObserver(DeterministicSocketData* data, int run_before_task)
- : data_(data),
- run_before_task_(run_before_task),
- current_task_(0) { }
-
- virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
- ++current_task_;
- if (current_task_ == run_before_task_) {
- data_->Run();
- base::MessageLoop::current()->RemoveTaskObserver(this);
- }
- }
-
- virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {}
-
- private:
- DeterministicSocketData* data_;
- int run_before_task_;
- int current_task_;
-};
-
-TEST_F(HttpPipelinedNetworkTransactionTest, OpenPipelinesWhileBinding) {
- // There was a racy crash in the pipelining code. This test recreates that
- // race. The steps are:
- // 1. The first request starts a pipeline and requests headers.
- // 2. HttpStreamFactoryImpl::Job tries to bind a pending request to a new
- // pipeline and queues a task to do so.
- // 3. Before that task runs, the first request receives its headers and
- // determines this host is probably capable of pipelining.
- // 4. All of the hosts' pipelines are notified they have capacity in a loop.
- // 5. On the first iteration, the first pipeline is opened up to accept new
- // requests and steals the request from step #2.
- // 6. The pipeline from #2 is deleted because it has no streams.
- // 7. On the second iteration, the host tries to notify the pipeline from step
- // #2 that it has capacity. This is a use-after-free.
- Initialize(false);
-
- MockWrite writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- MockWrite(ASYNC, 3, "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 4, "one.html"),
- MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
- MockRead(SYNCHRONOUS, 6, "Content-Length: 8\r\n\r\n"),
- MockRead(SYNCHRONOUS, 7, "two.html"),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- AddExpectedConnection(NULL, 0, NULL, 0);
-
- HttpNetworkTransaction one_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction.Start(GetRequestInfo("one.html"),
- one_callback.callback(), BoundNetLog()));
-
- data_vector_[0]->SetStop(2);
- data_vector_[0]->Run();
-
- HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback two_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- two_transaction.Start(GetRequestInfo("two.html"),
- two_callback.callback(), BoundNetLog()));
- // Posted tasks should be:
- // 1. MockHostResolverBase::ResolveNow
- // 2. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 1
- // 3. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 2
- //
- // We need to make sure that the response that triggers OnPipelineFeedback(OK)
- // is called in between when task #3 is scheduled and when it runs. The
- // DataRunnerObserver does that.
- DataRunnerObserver observer(data_vector_[0], 3);
- base::MessageLoop::current()->AddTaskObserver(&observer);
- data_vector_[0]->SetStop(4);
- base::MessageLoop::current()->RunUntilIdle();
- data_vector_[0]->SetStop(10);
-
- EXPECT_EQ(OK, one_callback.WaitForResult());
- ExpectResponse("one.html", one_transaction, SYNCHRONOUS);
- EXPECT_EQ(OK, two_callback.WaitForResult());
- ExpectResponse("two.html", two_transaction, SYNCHRONOUS);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, ProxyChangesWhileConnecting) {
- Initialize(false);
-
- DeterministicSocketData data(NULL, 0, NULL, 0);
- data.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
- factory_.AddSocketDataProvider(&data);
-
- DeterministicSocketData data2(NULL, 0, NULL, 0);
- data2.set_connect_data(MockConnect(ASYNC, ERR_FAILED));
- factory_.AddSocketDataProvider(&data2);
-
- HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session_.get());
- EXPECT_EQ(ERR_IO_PENDING,
- transaction.Start(GetRequestInfo("test.html"), callback_.callback(),
- BoundNetLog()));
-
- proxy_config_service_->IncrementConfigId();
-
- EXPECT_EQ(ERR_FAILED, callback_.WaitForResult());
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineSharesConnection) {
- Initialize(true);
-
- MockWrite writes[] = {
- MockWrite(ASYNC, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"
- "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 2, "Content-Length: 8\r\n\r\n"),
- MockRead(ASYNC, 3, "one.html"),
- MockRead(ASYNC, 4, "HTTP/1.1 200 OK\r\n"),
- MockRead(ASYNC, 5, "Content-Length: 8\r\n\r\n"),
- MockRead(ASYNC, 6, "two.html"),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpNetworkTransaction> one_transaction(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
- TestCompletionCallback one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction->Start(GetRequestInfo("one.html"),
- one_callback.callback(), BoundNetLog()));
-
- HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback two_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- two_transaction.Start(GetRequestInfo("two.html"),
- two_callback.callback(), BoundNetLog()));
-
- data_vector_[0]->RunFor(3); // Send + 2 lines of headers.
- EXPECT_EQ(OK, one_callback.WaitForResult());
- ExpectResponse("one.html", *one_transaction.get(), ASYNC);
- one_transaction.reset();
-
- data_vector_[0]->RunFor(2); // 2 lines of headers.
- EXPECT_EQ(OK, two_callback.WaitForResult());
- ExpectResponse("two.html", two_transaction, ASYNC);
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest,
- ForcedPipelineConnectionErrorFailsBoth) {
- Initialize(true);
-
- DeterministicSocketData data(NULL, 0, NULL, 0);
- data.set_connect_data(MockConnect(ASYNC, ERR_FAILED));
- factory_.AddSocketDataProvider(&data);
-
- scoped_ptr<HttpNetworkTransaction> one_transaction(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
- TestCompletionCallback one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction->Start(GetRequestInfo("one.html"),
- one_callback.callback(), BoundNetLog()));
-
- HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback two_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- two_transaction.Start(GetRequestInfo("two.html"),
- two_callback.callback(), BoundNetLog()));
-
- data.Run();
- EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult());
- EXPECT_EQ(ERR_FAILED, two_callback.WaitForResult());
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineEvictionIsFatal) {
- Initialize(true);
-
- MockWrite writes[] = {
- MockWrite(ASYNC, 0, "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"
- "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"),
- };
- MockRead reads[] = {
- MockRead(ASYNC, ERR_FAILED, 1),
- };
- AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
-
- scoped_ptr<HttpNetworkTransaction> one_transaction(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
- TestCompletionCallback one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction->Start(GetRequestInfo("one.html"),
- one_callback.callback(), BoundNetLog()));
-
- HttpNetworkTransaction two_transaction(DEFAULT_PRIORITY, session_.get());
- TestCompletionCallback two_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- two_transaction.Start(GetRequestInfo("two.html"),
- two_callback.callback(), BoundNetLog()));
-
- data_vector_[0]->RunFor(2);
- EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult());
- one_transaction.reset();
- EXPECT_EQ(ERR_PIPELINE_EVICTION, two_callback.WaitForResult());
-}
-
-TEST_F(HttpPipelinedNetworkTransactionTest, ForcedPipelineOrder) {
- Initialize(true);
-
- MockWrite writes[] = {
- MockWrite(ASYNC, 0,
- "GET /one.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"
- "GET /two.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"
- "GET /three.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"
- "GET /four.html HTTP/1.1\r\n"
- "Host: localhost\r\n"
- "Connection: keep-alive\r\n\r\n"
- ),
- };
- MockRead reads[] = {
- MockRead(ASYNC, ERR_FAILED, 1),
- };
- DeterministicSocketData data(
- reads, arraysize(reads), writes, arraysize(writes));
- data.set_connect_data(MockConnect(ASYNC, OK));
- factory_.AddSocketDataProvider(&data);
-
- scoped_ptr<HttpNetworkTransaction> one_transaction(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
- TestCompletionCallback one_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- one_transaction->Start(GetRequestInfo("one.html"),
- one_callback.callback(), BoundNetLog()));
-
- scoped_ptr<HttpNetworkTransaction> two_transaction(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
- TestCompletionCallback two_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- two_transaction->Start(GetRequestInfo("two.html"),
- two_callback.callback(), BoundNetLog()));
-
- scoped_ptr<HttpNetworkTransaction> three_transaction(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
- TestCompletionCallback three_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- three_transaction->Start(GetRequestInfo("three.html"),
- three_callback.callback(), BoundNetLog()));
-
- scoped_ptr<HttpNetworkTransaction> four_transaction(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
- TestCompletionCallback four_callback;
- EXPECT_EQ(ERR_IO_PENDING,
- four_transaction->Start(GetRequestInfo("four.html"),
- four_callback.callback(), BoundNetLog()));
-
- data.RunFor(3);
- EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult());
- one_transaction.reset();
- EXPECT_EQ(ERR_PIPELINE_EVICTION, two_callback.WaitForResult());
- two_transaction.reset();
- EXPECT_EQ(ERR_PIPELINE_EVICTION, three_callback.WaitForResult());
- three_transaction.reset();
- EXPECT_EQ(ERR_PIPELINE_EVICTION, four_callback.WaitForResult());
-}
-
-} // anonymous namespace
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_stream.cc b/chromium/net/http/http_pipelined_stream.cc
deleted file mode 100644
index cc267e2510e..00000000000
--- a/chromium/net/http/http_pipelined_stream.cc
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_pipelined_stream.h"
-
-#include "base/logging.h"
-#include "base/strings/stringprintf.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_pipelined_connection_impl.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_request_info.h"
-#include "net/http/http_util.h"
-
-namespace net {
-
-HttpPipelinedStream::HttpPipelinedStream(HttpPipelinedConnectionImpl* pipeline,
- int pipeline_id)
- : pipeline_(pipeline),
- pipeline_id_(pipeline_id),
- request_info_(NULL) {
-}
-
-HttpPipelinedStream::~HttpPipelinedStream() {
- pipeline_->OnStreamDeleted(pipeline_id_);
-}
-
-int HttpPipelinedStream::InitializeStream(
- const HttpRequestInfo* request_info,
- RequestPriority priority,
- const BoundNetLog& net_log,
- const CompletionCallback& callback) {
- request_info_ = request_info;
- pipeline_->InitializeParser(pipeline_id_, request_info, net_log);
- return OK;
-}
-
-
-int HttpPipelinedStream::SendRequest(const HttpRequestHeaders& headers,
- HttpResponseInfo* response,
- const CompletionCallback& callback) {
- CHECK(pipeline_id_);
- CHECK(request_info_);
- // TODO(simonjam): Proxy support will be needed here.
- const std::string path = HttpUtil::PathForRequest(request_info_->url);
- std::string request_line_ = base::StringPrintf("%s %s HTTP/1.1\r\n",
- request_info_->method.c_str(),
- path.c_str());
- return pipeline_->SendRequest(pipeline_id_, request_line_, headers, response,
- callback);
-}
-
-UploadProgress HttpPipelinedStream::GetUploadProgress() const {
- return pipeline_->GetUploadProgress(pipeline_id_);
-}
-
-int HttpPipelinedStream::ReadResponseHeaders(
- const CompletionCallback& callback) {
- return pipeline_->ReadResponseHeaders(pipeline_id_, callback);
-}
-
-const HttpResponseInfo* HttpPipelinedStream::GetResponseInfo() const {
- return pipeline_->GetResponseInfo(pipeline_id_);
-}
-
-int HttpPipelinedStream::ReadResponseBody(IOBuffer* buf, int buf_len,
- const CompletionCallback& callback) {
- return pipeline_->ReadResponseBody(pipeline_id_, buf, buf_len, callback);
-}
-
-void HttpPipelinedStream::Close(bool not_reusable) {
- pipeline_->Close(pipeline_id_, not_reusable);
-}
-
-HttpStream* HttpPipelinedStream::RenewStreamForAuth() {
- if (pipeline_->usable()) {
- return pipeline_->CreateNewStream();
- }
- return NULL;
-}
-
-bool HttpPipelinedStream::IsResponseBodyComplete() const {
- return pipeline_->IsResponseBodyComplete(pipeline_id_);
-}
-
-bool HttpPipelinedStream::CanFindEndOfResponse() const {
- return pipeline_->CanFindEndOfResponse(pipeline_id_);
-}
-
-bool HttpPipelinedStream::IsConnectionReused() const {
- return pipeline_->IsConnectionReused(pipeline_id_);
-}
-
-void HttpPipelinedStream::SetConnectionReused() {
- pipeline_->SetConnectionReused(pipeline_id_);
-}
-
-bool HttpPipelinedStream::IsConnectionReusable() const {
- return pipeline_->usable();
-}
-
-int64 HttpPipelinedStream::GetTotalReceivedBytes() const {
- return pipeline_->GetTotalReceivedBytes(pipeline_id_);
-}
-
-bool HttpPipelinedStream::GetLoadTimingInfo(
- LoadTimingInfo* load_timing_info) const {
- return pipeline_->GetLoadTimingInfo(pipeline_id_, load_timing_info);
-}
-
-void HttpPipelinedStream::GetSSLInfo(SSLInfo* ssl_info) {
- pipeline_->GetSSLInfo(pipeline_id_, ssl_info);
-}
-
-void HttpPipelinedStream::GetSSLCertRequestInfo(
- SSLCertRequestInfo* cert_request_info) {
- pipeline_->GetSSLCertRequestInfo(pipeline_id_, cert_request_info);
-}
-
-bool HttpPipelinedStream::IsSpdyHttpStream() const {
- return false;
-}
-
-void HttpPipelinedStream::Drain(HttpNetworkSession* session) {
- pipeline_->Drain(this, session);
-}
-
-void HttpPipelinedStream::SetPriority(RequestPriority priority) {
- // TODO(akalin): Plumb this through to |pipeline_| and its
- // underlying ClientSocketHandle.
-}
-
-const SSLConfig& HttpPipelinedStream::used_ssl_config() const {
- return pipeline_->used_ssl_config();
-}
-
-const ProxyInfo& HttpPipelinedStream::used_proxy_info() const {
- return pipeline_->used_proxy_info();
-}
-
-const BoundNetLog& HttpPipelinedStream::net_log() const {
- return pipeline_->net_log();
-}
-
-bool HttpPipelinedStream::was_npn_negotiated() const {
- return pipeline_->was_npn_negotiated();
-}
-
-NextProto HttpPipelinedStream::protocol_negotiated() const {
- return pipeline_->protocol_negotiated();
-}
-
-} // namespace net
diff --git a/chromium/net/http/http_pipelined_stream.h b/chromium/net/http/http_pipelined_stream.h
deleted file mode 100644
index 7a853abc1a7..00000000000
--- a/chromium/net/http/http_pipelined_stream.h
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2012 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_HTTP_HTTP_PIPELINED_STREAM_H_
-#define NET_HTTP_HTTP_PIPELINED_STREAM_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "net/base/net_log.h"
-#include "net/http/http_stream.h"
-#include "net/socket/ssl_client_socket.h"
-
-namespace net {
-
-class BoundNetLog;
-class HttpPipelinedConnectionImpl;
-class HttpResponseInfo;
-class HttpRequestHeaders;
-struct HttpRequestInfo;
-class IOBuffer;
-class ProxyInfo;
-struct SSLConfig;
-
-// HttpPipelinedStream is the pipelined implementation of HttpStream. It has
-// very little code in it. Instead, it serves as the client's interface to the
-// pipelined connection, where all the work happens.
-//
-// In the case of pipelining failures, these functions may return
-// ERR_PIPELINE_EVICTION. In that case, the client should retry the HTTP
-// request without pipelining.
-class HttpPipelinedStream : public HttpStream {
- public:
- HttpPipelinedStream(HttpPipelinedConnectionImpl* pipeline,
- int pipeline_id);
- virtual ~HttpPipelinedStream();
-
- // HttpStream methods:
- virtual int InitializeStream(const HttpRequestInfo* request_info,
- RequestPriority priority,
- const BoundNetLog& net_log,
- const CompletionCallback& callback) OVERRIDE;
-
- virtual int SendRequest(const HttpRequestHeaders& headers,
- HttpResponseInfo* response,
- const CompletionCallback& callback) OVERRIDE;
-
- virtual UploadProgress GetUploadProgress() const OVERRIDE;
-
- virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE;
-
- virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE;
-
- virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
- const CompletionCallback& callback) OVERRIDE;
-
- virtual void Close(bool not_reusable) OVERRIDE;
-
- virtual HttpStream* RenewStreamForAuth() OVERRIDE;
-
- virtual bool IsResponseBodyComplete() const OVERRIDE;
-
- virtual bool CanFindEndOfResponse() const OVERRIDE;
-
- virtual bool IsConnectionReused() const OVERRIDE;
-
- virtual void SetConnectionReused() OVERRIDE;
-
- virtual bool IsConnectionReusable() const OVERRIDE;
-
- virtual int64 GetTotalReceivedBytes() const OVERRIDE;
-
- virtual bool GetLoadTimingInfo(
- LoadTimingInfo* load_timing_info) const OVERRIDE;
-
- virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;
-
- virtual void GetSSLCertRequestInfo(
- SSLCertRequestInfo* cert_request_info) OVERRIDE;
-
- virtual bool IsSpdyHttpStream() const OVERRIDE;
-
- virtual void Drain(HttpNetworkSession* session) OVERRIDE;
-
- virtual void SetPriority(RequestPriority priority) OVERRIDE;
-
- // The SSLConfig used to establish this stream's pipeline.
- const SSLConfig& used_ssl_config() const;
-
- // The ProxyInfo used to establish this this stream's pipeline.
- const ProxyInfo& used_proxy_info() const;
-
- // The BoundNetLog of this stream's pipelined connection.
- const BoundNetLog& net_log() const;
-
- // True if this stream's pipeline was NPN negotiated.
- bool was_npn_negotiated() const;
-
- // Protocol negotiated with the server.
- NextProto protocol_negotiated() const;
-
- private:
- HttpPipelinedConnectionImpl* pipeline_;
-
- int pipeline_id_;
-
- const HttpRequestInfo* request_info_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpPipelinedStream);
-};
-
-} // namespace net
-
-#endif // NET_HTTP_HTTP_PIPELINED_STREAM_H_
diff --git a/chromium/net/http/http_proxy_client_socket.cc b/chromium/net/http/http_proxy_client_socket.cc
index 7037616ae5a..3d9eadd4835 100644
--- a/chromium/net/http/http_proxy_client_socket.cc
+++ b/chromium/net/http/http_proxy_client_socket.cc
@@ -237,11 +237,11 @@ int HttpProxyClientSocket::Write(IOBuffer* buf, int buf_len,
return transport_->socket()->Write(buf, buf_len, callback);
}
-bool HttpProxyClientSocket::SetReceiveBufferSize(int32 size) {
+int HttpProxyClientSocket::SetReceiveBufferSize(int32 size) {
return transport_->socket()->SetReceiveBufferSize(size);
}
-bool HttpProxyClientSocket::SetSendBufferSize(int32 size) {
+int HttpProxyClientSocket::SetSendBufferSize(int32 size) {
return transport_->socket()->SetSendBufferSize(size);
}
@@ -276,7 +276,7 @@ int HttpProxyClientSocket::PrepareForAuthRestart() {
int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) {
if (keep_alive && transport_->socket()->IsConnectedAndIdle()) {
next_state_ = STATE_GENERATE_AUTH_TOKEN;
- transport_->set_is_reused(true);
+ transport_->set_reuse_type(ClientSocketHandle::REUSED_IDLE);
} else {
// This assumes that the underlying transport socket is a TCP socket,
// since only TCP sockets are restartable.
diff --git a/chromium/net/http/http_proxy_client_socket.h b/chromium/net/http/http_proxy_client_socket.h
index fca054f9c44..a2682c505b1 100644
--- a/chromium/net/http/http_proxy_client_socket.h
+++ b/chromium/net/http/http_proxy_client_socket.h
@@ -82,8 +82,8 @@ class HttpProxyClientSocket : public ProxyClientSocket {
virtual int Write(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) OVERRIDE;
- virtual bool SetReceiveBufferSize(int32 size) OVERRIDE;
- virtual bool SetSendBufferSize(int32 size) OVERRIDE;
+ virtual int SetReceiveBufferSize(int32 size) OVERRIDE;
+ virtual int SetSendBufferSize(int32 size) OVERRIDE;
virtual int GetPeerAddress(IPEndPoint* address) const OVERRIDE;
virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE;
diff --git a/chromium/net/http/http_proxy_client_socket_pool.cc b/chromium/net/http/http_proxy_client_socket_pool.cc
index 8d691b7dd80..829a5e78314 100644
--- a/chromium/net/http/http_proxy_client_socket_pool.cc
+++ b/chromium/net/http/http_proxy_client_socket_pool.cc
@@ -206,7 +206,7 @@ int HttpProxyConnectJob::DoSSLConnect() {
if (params_->tunnel()) {
SpdySessionKey key(params_->destination().host_port_pair(),
ProxyServer::Direct(),
- kPrivacyModeDisabled);
+ PRIVACY_MODE_DISABLED);
if (params_->spdy_session_pool()->FindAvailableSession(key, net_log())) {
using_spdy_ = true;
next_state_ = STATE_SPDY_PROXY_CREATE_STREAM;
@@ -237,6 +237,13 @@ int HttpProxyConnectJob::DoSSLConnectComplete(int result) {
return ERR_PROXY_CERTIFICATE_INVALID;
}
}
+ // A SPDY session to the proxy completed prior to resolving the proxy
+ // hostname. Surface this error, and allow the delegate to retry.
+ // See crbug.com/334413.
+ if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) {
+ DCHECK(!transport_socket_handle_->socket());
+ return ERR_SPDY_SESSION_ALREADY_EXISTS;
+ }
if (result < 0) {
if (transport_socket_handle_->socket())
transport_socket_handle_->socket()->Disconnect();
@@ -302,7 +309,7 @@ int HttpProxyConnectJob::DoSpdyProxyCreateStream() {
DCHECK(params_->tunnel());
SpdySessionKey key(params_->destination().host_port_pair(),
ProxyServer::Direct(),
- kPrivacyModeDisabled);
+ PRIVACY_MODE_DISABLED);
SpdySessionPool* spdy_pool = params_->spdy_session_pool();
base::WeakPtr<SpdySession> spdy_session =
spdy_pool->FindAvailableSession(key, net_log());
@@ -315,11 +322,11 @@ int HttpProxyConnectJob::DoSpdyProxyCreateStream() {
}
} else {
// Create a session direct to the proxy itself
- int rv = spdy_pool->CreateAvailableSessionFromSocket(
- key, transport_socket_handle_.Pass(),
- net_log(), OK, &spdy_session, /*using_ssl_*/ true);
- if (rv < 0)
- return rv;
+ spdy_session =
+ spdy_pool->CreateAvailableSessionFromSocket(
+ key, transport_socket_handle_.Pass(),
+ net_log(), OK, /*using_ssl_*/ true);
+ DCHECK(spdy_session);
}
next_state_ = STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE;
diff --git a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
index a70fe6ab067..d7955d2c058 100644
--- a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -100,8 +100,8 @@ class HttpProxyClientSocketPoolTest
}
void AddAuthToCache() {
- const base::string16 kFoo(ASCIIToUTF16("foo"));
- const base::string16 kBar(ASCIIToUTF16("bar"));
+ const base::string16 kFoo(base::ASCIIToUTF16("foo"));
+ const base::string16 kBar(base::ASCIIToUTF16("bar"));
GURL proxy_url(GetParam().proxy_type == HTTP ?
(std::string("http://") + kHttpProxyHost) :
(std::string("https://") + kHttpsProxyHost));
@@ -135,7 +135,7 @@ class HttpProxyClientSocketPoolTest
NULL,
HostPortPair(kHttpsProxyHost, 443),
SSLConfig(),
- kPrivacyModeDisabled,
+ PRIVACY_MODE_DISABLED,
0,
false,
false);
@@ -248,12 +248,9 @@ INSTANTIATE_TEST_CASE_P(
HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY31),
HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY31),
HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY31),
- HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY4a2),
- HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY4a2),
- HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY4a2),
- HttpProxyClientSocketPoolTestParams(HTTP, kProtoHTTP2Draft04),
- HttpProxyClientSocketPoolTestParams(HTTPS, kProtoHTTP2Draft04),
- HttpProxyClientSocketPoolTestParams(SPDY, kProtoHTTP2Draft04)));
+ HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY4),
+ HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY4),
+ HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY4)));
TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) {
Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
diff --git a/chromium/net/http/http_request_headers.cc b/chromium/net/http/http_request_headers.cc
index 8c9c4289336..9348e3e2778 100644
--- a/chromium/net/http/http_request_headers.cc
+++ b/chromium/net/http/http_request_headers.cc
@@ -9,20 +9,9 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
+#include "net/http/http_log_util.h"
#include "net/http/http_util.h"
-namespace {
-
-bool ShouldShowHttpHeaderValue(const std::string& header_name) {
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
- if (header_name == "Proxy-Authorization")
- return false;
-#endif
- return true;
-}
-
-} // namespace
-
namespace net {
const char HttpRequestHeaders::kGetMethod[] = "GET";
@@ -197,17 +186,17 @@ std::string HttpRequestHeaders::ToString() const {
base::Value* HttpRequestHeaders::NetLogCallback(
const std::string* request_line,
- NetLog::LogLevel /* log_level */) const {
+ NetLog::LogLevel log_level) const {
base::DictionaryValue* dict = new base::DictionaryValue();
dict->SetString("line", *request_line);
base::ListValue* headers = new base::ListValue();
for (HeaderVector::const_iterator it = headers_.begin();
it != headers_.end(); ++it) {
+ std::string log_value = ElideHeaderValueForNetLog(
+ log_level, it->key, it->value);
headers->Append(new base::StringValue(
base::StringPrintf("%s: %s",
- it->key.c_str(),
- (ShouldShowHttpHeaderValue(it->key) ?
- it->value.c_str() : "[elided]"))));
+ it->key.c_str(), log_value.c_str())));
}
dict->Set("headers", headers);
return dict;
diff --git a/chromium/net/http/http_request_info.cc b/chromium/net/http/http_request_info.cc
index bffc96ccfae..794aa1c3a7c 100644
--- a/chromium/net/http/http_request_info.cc
+++ b/chromium/net/http/http_request_info.cc
@@ -10,7 +10,7 @@ HttpRequestInfo::HttpRequestInfo()
: upload_data_stream(NULL),
load_flags(0),
motivation(NORMAL_MOTIVATION),
- privacy_mode(kPrivacyModeDisabled) {
+ privacy_mode(PRIVACY_MODE_DISABLED) {
}
HttpRequestInfo::~HttpRequestInfo() {}
diff --git a/chromium/net/http/http_response_body_drainer.cc b/chromium/net/http/http_response_body_drainer.cc
index a1ba35ad31e..91dbbf70984 100644
--- a/chromium/net/http/http_response_body_drainer.cc
+++ b/chromium/net/http/http_response_body_drainer.cc
@@ -14,8 +14,7 @@
namespace net {
HttpResponseBodyDrainer::HttpResponseBodyDrainer(HttpStreamBase* stream)
- : read_size_(0),
- stream_(stream),
+ : stream_(stream),
next_state_(STATE_NONE),
total_read_(0),
session_(NULL) {}
@@ -23,25 +22,7 @@ HttpResponseBodyDrainer::HttpResponseBodyDrainer(HttpStreamBase* stream)
HttpResponseBodyDrainer::~HttpResponseBodyDrainer() {}
void HttpResponseBodyDrainer::Start(HttpNetworkSession* session) {
- StartWithSize(session, kDrainBodyBufferSize);
-}
-
-void HttpResponseBodyDrainer::StartWithSize(HttpNetworkSession* session,
- int num_bytes_to_drain) {
- DCHECK_LE(0, num_bytes_to_drain);
- // TODO(simonjam): Consider raising this limit if we're pipelining. If we have
- // a bunch of responses in the pipeline, we should be less willing to give up
- // while draining.
- if (num_bytes_to_drain > kDrainBodyBufferSize) {
- Finish(ERR_RESPONSE_BODY_TOO_BIG_TO_DRAIN);
- return;
- } else if (num_bytes_to_drain == 0) {
- Finish(OK);
- return;
- }
-
- read_size_ = num_bytes_to_drain;
- read_buf_ = new IOBuffer(read_size_);
+ read_buf_ = new IOBuffer(kDrainBodyBufferSize);
next_state_ = STATE_DRAIN_RESPONSE_BODY;
int rv = DoLoop(OK);
@@ -88,7 +69,7 @@ int HttpResponseBodyDrainer::DoDrainResponseBody() {
return stream_->ReadResponseBody(
read_buf_.get(),
- read_size_ - total_read_,
+ kDrainBodyBufferSize - total_read_,
base::Bind(&HttpResponseBodyDrainer::OnIOComplete,
base::Unretained(this)));
}
diff --git a/chromium/net/http/http_response_body_drainer.h b/chromium/net/http/http_response_body_drainer.h
index 284d08a99cd..5c7713e254b 100644
--- a/chromium/net/http/http_response_body_drainer.h
+++ b/chromium/net/http/http_response_body_drainer.h
@@ -35,9 +35,6 @@ class NET_EXPORT_PRIVATE HttpResponseBodyDrainer {
// doesn't complete immediately, it will add itself to |session|.
void Start(HttpNetworkSession* session);
- // As above, but stop reading once |num_bytes_to_drain| has been reached.
- void StartWithSize(HttpNetworkSession* session, int num_bytes_to_drain);
-
private:
enum State {
STATE_DRAIN_RESPONSE_BODY,
@@ -54,7 +51,6 @@ class NET_EXPORT_PRIVATE HttpResponseBodyDrainer {
void OnTimerFired();
void Finish(int result);
- int read_size_;
scoped_refptr<IOBuffer> read_buf_;
const scoped_ptr<HttpStreamBase> stream_;
State next_state_;
diff --git a/chromium/net/http/http_response_body_drainer_unittest.cc b/chromium/net/http/http_response_body_drainer_unittest.cc
index f587b908529..42efa57f919 100644
--- a/chromium/net/http/http_response_body_drainer_unittest.cc
+++ b/chromium/net/http/http_response_body_drainer_unittest.cc
@@ -93,9 +93,6 @@ class MockHttpStream : public HttpStream {
virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
return ERR_UNEXPECTED;
}
- virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE {
- return NULL;
- }
virtual bool CanFindEndOfResponse() const OVERRIDE { return true; }
virtual bool IsConnectionReused() const OVERRIDE { return false; }
@@ -305,22 +302,6 @@ TEST_F(HttpResponseBodyDrainerTest, DrainBodyTooLarge) {
EXPECT_TRUE(result_waiter_.WaitForResult());
}
-TEST_F(HttpResponseBodyDrainerTest, StartBodyTooLarge) {
- int too_many_chunks =
- HttpResponseBodyDrainer::kDrainBodyBufferSize / kMagicChunkSize;
- too_many_chunks += 1; // Now it's too large.
-
- mock_stream_->set_num_chunks(0);
- drainer_->StartWithSize(session_.get(), too_many_chunks * kMagicChunkSize);
- EXPECT_TRUE(result_waiter_.WaitForResult());
-}
-
-TEST_F(HttpResponseBodyDrainerTest, StartWithNothingToDo) {
- mock_stream_->set_num_chunks(0);
- drainer_->StartWithSize(session_.get(), 0);
- EXPECT_FALSE(result_waiter_.WaitForResult());
-}
-
} // namespace
} // namespace net
diff --git a/chromium/net/http/http_response_headers.cc b/chromium/net/http/http_response_headers.cc
index 289facd4f9e..b7ef98a5980 100644
--- a/chromium/net/http/http_response_headers.cc
+++ b/chromium/net/http/http_response_headers.cc
@@ -11,6 +11,7 @@
#include <algorithm>
+#include "base/format_macros.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/pickle.h"
@@ -21,6 +22,8 @@
#include "base/time/time.h"
#include "base/values.h"
#include "net/base/escape.h"
+#include "net/http/http_byte_range.h"
+#include "net/http/http_log_util.h"
#include "net/http/http_util.h"
using base::StringPiece;
@@ -113,16 +116,10 @@ void CheckDoesNotHaveEmbededNulls(const std::string& str) {
CHECK(str.find('\0') == std::string::npos);
}
-bool ShouldShowHttpHeaderValue(const std::string& header_name) {
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
- if (header_name == "Proxy-Authenticate")
- return false;
-#endif
- return true;
-}
-
} // namespace
+const char HttpResponseHeaders::kContentRange[] = "Content-Range";
+
struct HttpResponseHeaders::ParsedHeader {
// A header "continuation" contains only a subsequent value for the
// preceding header. (Header values are comma separated.)
@@ -372,6 +369,32 @@ void HttpResponseHeaders::ReplaceStatusLine(const std::string& new_status) {
MergeWithHeaders(new_raw_headers, empty_to_remove);
}
+void HttpResponseHeaders::UpdateWithNewRange(
+ const HttpByteRange& byte_range,
+ int64 resource_size,
+ bool replace_status_line) {
+ DCHECK(byte_range.IsValid());
+ DCHECK(byte_range.HasFirstBytePosition());
+ DCHECK(byte_range.HasLastBytePosition());
+
+ const char kLengthHeader[] = "Content-Length";
+ const char kRangeHeader[] = "Content-Range";
+
+ RemoveHeader(kLengthHeader);
+ RemoveHeader(kRangeHeader);
+
+ int64 start = byte_range.first_byte_position();
+ int64 end = byte_range.last_byte_position();
+ int64 range_len = end - start + 1;
+
+ if (replace_status_line)
+ ReplaceStatusLine("HTTP/1.1 206 Partial Content");
+
+ AddHeader(base::StringPrintf("%s: bytes %" PRId64 "-%" PRId64 "/%" PRId64,
+ kRangeHeader, start, end, resource_size));
+ AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, range_len));
+}
+
void HttpResponseHeaders::Parse(const std::string& raw_input) {
raw_headers_.reserve(raw_input.size());
@@ -827,7 +850,7 @@ void HttpResponseHeaders::AddChallengeHeaders(HeaderSet* result) {
}
void HttpResponseHeaders::AddHopContentRangeHeaders(HeaderSet* result) {
- result->insert("content-range");
+ result->insert(kContentRange);
}
void HttpResponseHeaders::AddSecurityStateHeaders(HeaderSet* result) {
@@ -894,7 +917,8 @@ bool HttpResponseHeaders::IsRedirectResponseCode(int response_code) {
return (response_code == 301 ||
response_code == 302 ||
response_code == 303 ||
- response_code == 307);
+ response_code == 307 ||
+ response_code == 308);
}
// From RFC 2616 section 13.2.4:
@@ -993,6 +1017,9 @@ TimeDelta HttpResponseHeaders::GetFreshnessLifetime(
// time, if, based solely on the origin server's Expires or max-age value,
// the cached response is stale.)
//
+ // https://datatracker.ietf.org/doc/draft-reschke-http-status-308/ is an
+ // experimental RFC that adds 308 permanent redirect as well, for which "any
+ // future references ... SHOULD use one of the returned URIs."
if ((response_code_ == 200 || response_code_ == 203 ||
response_code_ == 206) &&
!HasHeaderValue("cache-control", "must-revalidate")) {
@@ -1006,8 +1033,10 @@ TimeDelta HttpResponseHeaders::GetFreshnessLifetime(
}
// These responses are implicitly fresh (unless otherwise overruled):
- if (response_code_ == 300 || response_code_ == 301 || response_code_ == 410)
- return TimeDelta::FromMicroseconds(kint64max);
+ if (response_code_ == 300 || response_code_ == 301 || response_code_ == 308 ||
+ response_code_ == 410) {
+ return TimeDelta::Max();
+ }
return TimeDelta(); // not fresh
}
@@ -1207,7 +1236,7 @@ bool HttpResponseHeaders::GetContentRange(int64* first_byte_position,
void* iter = NULL;
std::string content_range_spec;
*first_byte_position = *last_byte_position = *instance_length = -1;
- if (!EnumerateHeader(&iter, "content-range", &content_range_spec))
+ if (!EnumerateHeader(&iter, kContentRange, &content_range_spec))
return false;
// If the header value is empty, we have an invalid header.
@@ -1308,7 +1337,7 @@ bool HttpResponseHeaders::GetContentRange(int64* first_byte_position,
}
base::Value* HttpResponseHeaders::NetLogCallback(
- NetLog::LogLevel /* log_level */) const {
+ NetLog::LogLevel log_level) const {
base::DictionaryValue* dict = new base::DictionaryValue();
base::ListValue* headers = new base::ListValue();
headers->Append(new base::StringValue(GetStatusLine()));
@@ -1316,12 +1345,10 @@ base::Value* HttpResponseHeaders::NetLogCallback(
std::string name;
std::string value;
while (EnumerateHeaderLines(&iterator, &name, &value)) {
+ std::string log_value = ElideHeaderValueForNetLog(log_level, name, value);
headers->Append(
new base::StringValue(
- base::StringPrintf("%s: %s",
- name.c_str(),
- (ShouldShowHttpHeaderValue(name) ?
- value.c_str() : "[elided]"))));
+ base::StringPrintf("%s: %s", name.c_str(), log_value.c_str())));
}
dict->Set("headers", headers);
return dict;
@@ -1364,59 +1391,4 @@ bool HttpResponseHeaders::IsChunkEncoded() const {
HasHeaderValue("Transfer-Encoding", "chunked");
}
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
-bool HttpResponseHeaders::GetChromeProxyBypassDuration(
- const std::string& action_prefix,
- base::TimeDelta* duration) const {
- void* iter = NULL;
- std::string value;
- std::string name = "chrome-proxy";
-
- while (EnumerateHeader(&iter, name, &value)) {
- if (value.size() > action_prefix.size()) {
- if (LowerCaseEqualsASCII(value.begin(),
- value.begin() + action_prefix.size(),
- action_prefix.c_str())) {
- int64 seconds;
- if (!base::StringToInt64(
- StringPiece(value.begin() + action_prefix.size(), value.end()),
- &seconds) || seconds < 0) {
- continue; // In case there is a well formed instruction.
- }
- *duration = TimeDelta::FromSeconds(seconds);
- return true;
- }
- }
- }
- return false;
-}
-
-bool HttpResponseHeaders::GetChromeProxyInfo(
- ChromeProxyInfo* proxy_info) const {
- DCHECK(proxy_info);
- proxy_info->bypass_all = false;
- proxy_info->bypass_duration = base::TimeDelta();
-
- // Support header of the form Chrome-Proxy: bypass|block=<duration>, where
- // <duration> is the number of seconds to wait before retrying
- // the proxy. If the duration is 0, then the default proxy retry delay
- // (specified in |ProxyList::UpdateRetryInfoOnFallback|) will be used.
- // 'bypass' instructs Chrome to bypass the currently connected Chrome proxy,
- // whereas 'block' instructs Chrome to bypass all available Chrome proxies.
-
- // 'block' takes precedence over 'bypass', so look for it first.
- // TODO(bengr): Reduce checks for 'block' and 'bypass' to a single loop.
- if (GetChromeProxyBypassDuration("block=", &proxy_info->bypass_duration)) {
- proxy_info->bypass_all = true;
- return true;
- }
-
- // Next, look for 'bypass'.
- if (GetChromeProxyBypassDuration("bypass=", &proxy_info->bypass_duration))
- return true;
-
- return false;
-}
-#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
-
} // namespace net
diff --git a/chromium/net/http/http_response_headers.h b/chromium/net/http/http_response_headers.h
index e54ac5df669..2d306c95ca0 100644
--- a/chromium/net/http/http_response_headers.h
+++ b/chromium/net/http/http_response_headers.h
@@ -26,6 +26,8 @@ class TimeDelta;
namespace net {
+class HttpByteRange;
+
// HttpResponseHeaders: parses and holds HTTP response headers.
class NET_EXPORT HttpResponseHeaders
: public base::RefCountedThreadSafe<HttpResponseHeaders> {
@@ -41,6 +43,8 @@ class NET_EXPORT HttpResponseHeaders
static const PersistOptions PERSIST_SANS_RANGES = 1 << 4;
static const PersistOptions PERSIST_SANS_SECURITY_STATE = 1 << 5;
+ static const char kContentRange[];
+
// Parses the given raw_headers. raw_headers should be formatted thus:
// includes the http status response line, each line is \0-terminated, and
// it's terminated by an empty line (ie, 2 \0s in a row).
@@ -81,6 +85,15 @@ class NET_EXPORT HttpResponseHeaders
// not have any EOL).
void ReplaceStatusLine(const std::string& new_status);
+ // Updates headers (Content-Length and Content-Range) in the |headers| to
+ // include the right content length and range for |byte_range|. This also
+ // updates HTTP status line if |replace_status_line| is true.
+ // |byte_range| must have a valid, bounded range (i.e. coming from a valid
+ // response or should be usable for a response).
+ void UpdateWithNewRange(const HttpByteRange& byte_range,
+ int64 resource_size,
+ bool replace_status_line);
+
// Creates a normalized header string. The output will be formatted exactly
// like so:
// HTTP/<version> <status_code> <status_text>\n
@@ -250,28 +263,6 @@ class NET_EXPORT HttpResponseHeaders
// Returns true if the response is chunk-encoded.
bool IsChunkEncoded() const;
-#if defined (SPDY_PROXY_AUTH_ORIGIN)
- // Contains instructions contained in the Chrome-Proxy header.
- struct ChromeProxyInfo {
- ChromeProxyInfo() : bypass_all(false) {}
-
- // True if Chrome should bypass all available Chrome proxies. False if only
- // the currently connected Chrome proxy should be bypassed.
- bool bypass_all;
-
- // Amount of time to bypass the Chrome proxy or proxies.
- base::TimeDelta bypass_duration;
- };
-
- // Returns true if the Chrome-Proxy header is present and contains a bypass
- // delay. Sets |proxy_info->bypass_duration| to the specified delay if greater
- // than 0, and to 0 otherwise to indicate that the default proxy delay
- // (as specified in |ProxyList::UpdateRetryInfoOnFallback|) should be used.
- // If all available Chrome proxies should by bypassed, |bypass_all| is set to
- // true. |proxy_info| must be non-NULL.
- bool GetChromeProxyInfo(ChromeProxyInfo* proxy_info) const;
-#endif
-
// Creates a Value for use with the NetLog containing the response headers.
base::Value* NetLogCallback(NetLog::LogLevel log_level) const;
@@ -370,13 +361,6 @@ class NET_EXPORT HttpResponseHeaders
// Adds the set of transport security state headers.
static void AddSecurityStateHeaders(HeaderSet* header_names);
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
- // Searches for the specified Chrome-Proxy action, and if present interprets
- // its value as a duration in seconds.
- bool GetChromeProxyBypassDuration(const std::string& action_prefix,
- base::TimeDelta* duration) const;
-#endif
-
// We keep a list of ParsedHeader objects. These tell us where to locate the
// header-value pairs within raw_headers_.
HeaderList parsed_;
diff --git a/chromium/net/http/http_response_headers_unittest.cc b/chromium/net/http/http_response_headers_unittest.cc
index 4be74783b74..cc236d183e8 100644
--- a/chromium/net/http/http_response_headers_unittest.cc
+++ b/chromium/net/http/http_response_headers_unittest.cc
@@ -9,6 +9,7 @@
#include "base/pickle.h"
#include "base/time/time.h"
#include "base/values.h"
+#include "net/http/http_byte_range.h"
#include "net/http/http_response_headers.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -807,6 +808,11 @@ TEST(HttpResponseHeadersTest, RequiresValidation) {
"\n",
false
},
+ // another cached permanent redirect
+ { "HTTP/1.1 308 Permanent Redirect\n"
+ "\n",
+ false
+ },
// cached redirect: not reusable even though by default it would be
{ "HTTP/1.1 300 Multiple Choices\n"
"Cache-Control: no-cache\n"
@@ -1851,6 +1857,58 @@ TEST(HttpResponseHeadersTest, ReplaceStatus) {
}
}
+TEST(HttpResponseHeadersTest, UpdateWithNewRange) {
+ const struct {
+ const char* orig_headers;
+ const char* expected_headers;
+ const char* expected_headers_with_replaced_status;
+ } tests[] = {
+ { "HTTP/1.1 200 OK\n"
+ "Content-Length: 450\n",
+
+ "HTTP/1.1 200 OK\n"
+ "Content-Range: bytes 3-5/450\n"
+ "Content-Length: 3\n",
+
+ "HTTP/1.1 206 Partial Content\n"
+ "Content-Range: bytes 3-5/450\n"
+ "Content-Length: 3\n",
+ },
+ { "HTTP/1.1 200 OK\n"
+ "Content-Length: 5\n",
+
+ "HTTP/1.1 200 OK\n"
+ "Content-Range: bytes 3-5/5\n"
+ "Content-Length: 3\n",
+
+ "HTTP/1.1 206 Partial Content\n"
+ "Content-Range: bytes 3-5/5\n"
+ "Content-Length: 3\n",
+ },
+ };
+ const net::HttpByteRange range = net::HttpByteRange::Bounded(3, 5);
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ std::string orig_headers(tests[i].orig_headers);
+ std::replace(orig_headers.begin(), orig_headers.end(), '\n', '\0');
+ scoped_refptr<net::HttpResponseHeaders> parsed(
+ new net::HttpResponseHeaders(orig_headers + '\0'));
+ int64 content_size = parsed->GetContentLength();
+ std::string resulting_headers;
+
+ // Update headers without replacing status line.
+ parsed->UpdateWithNewRange(range, content_size, false);
+ parsed->GetNormalizedHeaders(&resulting_headers);
+ EXPECT_EQ(std::string(tests[i].expected_headers), resulting_headers);
+
+ // Replace status line too.
+ parsed->UpdateWithNewRange(range, content_size, true);
+ parsed->GetNormalizedHeaders(&resulting_headers);
+ EXPECT_EQ(std::string(tests[i].expected_headers_with_replaced_status),
+ resulting_headers);
+ }
+}
+
TEST(HttpResponseHeadersTest, ToNetLogParamAndBackAgain) {
std::string headers("HTTP/1.1 404\n"
"Content-Length: 450\n"
@@ -1877,156 +1935,3 @@ TEST(HttpResponseHeadersTest, ToNetLogParamAndBackAgain) {
parsed->GetNormalizedHeaders(&normalized_recreated);
EXPECT_EQ(normalized_parsed, normalized_recreated);
}
-
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
-TEST(HttpResponseHeadersTest, GetProxyBypassInfo) {
- const struct {
- const char* headers;
- bool expected_result;
- int64 expected_retry_delay;
- bool expected_bypass_all;
- } tests[] = {
- { "HTTP/1.1 200 OK\n"
- "Content-Length: 999\n",
- false,
- 0,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Content-Length: 999\n",
- false,
- 0,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: bypass=86400\n"
- "Content-Length: 999\n",
- true,
- 86400,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: bypass=0\n"
- "Content-Length: 999\n",
- true,
- 0,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: bypass=-1\n"
- "Content-Length: 999\n",
- false,
- 0,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: bypass=xyz\n"
- "Content-Length: 999\n",
- false,
- 0,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: bypass\n"
- "Content-Length: 999\n",
- false,
- 0,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: foo=abc, bypass=86400\n"
- "Content-Length: 999\n",
- true,
- 86400,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: bypass=86400, bar=abc\n"
- "Content-Length: 999\n",
- true,
- 86400,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: bypass=3600\n"
- "Chrome-Proxy: bypass=86400\n"
- "Content-Length: 999\n",
- true,
- 3600,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: bypass=3600, bypass=86400\n"
- "Content-Length: 999\n",
- true,
- 3600,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: bypass=, bypass=86400\n"
- "Content-Length: 999\n",
- true,
- 86400,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: bypass\n"
- "Chrome-Proxy: bypass=86400\n"
- "Content-Length: 999\n",
- true,
- 86400,
- false,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: block=, block=3600\n"
- "Content-Length: 999\n",
- true,
- 3600,
- true,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: keep-alive\n"
- "Chrome-Proxy: bypass=86400, block=3600\n"
- "Content-Length: 999\n",
- true,
- 3600,
- true,
- },
- { "HTTP/1.1 200 OK\n"
- "connection: proxy-bypass\n"
- "Chrome-Proxy: block=, bypass=86400\n"
- "Content-Length: 999\n",
- true,
- 86400,
- false,
- },
- };
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
- std::string headers(tests[i].headers);
- HeadersToRaw(&headers);
- scoped_refptr<net::HttpResponseHeaders> parsed(
- new net::HttpResponseHeaders(headers));
-
- net::HttpResponseHeaders::ChromeProxyInfo chrome_proxy_info;
- EXPECT_EQ(tests[i].expected_result,
- parsed->GetChromeProxyInfo(&chrome_proxy_info));
- EXPECT_EQ(tests[i].expected_retry_delay,
- chrome_proxy_info.bypass_duration.InSeconds());
- EXPECT_EQ(tests[i].expected_bypass_all,
- chrome_proxy_info.bypass_all);
- }
-}
-#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
diff --git a/chromium/net/http/http_response_info.cc b/chromium/net/http/http_response_info.cc
index 4f9e014cfb2..83896736a12 100644
--- a/chromium/net/http/http_response_info.cc
+++ b/chromium/net/http/http_response_info.cc
@@ -113,6 +113,7 @@ HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs)
was_fetched_via_spdy(rhs.was_fetched_via_spdy),
was_npn_negotiated(rhs.was_npn_negotiated),
was_fetched_via_proxy(rhs.was_fetched_via_proxy),
+ proxy_server(rhs.proxy_server),
did_use_http_auth(rhs.did_use_http_auth),
socket_address(rhs.socket_address),
npn_negotiated_protocol(rhs.npn_negotiated_protocol),
@@ -135,6 +136,7 @@ HttpResponseInfo& HttpResponseInfo::operator=(const HttpResponseInfo& rhs) {
server_data_unavailable = rhs.server_data_unavailable;
network_accessed = rhs.network_accessed;
was_fetched_via_spdy = rhs.was_fetched_via_spdy;
+ proxy_server = rhs.proxy_server;
was_npn_negotiated = rhs.was_npn_negotiated;
was_fetched_via_proxy = rhs.was_fetched_via_proxy;
did_use_http_auth = rhs.did_use_http_auth;
@@ -340,8 +342,8 @@ void HttpResponseInfo::Persist(Pickle* pickle,
for (SignedCertificateTimestampAndStatusList::const_iterator it =
ssl_info.signed_certificate_timestamps.begin(); it !=
ssl_info.signed_certificate_timestamps.end(); ++it) {
- it->sct_->Persist(pickle);
- pickle->WriteUInt16(it->status_);
+ it->sct->Persist(pickle);
+ pickle->WriteUInt16(it->status);
}
}
}
@@ -367,10 +369,8 @@ HttpResponseInfo::ConnectionInfo HttpResponseInfo::ConnectionInfoFromNextProto(
case kProtoSPDY3:
case kProtoSPDY31:
return CONNECTION_INFO_SPDY3;
- case kProtoSPDY4a2:
- return CONNECTION_INFO_SPDY4A2;
- case kProtoHTTP2Draft04:
- return CONNECTION_INFO_HTTP2_DRAFT_04;
+ case kProtoSPDY4:
+ return CONNECTION_INFO_SPDY4;
case kProtoQUIC1SPDY3:
return CONNECTION_INFO_QUIC1_SPDY3;
@@ -395,10 +395,10 @@ std::string HttpResponseInfo::ConnectionInfoToString(
return "spdy/2";
case CONNECTION_INFO_SPDY3:
return "spdy/3";
- case CONNECTION_INFO_SPDY4A2:
- return "spdy/4a2";
- case CONNECTION_INFO_HTTP2_DRAFT_04:
- return "HTTP-draft-04/2.0";
+ case CONNECTION_INFO_SPDY4:
+ // This is the HTTP/2 draft 12 identifier. For internal
+ // consistency, HTTP/2 is named SPDY4 within Chromium.
+ return "h2-12";
case CONNECTION_INFO_QUIC1_SPDY3:
return "quic/1+spdy/3";
case NUM_OF_CONNECTION_INFOS:
diff --git a/chromium/net/http/http_response_info.h b/chromium/net/http/http_response_info.h
index f0908b0ab46..efd76fe7b51 100644
--- a/chromium/net/http/http_response_info.h
+++ b/chromium/net/http/http_response_info.h
@@ -37,9 +37,8 @@ class NET_EXPORT HttpResponseInfo {
CONNECTION_INFO_HTTP1 = 1,
CONNECTION_INFO_DEPRECATED_SPDY2 = 2,
CONNECTION_INFO_SPDY3 = 3,
- CONNECTION_INFO_SPDY4A2 = 4,
+ CONNECTION_INFO_SPDY4 = 4,
CONNECTION_INFO_QUIC1_SPDY3 = 5,
- CONNECTION_INFO_HTTP2_DRAFT_04 = 6,
NUM_OF_CONNECTION_INFOS,
};
@@ -59,12 +58,14 @@ class NET_EXPORT HttpResponseInfo {
bool response_truncated) const;
// The following is only defined if the request_time member is set.
- // If this response was resurrected from cache, then this bool is set, and
+ // If this resource was found in the cache, then this bool is set, and
// request_time may corresponds to a time "far" in the past. Note that
// stale content (perhaps un-cacheable) may be fetched from cache subject to
// the load flags specified on the request info. For example, this is done
// when a user presses the back button to re-render pages, or at startup,
// when reloading previously visited pages (without going over the network).
+ // Note also that under normal circumstances, was_cached is set to the correct
+ // value even if the request fails.
bool was_cached;
// True if the request was fetched from cache rather than the network
@@ -84,8 +85,10 @@ class NET_EXPORT HttpResponseInfo {
// True if the request was fetched via an explicit proxy. The proxy could
// be any type of proxy, HTTP or SOCKS. Note, we do not know if a
- // transparent proxy may have been involved.
+ // transparent proxy may have been involved. If true, |proxy_server| contains
+ // the name of the proxy server that was used.
bool was_fetched_via_proxy;
+ HostPortPair proxy_server;
// Whether the request use http proxy or server authentication.
bool did_use_http_auth;
diff --git a/chromium/net/http/http_security_headers.cc b/chromium/net/http/http_security_headers.cc
index 0c3305f6e42..8d0c1465307 100644
--- a/chromium/net/http/http_security_headers.cc
+++ b/chromium/net/http/http_security_headers.cc
@@ -253,6 +253,7 @@ bool ParseHSTSHeader(const std::string& value,
}
switch (state) {
+ case DIRECTIVE_END:
case AFTER_MAX_AGE:
case AFTER_INCLUDE_SUBDOMAINS:
case AFTER_UNKNOWN_LABEL:
@@ -260,7 +261,6 @@ bool ParseHSTSHeader(const std::string& value,
*include_subdomains = include_subdomains_candidate;
return true;
case START:
- case DIRECTIVE_END:
case AFTER_MAX_AGE_LABEL:
case AFTER_MAX_AGE_EQUALS:
return false;
diff --git a/chromium/net/http/http_security_headers_unittest.cc b/chromium/net/http/http_security_headers_unittest.cc
index 42a5ee98960..ce919ff81f3 100644
--- a/chromium/net/http/http_security_headers_unittest.cc
+++ b/chromium/net/http/http_security_headers_unittest.cc
@@ -90,8 +90,6 @@ TEST_F(HttpSecurityHeadersTest, BogusHeaders) {
&include_subdomains));
EXPECT_FALSE(ParseHSTSHeader("max-age=-3488923", &max_age,
&include_subdomains));
- EXPECT_FALSE(ParseHSTSHeader("max-age=3488923;", &max_age,
- &include_subdomains));
EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 e", &max_age,
&include_subdomains));
EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain",
@@ -114,6 +112,16 @@ TEST_F(HttpSecurityHeadersTest, BogusHeaders) {
&max_age, &include_subdomains));
EXPECT_FALSE(ParseHSTSHeader("max-age=34889 includesubdomains",
&max_age, &include_subdomains));
+ EXPECT_FALSE(ParseHSTSHeader(";;;; ;;;",
+ &max_age, &include_subdomains));
+ EXPECT_FALSE(ParseHSTSHeader(";;;; includeSubDomains;;;",
+ &max_age, &include_subdomains));
+ EXPECT_FALSE(ParseHSTSHeader(" includeSubDomains; ",
+ &max_age, &include_subdomains));
+ EXPECT_FALSE(ParseHSTSHeader(";",
+ &max_age, &include_subdomains));
+ EXPECT_FALSE(ParseHSTSHeader("max-age; ;",
+ &max_age, &include_subdomains));
// Check the out args were not updated by checking the default
// values for its predictable fields.
@@ -223,6 +231,9 @@ TEST_F(HttpSecurityHeadersTest, ValidSTSHeaders) {
EXPECT_EQ(expect_max_age, max_age);
EXPECT_FALSE(include_subdomains);
+ EXPECT_TRUE(ParseHSTSHeader("max-age=3488923;", &max_age,
+ &include_subdomains));
+
EXPECT_TRUE(ParseHSTSHeader(" Max-agE = 567", &max_age,
&include_subdomains));
expect_max_age = base::TimeDelta::FromSeconds(567);
@@ -311,6 +322,46 @@ TEST_F(HttpSecurityHeadersTest, ValidSTSHeaders) {
EXPECT_TRUE(include_subdomains);
EXPECT_TRUE(ParseHSTSHeader(
+ "max-age=394082038 ; incLudesUbdOmains;", &max_age,
+ &include_subdomains));
+ expect_max_age = base::TimeDelta::FromSeconds(
+ std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
+ EXPECT_EQ(expect_max_age, max_age);
+ EXPECT_TRUE(include_subdomains);
+
+ EXPECT_TRUE(ParseHSTSHeader(
+ ";; max-age=394082038 ; incLudesUbdOmains; ;", &max_age,
+ &include_subdomains));
+ expect_max_age = base::TimeDelta::FromSeconds(
+ std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
+ EXPECT_EQ(expect_max_age, max_age);
+ EXPECT_TRUE(include_subdomains);
+
+ EXPECT_TRUE(ParseHSTSHeader(
+ ";; max-age=394082038 ;", &max_age,
+ &include_subdomains));
+ expect_max_age = base::TimeDelta::FromSeconds(
+ std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
+ EXPECT_EQ(expect_max_age, max_age);
+ EXPECT_FALSE(include_subdomains);
+
+ EXPECT_TRUE(ParseHSTSHeader(
+ ";; ; ; max-age=394082038;;; includeSubdomains ;; ;", &max_age,
+ &include_subdomains));
+ expect_max_age = base::TimeDelta::FromSeconds(
+ std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
+ EXPECT_EQ(expect_max_age, max_age);
+ EXPECT_TRUE(include_subdomains);
+
+ EXPECT_TRUE(ParseHSTSHeader(
+ "incLudesUbdOmains ; max-age=394082038 ;;", &max_age,
+ &include_subdomains));
+ expect_max_age = base::TimeDelta::FromSeconds(
+ std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
+ EXPECT_EQ(expect_max_age, max_age);
+ EXPECT_TRUE(include_subdomains);
+
+ EXPECT_TRUE(ParseHSTSHeader(
" max-age=0 ; incLudesUbdOmains ", &max_age,
&include_subdomains));
expect_max_age = base::TimeDelta::FromSeconds(0);
@@ -450,13 +501,15 @@ TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA256) {
TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) {
TransportSecurityState state;
- TransportSecurityState::DomainState domain_state;
+ TransportSecurityState::DomainState static_domain_state;
// docs.google.com has preloaded pins.
+ const bool sni_enabled = true;
std::string domain = "docs.google.com";
- EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state));
- EXPECT_GT(domain_state.static_spki_hashes.size(), 1UL);
- HashValueVector saved_hashes = domain_state.static_spki_hashes;
+ EXPECT_TRUE(
+ state.GetStaticDomainState(domain, sni_enabled, &static_domain_state));
+ EXPECT_GT(static_domain_state.pkp.spki_hashes.size(), 1UL);
+ HashValueVector saved_hashes = static_domain_state.pkp.spki_hashes;
// Add a header, which should only update the dynamic state.
HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
@@ -471,49 +524,185 @@ TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) {
ssl_info.public_key_hashes.push_back(saved_hashes[0]);
EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
- // Expect the preloaded state to remain unchanged.
- std::string canonicalized_host = TransportSecurityState::CanonicalizeHost(
- domain);
- TransportSecurityState::DomainState static_domain_state;
- EXPECT_TRUE(state.GetStaticDomainState(canonicalized_host,
- true,
- &static_domain_state));
+ // Expect the static state to remain unchanged.
+ TransportSecurityState::DomainState new_static_domain_state;
+ EXPECT_TRUE(state.GetStaticDomainState(
+ domain, sni_enabled, &new_static_domain_state));
for (size_t i = 0; i < saved_hashes.size(); ++i) {
- EXPECT_TRUE(HashValuesEqual(
- saved_hashes[i])(static_domain_state.static_spki_hashes[i]));
+ EXPECT_TRUE(HashValuesEqual(saved_hashes[i])(
+ new_static_domain_state.pkp.spki_hashes[i]));
}
// Expect the dynamic state to reflect the header.
TransportSecurityState::DomainState dynamic_domain_state;
EXPECT_TRUE(state.GetDynamicDomainState(domain, &dynamic_domain_state));
- EXPECT_EQ(2UL, dynamic_domain_state.dynamic_spki_hashes.size());
+ EXPECT_EQ(2UL, dynamic_domain_state.pkp.spki_hashes.size());
- HashValueVector::const_iterator hash = std::find_if(
- dynamic_domain_state.dynamic_spki_hashes.begin(),
- dynamic_domain_state.dynamic_spki_hashes.end(),
- HashValuesEqual(good_hash));
- EXPECT_NE(dynamic_domain_state.dynamic_spki_hashes.end(), hash);
+ HashValueVector::const_iterator hash =
+ std::find_if(dynamic_domain_state.pkp.spki_hashes.begin(),
+ dynamic_domain_state.pkp.spki_hashes.end(),
+ HashValuesEqual(good_hash));
+ EXPECT_NE(dynamic_domain_state.pkp.spki_hashes.end(), hash);
- hash = std::find_if(
- dynamic_domain_state.dynamic_spki_hashes.begin(),
- dynamic_domain_state.dynamic_spki_hashes.end(),
- HashValuesEqual(backup_hash));
- EXPECT_NE(dynamic_domain_state.dynamic_spki_hashes.end(), hash);
+ hash = std::find_if(dynamic_domain_state.pkp.spki_hashes.begin(),
+ dynamic_domain_state.pkp.spki_hashes.end(),
+ HashValuesEqual(backup_hash));
+ EXPECT_NE(dynamic_domain_state.pkp.spki_hashes.end(), hash);
// Expect the overall state to reflect the header, too.
- EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state));
- EXPECT_EQ(2UL, domain_state.dynamic_spki_hashes.size());
+ EXPECT_TRUE(state.HasPublicKeyPins(domain, sni_enabled));
+ HashValueVector hashes;
+ hashes.push_back(good_hash);
+ std::string failure_log;
+ EXPECT_TRUE(
+ state.CheckPublicKeyPins(domain, sni_enabled, hashes, &failure_log));
- hash = std::find_if(domain_state.dynamic_spki_hashes.begin(),
- domain_state.dynamic_spki_hashes.end(),
+ TransportSecurityState::DomainState new_dynamic_domain_state;
+ EXPECT_TRUE(state.GetDynamicDomainState(domain, &new_dynamic_domain_state));
+ EXPECT_EQ(2UL, new_dynamic_domain_state.pkp.spki_hashes.size());
+
+ hash = std::find_if(new_dynamic_domain_state.pkp.spki_hashes.begin(),
+ new_dynamic_domain_state.pkp.spki_hashes.end(),
HashValuesEqual(good_hash));
- EXPECT_NE(domain_state.dynamic_spki_hashes.end(), hash);
+ EXPECT_NE(new_dynamic_domain_state.pkp.spki_hashes.end(), hash);
+
+ hash = std::find_if(new_dynamic_domain_state.pkp.spki_hashes.begin(),
+ new_dynamic_domain_state.pkp.spki_hashes.end(),
+ HashValuesEqual(backup_hash));
+ EXPECT_NE(new_dynamic_domain_state.pkp.spki_hashes.end(), hash);
+}
+
+// Failing on win_chromium_rel. crbug.com/375538
+#if defined(OS_WIN)
+#define MAYBE_UpdateDynamicPKPMaxAge0 DISABLED_UpdateDynamicPKPMaxAge0
+#else
+#define MAYBE_UpdateDynamicPKPMaxAge0 UpdateDynamicPKPMaxAge0
+#endif
+TEST_F(HttpSecurityHeadersTest, MAYBE_UpdateDynamicPKPMaxAge0) {
+ TransportSecurityState state;
+ TransportSecurityState::DomainState static_domain_state;
+
+ // docs.google.com has preloaded pins.
+ const bool sni_enabled = true;
+ std::string domain = "docs.google.com";
+ ASSERT_TRUE(
+ state.GetStaticDomainState(domain, sni_enabled, &static_domain_state));
+ EXPECT_GT(static_domain_state.pkp.spki_hashes.size(), 1UL);
+ HashValueVector saved_hashes = static_domain_state.pkp.spki_hashes;
+
+ // Add a header, which should only update the dynamic state.
+ HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
+ std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
+ std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
+ std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin;
+
+ // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
+ SSLInfo ssl_info;
+ ssl_info.public_key_hashes.push_back(good_hash);
+ ssl_info.public_key_hashes.push_back(saved_hashes[0]);
+ EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
+
+ // Expect the static state to remain unchanged.
+ TransportSecurityState::DomainState new_static_domain_state;
+ EXPECT_TRUE(state.GetStaticDomainState(
+ domain, sni_enabled, &new_static_domain_state));
+ EXPECT_EQ(saved_hashes.size(),
+ new_static_domain_state.pkp.spki_hashes.size());
+ for (size_t i = 0; i < saved_hashes.size(); ++i) {
+ EXPECT_TRUE(HashValuesEqual(saved_hashes[i])(
+ new_static_domain_state.pkp.spki_hashes[i]));
+ }
- hash = std::find_if(
- domain_state.dynamic_spki_hashes.begin(),
- domain_state.dynamic_spki_hashes.end(),
- HashValuesEqual(backup_hash));
- EXPECT_NE(domain_state.dynamic_spki_hashes.end(), hash);
+ // Expect the dynamic state to have pins.
+ TransportSecurityState::DomainState new_dynamic_domain_state;
+ EXPECT_TRUE(state.GetDynamicDomainState(domain, &new_dynamic_domain_state));
+ EXPECT_EQ(2UL, new_dynamic_domain_state.pkp.spki_hashes.size());
+ EXPECT_TRUE(new_dynamic_domain_state.HasPublicKeyPins());
+
+ // Now set another header with max-age=0, and check that the pins are
+ // cleared in the dynamic state only.
+ header = "max-age = 0; " + good_pin + "; " + backup_pin;
+ EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
+
+ // Expect the static state to remain unchanged.
+ TransportSecurityState::DomainState new_static_domain_state2;
+ EXPECT_TRUE(state.GetStaticDomainState(
+ domain, sni_enabled, &new_static_domain_state2));
+ EXPECT_EQ(saved_hashes.size(),
+ new_static_domain_state2.pkp.spki_hashes.size());
+ for (size_t i = 0; i < saved_hashes.size(); ++i) {
+ EXPECT_TRUE(HashValuesEqual(saved_hashes[i])(
+ new_static_domain_state2.pkp.spki_hashes[i]));
+ }
+
+ // Expect the dynamic pins to be gone.
+ TransportSecurityState::DomainState new_dynamic_domain_state2;
+ EXPECT_FALSE(state.GetDynamicDomainState(domain, &new_dynamic_domain_state2));
+
+ // Expect the exact-matching static policy to continue to apply, even
+ // though dynamic policy has been removed. (This policy may change in the
+ // future, in which case this test must be updated.)
+ EXPECT_TRUE(state.HasPublicKeyPins(domain, true));
+ EXPECT_TRUE(state.ShouldSSLErrorsBeFatal(domain, true));
+ std::string failure_log;
+ // Damage the hashes to cause a pin validation failure.
+ new_static_domain_state2.pkp.spki_hashes[0].data()[0] ^= 0x80;
+ new_static_domain_state2.pkp.spki_hashes[1].data()[0] ^= 0x80;
+ EXPECT_FALSE(state.CheckPublicKeyPins(
+ domain, true, new_static_domain_state2.pkp.spki_hashes, &failure_log));
+ EXPECT_NE(0UL, failure_log.length());
+}
+#undef MAYBE_UpdateDynamicPKPMaxAge0
+
+// Tests that when a static HSTS and a static HPKP entry are present, adding a
+// dynamic HSTS header does not clobber the static HPKP entry. Further, adding a
+// dynamic HPKP entry could not affect the HSTS entry for the site.
+TEST_F(HttpSecurityHeadersTest, NoClobberPins) {
+ TransportSecurityState state;
+ TransportSecurityState::DomainState domain_state;
+
+ // accounts.google.com has preloaded pins.
+ std::string domain = "accounts.google.com";
+
+ // Retrieve the DomainState as it is by default, including its known good
+ // pins.
+ const bool sni_enabled = true;
+ EXPECT_TRUE(state.GetStaticDomainState(domain, sni_enabled, &domain_state));
+ HashValueVector saved_hashes = domain_state.pkp.spki_hashes;
+ EXPECT_TRUE(domain_state.ShouldUpgradeToSSL());
+ EXPECT_TRUE(domain_state.HasPublicKeyPins());
+ EXPECT_TRUE(state.ShouldUpgradeToSSL(domain, sni_enabled));
+ EXPECT_TRUE(state.HasPublicKeyPins(domain, sni_enabled));
+
+ // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given
+ // the original |saved_hashes|, indicating that the static PKP data is still
+ // configured for the domain.
+ EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000"));
+ EXPECT_TRUE(state.ShouldUpgradeToSSL(domain, sni_enabled));
+ std::string failure_log;
+ EXPECT_TRUE(state.CheckPublicKeyPins(
+ domain, sni_enabled, saved_hashes, &failure_log));
+
+ // Add an HPKP header, which should only update the dynamic state.
+ HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
+ std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
+ std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
+ std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin;
+
+ // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
+ SSLInfo ssl_info;
+ ssl_info.public_key_hashes.push_back(good_hash);
+ ssl_info.public_key_hashes.push_back(saved_hashes[0]);
+ EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
+
+ EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
+ // HSTS should still be configured for this domain.
+ EXPECT_TRUE(domain_state.ShouldUpgradeToSSL());
+ EXPECT_TRUE(state.ShouldUpgradeToSSL(domain, sni_enabled));
+ // The dynamic pins, which do not match |saved_hashes|, should take
+ // precedence over the static pins and cause the check to fail.
+ EXPECT_FALSE(state.CheckPublicKeyPins(
+ domain, sni_enabled, saved_hashes, &failure_log));
}
}; // namespace net
diff --git a/chromium/net/http/http_server_properties.cc b/chromium/net/http/http_server_properties.cc
index a10d5060c06..19b334c1fb3 100644
--- a/chromium/net/http/http_server_properties.cc
+++ b/chromium/net/http/http_server_properties.cc
@@ -5,6 +5,7 @@
#include "net/http/http_server_properties.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/strings/stringprintf.h"
namespace net {
@@ -19,8 +20,7 @@ const char* const kAlternateProtocolStrings[] = {
"npn-spdy/2",
"npn-spdy/3",
"npn-spdy/3.1",
- "npn-spdy/4a2",
- "npn-HTTP-draft-04/2.0",
+ "npn-h2-12", // HTTP/2 draft 12. Called SPDY4 internally.
"quic"
};
const char kBrokenAlternateProtocol[] = "Broken";
@@ -31,6 +31,28 @@ COMPILE_ASSERT(
} // namespace
+void HistogramAlternateProtocolUsage(
+ AlternateProtocolUsage usage,
+ AlternateProtocolExperiment alternate_protocol_experiment) {
+ UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage", usage,
+ ALTERNATE_PROTOCOL_USAGE_MAX);
+ if (alternate_protocol_experiment ==
+ ALTERNATE_PROTOCOL_TRUNCATED_200_SERVERS) {
+ UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage.200Truncated", usage,
+ ALTERNATE_PROTOCOL_USAGE_MAX);
+ } else if (alternate_protocol_experiment ==
+ ALTERNATE_PROTOCOL_TRUNCATED_1000_SERVERS) {
+ UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage.1000Truncated", usage,
+ ALTERNATE_PROTOCOL_USAGE_MAX);
+ }
+}
+
+void HistogramBrokenAlternateProtocolLocation(
+ BrokenAlternateProtocolLocation location){
+ UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolBrokenLocation", location,
+ BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX);
+}
+
bool IsAlternateProtocolValid(AlternateProtocol protocol) {
return protocol >= ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION &&
protocol <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION;
@@ -41,8 +63,7 @@ const char* AlternateProtocolToString(AlternateProtocol protocol) {
case DEPRECATED_NPN_SPDY_2:
case NPN_SPDY_3:
case NPN_SPDY_3_1:
- case NPN_SPDY_4A2:
- case NPN_HTTP2_DRAFT_04:
+ case NPN_SPDY_4:
case QUIC:
DCHECK(IsAlternateProtocolValid(protocol));
return kAlternateProtocolStrings[
@@ -76,10 +97,8 @@ AlternateProtocol AlternateProtocolFromNextProto(NextProto next_proto) {
return NPN_SPDY_3;
case kProtoSPDY31:
return NPN_SPDY_3_1;
- case kProtoSPDY4a2:
- return NPN_SPDY_4A2;
- case kProtoHTTP2Draft04:
- return NPN_HTTP2_DRAFT_04;
+ case kProtoSPDY4:
+ return NPN_SPDY_4;
case kProtoQUIC1SPDY3:
return QUIC;
diff --git a/chromium/net/http/http_server_properties.h b/chromium/net/http/http_server_properties.h
index 72fda4355b1..88d1f3cefba 100644
--- a/chromium/net/http/http_server_properties.h
+++ b/chromium/net/http/http_server_properties.h
@@ -8,25 +8,67 @@
#include <map>
#include <string>
#include "base/basictypes.h"
+#include "base/containers/mru_cache.h"
#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
-#include "net/http/http_pipelined_host_capability.h"
#include "net/socket/next_proto.h"
#include "net/spdy/spdy_framer.h" // TODO(willchan): Reconsider this.
namespace net {
+enum AlternateProtocolExperiment {
+ // 200 alternate_protocol servers are loaded (persisted 200 MRU servers).
+ ALTERNATE_PROTOCOL_NOT_PART_OF_EXPERIMENT = 0,
+ // 200 alternate_protocol servers are loaded (persisted 1000 MRU servers).
+ ALTERNATE_PROTOCOL_TRUNCATED_200_SERVERS,
+ // 1000 alternate_protocol servers are loaded (persisted 1000 MRU servers).
+ ALTERNATE_PROTOCOL_TRUNCATED_1000_SERVERS,
+};
+
+enum AlternateProtocolUsage {
+ // Alternate Protocol was used without racing a normal connection.
+ ALTERNATE_PROTOCOL_USAGE_NO_RACE = 0,
+ // Alternate Protocol was used by winning a race with a normal connection.
+ ALTERNATE_PROTOCOL_USAGE_WON_RACE = 1,
+ // Alternate Protocol was not used by losing a race with a normal connection.
+ ALTERNATE_PROTOCOL_USAGE_LOST_RACE = 2,
+ // Alternate Protocol was not used because no Alternate-Protocol information
+ // was available when the request was issued, but an Alternate-Protocol header
+ // was present in the response.
+ ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING = 3,
+ // Alternate Protocol was not used because it was marked broken.
+ ALTERNATE_PROTOCOL_USAGE_BROKEN = 4,
+ // Maximum value for the enum.
+ ALTERNATE_PROTOCOL_USAGE_MAX,
+};
+
+// Log a histogram to reflect |usage| and |alternate_protocol_experiment|.
+NET_EXPORT void HistogramAlternateProtocolUsage(
+ AlternateProtocolUsage usage,
+ AlternateProtocolExperiment alternate_protocol_experiment);
+
+enum BrokenAlternateProtocolLocation {
+ BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB = 0,
+ BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY = 1,
+ BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT = 2,
+ BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN = 3,
+ BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX,
+};
+
+// Log a histogram to reflect |location|.
+NET_EXPORT void HistogramBrokenAlternateProtocolLocation(
+ BrokenAlternateProtocolLocation location);
+
enum AlternateProtocol {
DEPRECATED_NPN_SPDY_2 = 0,
ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION = DEPRECATED_NPN_SPDY_2,
NPN_SPDY_MINIMUM_VERSION = DEPRECATED_NPN_SPDY_2,
NPN_SPDY_3,
NPN_SPDY_3_1,
- NPN_SPDY_4A2,
- // We lump in HTTP/2 with the SPDY protocols for now.
- NPN_HTTP2_DRAFT_04,
- NPN_SPDY_MAXIMUM_VERSION = NPN_HTTP2_DRAFT_04,
+ NPN_SPDY_4, // SPDY4 is HTTP/2.
+ NPN_SPDY_MAXIMUM_VERSION = NPN_SPDY_4,
QUIC,
ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION = QUIC,
ALTERNATE_PROTOCOL_BROKEN, // The alternate protocol is known to be broken.
@@ -61,10 +103,9 @@ struct NET_EXPORT PortAlternateProtocolPair {
AlternateProtocol protocol;
};
-typedef std::map<HostPortPair, PortAlternateProtocolPair> AlternateProtocolMap;
-typedef std::map<HostPortPair, SettingsMap> SpdySettingsMap;
-typedef std::map<HostPortPair,
- HttpPipelinedHostCapability> PipelineCapabilityMap;
+typedef base::MRUCache<
+ HostPortPair, PortAlternateProtocolPair> AlternateProtocolMap;
+typedef base::MRUCache<HostPortPair, SettingsMap> SpdySettingsMap;
extern const char kAlternateProtocolHeader[];
@@ -75,6 +116,11 @@ extern const char kAlternateProtocolHeader[];
// * Spdy Settings (like CWND ID field)
class NET_EXPORT HttpServerProperties {
public:
+ struct NetworkStats {
+ base::TimeDelta srtt;
+ uint64 bandwidth_estimate;
+ };
+
HttpServerProperties() {}
virtual ~HttpServerProperties() {}
@@ -85,7 +131,7 @@ class NET_EXPORT HttpServerProperties {
virtual void Clear() = 0;
// Returns true if |server| supports SPDY.
- virtual bool SupportsSpdy(const HostPortPair& server) const = 0;
+ virtual bool SupportsSpdy(const HostPortPair& server) = 0;
// Add |server| into the persistent store. Should only be called from IO
// thread.
@@ -93,12 +139,12 @@ class NET_EXPORT HttpServerProperties {
bool support_spdy) = 0;
// Returns true if |server| has an Alternate-Protocol header.
- virtual bool HasAlternateProtocol(const HostPortPair& server) const = 0;
+ virtual bool HasAlternateProtocol(const HostPortPair& server) = 0;
// Returns the Alternate-Protocol and port for |server|.
// HasAlternateProtocol(server) must be true.
virtual PortAlternateProtocolPair GetAlternateProtocol(
- const HostPortPair& server) const = 0;
+ const HostPortPair& server) = 0;
// Sets the Alternate-Protocol for |server|.
virtual void SetAlternateProtocol(const HostPortPair& server,
@@ -108,13 +154,29 @@ class NET_EXPORT HttpServerProperties {
// Sets the Alternate-Protocol for |server| to be BROKEN.
virtual void SetBrokenAlternateProtocol(const HostPortPair& server) = 0;
+ // Returns true if Alternate-Protocol for |server| was recently BROKEN.
+ virtual bool WasAlternateProtocolRecentlyBroken(
+ const HostPortPair& server) = 0;
+
+ // Confirms that Alternate-Protocol for |server| is working.
+ virtual void ConfirmAlternateProtocol(const HostPortPair& server) = 0;
+
+ // Clears the Alternate-Protocol for |server|.
+ virtual void ClearAlternateProtocol(const HostPortPair& server) = 0;
+
// Returns all Alternate-Protocol mappings.
virtual const AlternateProtocolMap& alternate_protocol_map() const = 0;
+ virtual void SetAlternateProtocolExperiment(
+ AlternateProtocolExperiment experiment) = 0;
+
+ virtual AlternateProtocolExperiment GetAlternateProtocolExperiment()
+ const = 0;
+
// Gets a reference to the SettingsMap stored for a host.
// If no settings are stored, returns an empty SettingsMap.
virtual const SettingsMap& GetSpdySettings(
- const HostPortPair& host_port_pair) const = 0;
+ const HostPortPair& host_port_pair) = 0;
// Saves an individual SPDY setting for a host. Returns true if SPDY setting
// is to be persisted.
@@ -132,16 +194,11 @@ class NET_EXPORT HttpServerProperties {
// Returns all persistent SPDY settings.
virtual const SpdySettingsMap& spdy_settings_map() const = 0;
- virtual HttpPipelinedHostCapability GetPipelineCapability(
- const HostPortPair& origin) = 0;
-
- virtual void SetPipelineCapability(
- const HostPortPair& origin,
- HttpPipelinedHostCapability capability) = 0;
+ virtual void SetServerNetworkStats(const HostPortPair& host_port_pair,
+ NetworkStats stats) = 0;
- virtual void ClearPipelineCapabilities() = 0;
-
- virtual PipelineCapabilityMap GetPipelineCapabilityMap() const = 0;
+ virtual const NetworkStats* GetServerNetworkStats(
+ const HostPortPair& host_port_pair) const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(HttpServerProperties);
diff --git a/chromium/net/http/http_server_properties_impl.cc b/chromium/net/http/http_server_properties_impl.cc
index a4ac6dc3804..1def87f71a0 100644
--- a/chromium/net/http/http_server_properties_impl.cc
+++ b/chromium/net/http/http_server_properties_impl.cc
@@ -4,23 +4,32 @@
#include "net/http/http_server_properties_impl.h"
+#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "net/http/http_pipelined_host_capability.h"
namespace net {
-// TODO(simonjam): Run experiments with different values of this to see what
-// value is good at avoiding evictions without eating too much memory. Until
-// then, this is just a bad guess.
-static const int kDefaultNumHostsToRemember = 200;
+namespace {
+
+const uint64 kBrokenAlternateProtocolDelaySecs = 300;
+
+} // namespace
HttpServerPropertiesImpl::HttpServerPropertiesImpl()
- : pipeline_capability_map_(
- new CachedPipelineCapabilityMap(kDefaultNumHostsToRemember)),
+ : spdy_servers_map_(SpdyServerHostPortMap::NO_AUTO_EVICT),
+ alternate_protocol_map_(AlternateProtocolMap::NO_AUTO_EVICT),
+ alternate_protocol_experiment_(
+ ALTERNATE_PROTOCOL_NOT_PART_OF_EXPERIMENT),
+ spdy_settings_map_(SpdySettingsMap::NO_AUTO_EVICT),
weak_ptr_factory_(this) {
+ canoncial_suffixes_.push_back(".c.youtube.com");
+ canoncial_suffixes_.push_back(".googlevideo.com");
+ canoncial_suffixes_.push_back(".googleusercontent.com");
}
HttpServerPropertiesImpl::~HttpServerPropertiesImpl() {
@@ -30,59 +39,84 @@ void HttpServerPropertiesImpl::InitializeSpdyServers(
std::vector<std::string>* spdy_servers,
bool support_spdy) {
DCHECK(CalledOnValidThread());
- spdy_servers_table_.clear();
if (!spdy_servers)
return;
- for (std::vector<std::string>::iterator it = spdy_servers->begin();
- it != spdy_servers->end(); ++it) {
- spdy_servers_table_[*it] = support_spdy;
+ // Add the entries from persisted data.
+ for (std::vector<std::string>::reverse_iterator it = spdy_servers->rbegin();
+ it != spdy_servers->rend(); ++it) {
+ spdy_servers_map_.Put(*it, support_spdy);
}
}
void HttpServerPropertiesImpl::InitializeAlternateProtocolServers(
AlternateProtocolMap* alternate_protocol_map) {
- // First swap, and then add back all the ALTERNATE_PROTOCOL_BROKEN ones since
- // those don't get persisted.
- alternate_protocol_map_.swap(*alternate_protocol_map);
- for (AlternateProtocolMap::const_iterator it =
- alternate_protocol_map->begin();
- it != alternate_protocol_map->end(); ++it) {
- if (it->second.protocol == ALTERNATE_PROTOCOL_BROKEN)
- alternate_protocol_map_[it->first] = it->second;
+ // Keep all the ALTERNATE_PROTOCOL_BROKEN ones since those don't
+ // get persisted.
+ for (AlternateProtocolMap::iterator it = alternate_protocol_map_.begin();
+ it != alternate_protocol_map_.end();) {
+ AlternateProtocolMap::iterator old_it = it;
+ ++it;
+ if (old_it->second.protocol != ALTERNATE_PROTOCOL_BROKEN) {
+ alternate_protocol_map_.Erase(old_it);
+ }
}
-}
-void HttpServerPropertiesImpl::InitializeSpdySettingsServers(
- SpdySettingsMap* spdy_settings_map) {
- spdy_settings_map_.swap(*spdy_settings_map);
-}
+ // Add the entries from persisted data.
+ for (AlternateProtocolMap::reverse_iterator it =
+ alternate_protocol_map->rbegin();
+ it != alternate_protocol_map->rend(); ++it) {
+ alternate_protocol_map_.Put(it->first, it->second);
+ }
-void HttpServerPropertiesImpl::InitializePipelineCapabilities(
- const PipelineCapabilityMap* pipeline_capability_map) {
- PipelineCapabilityMap::const_iterator it;
- pipeline_capability_map_->Clear();
- for (it = pipeline_capability_map->begin();
- it != pipeline_capability_map->end(); ++it) {
- pipeline_capability_map_->Put(it->first, it->second);
+ // Attempt to find canonical servers.
+ int canonical_ports[] = { 80, 443 };
+ for (size_t i = 0; i < canoncial_suffixes_.size(); ++i) {
+ std::string canonical_suffix = canoncial_suffixes_[i];
+ for (size_t j = 0; j < arraysize(canonical_ports); ++j) {
+ HostPortPair canonical_host(canonical_suffix, canonical_ports[j]);
+ // If we already have a valid canonical server, we're done.
+ if (ContainsKey(canonical_host_to_origin_map_, canonical_host) &&
+ (alternate_protocol_map_.Peek(canonical_host_to_origin_map_[
+ canonical_host]) != alternate_protocol_map_.end())) {
+ continue;
+ }
+ // Now attempt to find a server which matches this origin and set it as
+ // canonical .
+ for (AlternateProtocolMap::const_iterator it =
+ alternate_protocol_map_.begin();
+ it != alternate_protocol_map_.end(); ++it) {
+ if (EndsWith(it->first.host(), canoncial_suffixes_[i], false)) {
+ canonical_host_to_origin_map_[canonical_host] = it->first;
+ break;
+ }
+ }
+ }
}
}
-void HttpServerPropertiesImpl::SetNumPipelinedHostsToRemember(int max_size) {
- DCHECK(pipeline_capability_map_->empty());
- pipeline_capability_map_.reset(new CachedPipelineCapabilityMap(max_size));
+void HttpServerPropertiesImpl::InitializeSpdySettingsServers(
+ SpdySettingsMap* spdy_settings_map) {
+ for (SpdySettingsMap::reverse_iterator it = spdy_settings_map->rbegin();
+ it != spdy_settings_map->rend(); ++it) {
+ spdy_settings_map_.Put(it->first, it->second);
+ }
}
void HttpServerPropertiesImpl::GetSpdyServerList(
- base::ListValue* spdy_server_list) const {
+ base::ListValue* spdy_server_list,
+ size_t max_size) const {
DCHECK(CalledOnValidThread());
DCHECK(spdy_server_list);
spdy_server_list->Clear();
+ size_t count = 0;
// Get the list of servers (host/port) that support SPDY.
- for (SpdyServerHostPortTable::const_iterator it = spdy_servers_table_.begin();
- it != spdy_servers_table_.end(); ++it) {
+ for (SpdyServerHostPortMap::const_iterator it = spdy_servers_map_.begin();
+ it != spdy_servers_map_.end() && count < max_size; ++it) {
const std::string spdy_server_host_port = it->first;
- if (it->second)
+ if (it->second) {
spdy_server_list->Append(new base::StringValue(spdy_server_host_port));
+ ++count;
+ }
}
}
@@ -119,22 +153,21 @@ base::WeakPtr<HttpServerProperties> HttpServerPropertiesImpl::GetWeakPtr() {
void HttpServerPropertiesImpl::Clear() {
DCHECK(CalledOnValidThread());
- spdy_servers_table_.clear();
- alternate_protocol_map_.clear();
- spdy_settings_map_.clear();
- pipeline_capability_map_->Clear();
+ spdy_servers_map_.Clear();
+ alternate_protocol_map_.Clear();
+ spdy_settings_map_.Clear();
}
bool HttpServerPropertiesImpl::SupportsSpdy(
- const net::HostPortPair& host_port_pair) const {
+ const net::HostPortPair& host_port_pair) {
DCHECK(CalledOnValidThread());
if (host_port_pair.host().empty())
return false;
std::string spdy_server = GetFlattenedSpdyServer(host_port_pair);
- SpdyServerHostPortTable::const_iterator spdy_host_port =
- spdy_servers_table_.find(spdy_server);
- if (spdy_host_port != spdy_servers_table_.end())
+ SpdyServerHostPortMap::iterator spdy_host_port =
+ spdy_servers_map_.Get(spdy_server);
+ if (spdy_host_port != spdy_servers_map_.end())
return spdy_host_port->second;
return false;
}
@@ -147,33 +180,53 @@ void HttpServerPropertiesImpl::SetSupportsSpdy(
return;
std::string spdy_server = GetFlattenedSpdyServer(host_port_pair);
- SpdyServerHostPortTable::iterator spdy_host_port =
- spdy_servers_table_.find(spdy_server);
- if ((spdy_host_port != spdy_servers_table_.end()) &&
+ SpdyServerHostPortMap::iterator spdy_host_port =
+ spdy_servers_map_.Get(spdy_server);
+ if ((spdy_host_port != spdy_servers_map_.end()) &&
(spdy_host_port->second == support_spdy)) {
return;
}
// Cache the data.
- spdy_servers_table_[spdy_server] = support_spdy;
+ spdy_servers_map_.Put(spdy_server, support_spdy);
}
bool HttpServerPropertiesImpl::HasAlternateProtocol(
- const HostPortPair& server) const {
- return ContainsKey(alternate_protocol_map_, server) ||
- g_forced_alternate_protocol;
+ const HostPortPair& server) {
+ if (alternate_protocol_map_.Get(server) != alternate_protocol_map_.end() ||
+ g_forced_alternate_protocol)
+ return true;
+
+ return GetCanonicalHost(server) != canonical_host_to_origin_map_.end();
+}
+
+std::string HttpServerPropertiesImpl::GetCanonicalSuffix(
+ const HostPortPair& server) {
+ // If this host ends with a canonical suffix, then return the canonical
+ // suffix.
+ for (size_t i = 0; i < canoncial_suffixes_.size(); ++i) {
+ std::string canonical_suffix = canoncial_suffixes_[i];
+ if (EndsWith(server.host(), canoncial_suffixes_[i], false)) {
+ return canonical_suffix;
+ }
+ }
+ return std::string();
}
PortAlternateProtocolPair
HttpServerPropertiesImpl::GetAlternateProtocol(
- const HostPortPair& server) const {
+ const HostPortPair& server) {
DCHECK(HasAlternateProtocol(server));
// First check the map.
- AlternateProtocolMap::const_iterator it =
- alternate_protocol_map_.find(server);
+ AlternateProtocolMap::iterator it = alternate_protocol_map_.Get(server);
if (it != alternate_protocol_map_.end())
return it->second;
+ // Next check the canonical host.
+ CanonicalHostMap::const_iterator canonical_host = GetCanonicalHost(server);
+ if (canonical_host != canonical_host_to_origin_map_.end())
+ return alternate_protocol_map_.Get(canonical_host->second)->second;
+
// We must be forcing an alternate.
DCHECK(g_forced_alternate_protocol);
return *g_forced_alternate_protocol;
@@ -210,14 +263,68 @@ void HttpServerPropertiesImpl::SetAlternateProtocol(
<< ", Protocol: " << alternate_protocol
<< "].";
}
+ } else {
+ // TODO(rch): Consider the case where multiple requests are started
+ // before the first completes. In this case, only one of the jobs
+ // would reach this code, whereas all of them should should have.
+ HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING,
+ alternate_protocol_experiment_);
}
- alternate_protocol_map_[server] = alternate;
+ alternate_protocol_map_.Put(server, alternate);
+
+ // If this host ends with a canonical suffix, then set it as the
+ // canonical host.
+ for (size_t i = 0; i < canoncial_suffixes_.size(); ++i) {
+ std::string canonical_suffix = canoncial_suffixes_[i];
+ if (EndsWith(server.host(), canoncial_suffixes_[i], false)) {
+ HostPortPair canonical_host(canonical_suffix, server.port());
+ canonical_host_to_origin_map_[canonical_host] = server;
+ break;
+ }
+ }
}
void HttpServerPropertiesImpl::SetBrokenAlternateProtocol(
const HostPortPair& server) {
- alternate_protocol_map_[server].protocol = ALTERNATE_PROTOCOL_BROKEN;
+ AlternateProtocolMap::iterator it = alternate_protocol_map_.Get(server);
+ if (it != alternate_protocol_map_.end()) {
+ it->second.protocol = ALTERNATE_PROTOCOL_BROKEN;
+ } else {
+ PortAlternateProtocolPair alternate;
+ alternate.protocol = ALTERNATE_PROTOCOL_BROKEN;
+ alternate_protocol_map_.Put(server, alternate);
+ }
+ int count = ++broken_alternate_protocol_map_[server];
+ base::TimeDelta delay =
+ base::TimeDelta::FromSeconds(kBrokenAlternateProtocolDelaySecs);
+ BrokenAlternateProtocolEntry entry;
+ entry.server = server;
+ entry.when = base::TimeTicks::Now() + delay * (1 << (count - 1));
+ broken_alternate_protocol_list_.push_back(entry);
+ // If this is the only entry in the list, schedule an expiration task.
+ // Otherwse it will be rescheduled automatically when the pending
+ // task runs.
+ if (broken_alternate_protocol_list_.size() == 1) {
+ ScheduleBrokenAlternateProtocolMappingsExpiration();
+ }
+}
+
+bool HttpServerPropertiesImpl::WasAlternateProtocolRecentlyBroken(
+ const HostPortPair& server) {
+ return ContainsKey(broken_alternate_protocol_map_, server);
+}
+
+void HttpServerPropertiesImpl::ConfirmAlternateProtocol(
+ const HostPortPair& server) {
+ broken_alternate_protocol_map_.erase(server);
+}
+
+void HttpServerPropertiesImpl::ClearAlternateProtocol(
+ const HostPortPair& server) {
+ AlternateProtocolMap::iterator it = alternate_protocol_map_.Peek(server);
+ if (it != alternate_protocol_map_.end())
+ alternate_protocol_map_.Erase(it);
}
const AlternateProtocolMap&
@@ -225,9 +332,19 @@ HttpServerPropertiesImpl::alternate_protocol_map() const {
return alternate_protocol_map_;
}
+void HttpServerPropertiesImpl::SetAlternateProtocolExperiment(
+ AlternateProtocolExperiment experiment) {
+ alternate_protocol_experiment_ = experiment;
+}
+
+AlternateProtocolExperiment
+HttpServerPropertiesImpl::GetAlternateProtocolExperiment() const {
+ return alternate_protocol_experiment_;
+}
+
const SettingsMap& HttpServerPropertiesImpl::GetSpdySettings(
- const HostPortPair& host_port_pair) const {
- SpdySettingsMap::const_iterator it = spdy_settings_map_.find(host_port_pair);
+ const HostPortPair& host_port_pair) {
+ SpdySettingsMap::iterator it = spdy_settings_map_.Get(host_port_pair);
if (it == spdy_settings_map_.end()) {
CR_DEFINE_STATIC_LOCAL(SettingsMap, kEmptySettingsMap, ());
return kEmptySettingsMap;
@@ -243,19 +360,28 @@ bool HttpServerPropertiesImpl::SetSpdySetting(
if (!(flags & SETTINGS_FLAG_PLEASE_PERSIST))
return false;
- SettingsMap& settings_map = spdy_settings_map_[host_port_pair];
SettingsFlagsAndValue flags_and_value(SETTINGS_FLAG_PERSISTED, value);
- settings_map[id] = flags_and_value;
+ SpdySettingsMap::iterator it = spdy_settings_map_.Get(host_port_pair);
+ if (it == spdy_settings_map_.end()) {
+ SettingsMap settings_map;
+ settings_map[id] = flags_and_value;
+ spdy_settings_map_.Put(host_port_pair, settings_map);
+ } else {
+ SettingsMap& settings_map = it->second;
+ settings_map[id] = flags_and_value;
+ }
return true;
}
void HttpServerPropertiesImpl::ClearSpdySettings(
const HostPortPair& host_port_pair) {
- spdy_settings_map_.erase(host_port_pair);
+ SpdySettingsMap::iterator it = spdy_settings_map_.Peek(host_port_pair);
+ if (it != spdy_settings_map_.end())
+ spdy_settings_map_.Erase(it);
}
void HttpServerPropertiesImpl::ClearAllSpdySettings() {
- spdy_settings_map_.clear();
+ spdy_settings_map_.Clear();
}
const SpdySettingsMap&
@@ -263,41 +389,65 @@ HttpServerPropertiesImpl::spdy_settings_map() const {
return spdy_settings_map_;
}
-HttpPipelinedHostCapability HttpServerPropertiesImpl::GetPipelineCapability(
- const HostPortPair& origin) {
- HttpPipelinedHostCapability capability = PIPELINE_UNKNOWN;
- CachedPipelineCapabilityMap::const_iterator it =
- pipeline_capability_map_->Get(origin);
- if (it != pipeline_capability_map_->end()) {
- capability = it->second;
+void HttpServerPropertiesImpl::SetServerNetworkStats(
+ const HostPortPair& host_port_pair,
+ NetworkStats stats) {
+ server_network_stats_map_[host_port_pair] = stats;
+}
+
+const HttpServerProperties::NetworkStats*
+HttpServerPropertiesImpl::GetServerNetworkStats(
+ const HostPortPair& host_port_pair) const {
+ ServerNetworkStatsMap::const_iterator it =
+ server_network_stats_map_.find(host_port_pair);
+ if (it == server_network_stats_map_.end()) {
+ return NULL;
}
- return capability;
+ return &it->second;
}
-void HttpServerPropertiesImpl::SetPipelineCapability(
- const HostPortPair& origin,
- HttpPipelinedHostCapability capability) {
- CachedPipelineCapabilityMap::iterator it =
- pipeline_capability_map_->Peek(origin);
- if (it == pipeline_capability_map_->end() ||
- it->second != PIPELINE_INCAPABLE) {
- pipeline_capability_map_->Put(origin, capability);
+HttpServerPropertiesImpl::CanonicalHostMap::const_iterator
+HttpServerPropertiesImpl::GetCanonicalHost(HostPortPair server) const {
+ for (size_t i = 0; i < canoncial_suffixes_.size(); ++i) {
+ std::string canonical_suffix = canoncial_suffixes_[i];
+ if (EndsWith(server.host(), canoncial_suffixes_[i], false)) {
+ HostPortPair canonical_host(canonical_suffix, server.port());
+ return canonical_host_to_origin_map_.find(canonical_host);
+ }
}
+
+ return canonical_host_to_origin_map_.end();
}
-void HttpServerPropertiesImpl::ClearPipelineCapabilities() {
- pipeline_capability_map_->Clear();
+void HttpServerPropertiesImpl::ExpireBrokenAlternateProtocolMappings() {
+ base::TimeTicks now = base::TimeTicks::Now();
+ while (!broken_alternate_protocol_list_.empty()) {
+ BrokenAlternateProtocolEntry entry =
+ broken_alternate_protocol_list_.front();
+ if (now < entry.when) {
+ break;
+ }
+
+ ClearAlternateProtocol(entry.server);
+ broken_alternate_protocol_list_.pop_front();
+ }
+ ScheduleBrokenAlternateProtocolMappingsExpiration();
}
-PipelineCapabilityMap
-HttpServerPropertiesImpl::GetPipelineCapabilityMap() const {
- PipelineCapabilityMap result;
- CachedPipelineCapabilityMap::const_iterator it;
- for (it = pipeline_capability_map_->begin();
- it != pipeline_capability_map_->end(); ++it) {
- result[it->first] = it->second;
+void
+HttpServerPropertiesImpl::ScheduleBrokenAlternateProtocolMappingsExpiration() {
+ if (broken_alternate_protocol_list_.empty()) {
+ return;
}
- return result;
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks when = broken_alternate_protocol_list_.front().when;
+ base::TimeDelta delay = when > now ? when - now : base::TimeDelta();
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(
+ &HttpServerPropertiesImpl::ExpireBrokenAlternateProtocolMappings,
+ weak_ptr_factory_.GetWeakPtr()),
+ delay);
}
} // namespace net
diff --git a/chromium/net/http/http_server_properties_impl.h b/chromium/net/http/http_server_properties_impl.h
index cf96b7d4f32..389c961f491 100644
--- a/chromium/net/http/http_server_properties_impl.h
+++ b/chromium/net/http/http_server_properties_impl.h
@@ -11,13 +11,11 @@
#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
-#include "base/containers/mru_cache.h"
#include "base/gtest_prod_util.h"
#include "base/threading/non_thread_safe.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
-#include "net/http/http_pipelined_host_capability.h"
#include "net/http/http_server_properties.h"
namespace base {
@@ -34,7 +32,7 @@ class NET_EXPORT HttpServerPropertiesImpl
HttpServerPropertiesImpl();
virtual ~HttpServerPropertiesImpl();
- // Initializes |spdy_servers_table_| with the servers (host/port) from
+ // Initializes |spdy_servers_map_| with the servers (host/port) from
// |spdy_servers| that either support SPDY or not.
void InitializeSpdyServers(std::vector<std::string>* spdy_servers,
bool support_spdy);
@@ -44,13 +42,10 @@ class NET_EXPORT HttpServerPropertiesImpl
void InitializeSpdySettingsServers(SpdySettingsMap* spdy_settings_map);
- // Initializes |pipeline_capability_map_| with the servers (host/port) from
- // |pipeline_capability_map| that either support HTTP pipelining or not.
- void InitializePipelineCapabilities(
- const PipelineCapabilityMap* pipeline_capability_map);
-
- // Get the list of servers (host/port) that support SPDY.
- void GetSpdyServerList(base::ListValue* spdy_server_list) const;
+ // Get the list of servers (host/port) that support SPDY. The max_size is the
+ // number of MRU servers that support SPDY that are to be returned.
+ void GetSpdyServerList(base::ListValue* spdy_server_list,
+ size_t max_size) const;
// Returns flattened string representation of the |host_port_pair|. Used by
// unittests.
@@ -63,11 +58,9 @@ class NET_EXPORT HttpServerPropertiesImpl
static void ForceAlternateProtocol(const PortAlternateProtocolPair& pair);
static void DisableForcedAlternateProtocol();
- // Changes the number of host/port pairs we remember pipelining capability
- // for. A larger number means we're more likely to be able to pipeline
- // immediately if a host is known good, but uses more memory. This function
- // can only be called if |pipeline_capability_map_| is empty.
- void SetNumPipelinedHostsToRemember(int max_size);
+ // Returns the canonical host suffix for |server|, or std::string() if none
+ // exists.
+ std::string GetCanonicalSuffix(const net::HostPortPair& server);
// -----------------------------
// HttpServerProperties methods:
@@ -80,19 +73,19 @@ class NET_EXPORT HttpServerPropertiesImpl
virtual void Clear() OVERRIDE;
// Returns true if |server| supports SPDY.
- virtual bool SupportsSpdy(const HostPortPair& server) const OVERRIDE;
+ virtual bool SupportsSpdy(const HostPortPair& server) OVERRIDE;
// Add |server| into the persistent store.
virtual void SetSupportsSpdy(const HostPortPair& server,
bool support_spdy) OVERRIDE;
// Returns true if |server| has an Alternate-Protocol header.
- virtual bool HasAlternateProtocol(const HostPortPair& server) const OVERRIDE;
+ virtual bool HasAlternateProtocol(const HostPortPair& server) OVERRIDE;
// Returns the Alternate-Protocol and port for |server|.
// HasAlternateProtocol(server) must be true.
virtual PortAlternateProtocolPair GetAlternateProtocol(
- const HostPortPair& server) const OVERRIDE;
+ const HostPortPair& server) OVERRIDE;
// Sets the Alternate-Protocol for |server|.
virtual void SetAlternateProtocol(
@@ -103,13 +96,29 @@ class NET_EXPORT HttpServerPropertiesImpl
// Sets the Alternate-Protocol for |server| to be BROKEN.
virtual void SetBrokenAlternateProtocol(const HostPortPair& server) OVERRIDE;
+ // Returns true if Alternate-Protocol for |server| was recently BROKEN.
+ virtual bool WasAlternateProtocolRecentlyBroken(
+ const HostPortPair& server) OVERRIDE;
+
+ // Confirms that Alternate-Protocol for |server| is working.
+ virtual void ConfirmAlternateProtocol(const HostPortPair& server) OVERRIDE;
+
+ // Clears the Alternate-Protocol for |server|.
+ virtual void ClearAlternateProtocol(const HostPortPair& server) OVERRIDE;
+
// Returns all Alternate-Protocol mappings.
virtual const AlternateProtocolMap& alternate_protocol_map() const OVERRIDE;
+ virtual void SetAlternateProtocolExperiment(
+ AlternateProtocolExperiment experiment) OVERRIDE;
+
+ virtual AlternateProtocolExperiment GetAlternateProtocolExperiment()
+ const OVERRIDE;
+
// Gets a reference to the SettingsMap stored for a host.
// If no settings are stored, returns an empty SettingsMap.
virtual const SettingsMap& GetSpdySettings(
- const HostPortPair& host_port_pair) const OVERRIDE;
+ const HostPortPair& host_port_pair) OVERRIDE;
// Saves an individual SPDY setting for a host. Returns true if SPDY setting
// is to be persisted.
@@ -127,29 +136,52 @@ class NET_EXPORT HttpServerPropertiesImpl
// Returns all persistent SPDY settings.
virtual const SpdySettingsMap& spdy_settings_map() const OVERRIDE;
- virtual HttpPipelinedHostCapability GetPipelineCapability(
- const HostPortPair& origin) OVERRIDE;
-
- virtual void SetPipelineCapability(
- const HostPortPair& origin,
- HttpPipelinedHostCapability capability) OVERRIDE;
-
- virtual void ClearPipelineCapabilities() OVERRIDE;
+ virtual void SetServerNetworkStats(const HostPortPair& host_port_pair,
+ NetworkStats stats) OVERRIDE;
- virtual PipelineCapabilityMap GetPipelineCapabilityMap() const OVERRIDE;
+ virtual const NetworkStats* GetServerNetworkStats(
+ const HostPortPair& host_port_pair) const OVERRIDE;
private:
- typedef base::MRUCache<
- HostPortPair, HttpPipelinedHostCapability> CachedPipelineCapabilityMap;
- // |spdy_servers_table_| has flattened representation of servers (host/port
- // pair) that either support or not support SPDY protocol.
- typedef base::hash_map<std::string, bool> SpdyServerHostPortTable;
-
- SpdyServerHostPortTable spdy_servers_table_;
+ // |spdy_servers_map_| has flattened representation of servers (host, port)
+ // that either support or not support SPDY protocol.
+ typedef base::MRUCache<std::string, bool> SpdyServerHostPortMap;
+ typedef std::map<HostPortPair, NetworkStats> ServerNetworkStatsMap;
+ typedef std::map<HostPortPair, HostPortPair> CanonicalHostMap;
+ typedef std::vector<std::string> CanonicalSufficList;
+ // List of broken host:ports and the times when they can be expired.
+ struct BrokenAlternateProtocolEntry {
+ HostPortPair server;
+ base::TimeTicks when;
+ };
+ typedef std::list<BrokenAlternateProtocolEntry>
+ BrokenAlternateProtocolList;
+ // Map from host:port to the number of times alternate protocol has
+ // been marked broken.
+ typedef std::map<HostPortPair, int> BrokenAlternateProtocolMap;
+
+ // Return the canonical host for |server|, or end if none exists.
+ CanonicalHostMap::const_iterator GetCanonicalHost(HostPortPair server) const;
+
+ void ExpireBrokenAlternateProtocolMappings();
+ void ScheduleBrokenAlternateProtocolMappingsExpiration();
+
+ SpdyServerHostPortMap spdy_servers_map_;
AlternateProtocolMap alternate_protocol_map_;
+ BrokenAlternateProtocolList broken_alternate_protocol_list_;
+ BrokenAlternateProtocolMap broken_alternate_protocol_map_;
+ AlternateProtocolExperiment alternate_protocol_experiment_;
+
SpdySettingsMap spdy_settings_map_;
- scoped_ptr<CachedPipelineCapabilityMap> pipeline_capability_map_;
+ ServerNetworkStatsMap server_network_stats_map_;
+ // Contains a map of servers which could share the same alternate protocol.
+ // Map from a Canonical host/port (host is some postfix of host names) to an
+ // actual origin, which has a plausible alternate protocol mapping.
+ CanonicalHostMap canonical_host_to_origin_map_;
+ // Contains list of suffixes (for exmaple ".c.youtube.com",
+ // ".googlevideo.com", ".googleusercontent.com") of canoncial hostnames.
+ CanonicalSufficList canoncial_suffixes_;
base::WeakPtrFactory<HttpServerPropertiesImpl> weak_ptr_factory_;
diff --git a/chromium/net/http/http_server_properties_impl_unittest.cc b/chromium/net/http/http_server_properties_impl_unittest.cc
index cf3a4643f9d..c8014741d7a 100644
--- a/chromium/net/http/http_server_properties_impl_unittest.cc
+++ b/chromium/net/http/http_server_properties_impl_unittest.cc
@@ -21,6 +21,8 @@ class ListValue;
namespace net {
+const int kMaxSupportsSpdyServerHosts = 500;
+
namespace {
class HttpServerPropertiesImplTest : public testing::Test {
@@ -60,6 +62,17 @@ TEST_F(SpdyServerPropertiesTest, Initialize) {
spdy_servers2.push_back(spdy_server_g);
spdy_servers2.push_back(spdy_server_d);
impl_.InitializeSpdyServers(&spdy_servers2, true);
+
+ // Verify spdy_server_g and spdy_server_d are in the list in the same order.
+ base::ListValue spdy_server_list;
+ impl_.GetSpdyServerList(&spdy_server_list, kMaxSupportsSpdyServerHosts);
+ EXPECT_EQ(2U, spdy_server_list.GetSize());
+ std::string string_value_g;
+ ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_g));
+ ASSERT_EQ(spdy_server_g, string_value_g);
+ std::string string_value_d;
+ ASSERT_TRUE(spdy_server_list.GetString(1, &string_value_d));
+ ASSERT_EQ(spdy_server_d, string_value_d);
EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_google));
EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_docs));
}
@@ -130,13 +143,13 @@ TEST_F(SpdyServerPropertiesTest, GetSpdyServerList) {
base::ListValue spdy_server_list;
// Check there are no spdy_servers.
- impl_.GetSpdyServerList(&spdy_server_list);
+ impl_.GetSpdyServerList(&spdy_server_list, kMaxSupportsSpdyServerHosts);
EXPECT_EQ(0U, spdy_server_list.GetSize());
// Check empty server is not added.
HostPortPair spdy_server_empty(std::string(), 443);
impl_.SetSupportsSpdy(spdy_server_empty, true);
- impl_.GetSpdyServerList(&spdy_server_list);
+ impl_.GetSpdyServerList(&spdy_server_list, kMaxSupportsSpdyServerHosts);
EXPECT_EQ(0U, spdy_server_list.GetSize());
std::string string_value_g;
@@ -150,38 +163,79 @@ TEST_F(SpdyServerPropertiesTest, GetSpdyServerList) {
// Add www.google.com:443 as not supporting SPDY.
impl_.SetSupportsSpdy(spdy_server_google, false);
- impl_.GetSpdyServerList(&spdy_server_list);
+ impl_.GetSpdyServerList(&spdy_server_list, kMaxSupportsSpdyServerHosts);
EXPECT_EQ(0U, spdy_server_list.GetSize());
// Add www.google.com:443 as supporting SPDY.
impl_.SetSupportsSpdy(spdy_server_google, true);
- impl_.GetSpdyServerList(&spdy_server_list);
+ impl_.GetSpdyServerList(&spdy_server_list, kMaxSupportsSpdyServerHosts);
ASSERT_EQ(1U, spdy_server_list.GetSize());
ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_g));
ASSERT_EQ(spdy_server_g, string_value_g);
// Add mail.google.com:443 as not supporting SPDY.
impl_.SetSupportsSpdy(spdy_server_mail, false);
- impl_.GetSpdyServerList(&spdy_server_list);
+ impl_.GetSpdyServerList(&spdy_server_list, kMaxSupportsSpdyServerHosts);
ASSERT_EQ(1U, spdy_server_list.GetSize());
ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_g));
ASSERT_EQ(spdy_server_g, string_value_g);
// Add mail.google.com:443 as supporting SPDY.
impl_.SetSupportsSpdy(spdy_server_mail, true);
- impl_.GetSpdyServerList(&spdy_server_list);
+ impl_.GetSpdyServerList(&spdy_server_list, kMaxSupportsSpdyServerHosts);
ASSERT_EQ(2U, spdy_server_list.GetSize());
// Verify www.google.com:443 and mail.google.com:443 are in the list.
+ ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_m));
+ ASSERT_EQ(spdy_server_m, string_value_m);
+ ASSERT_TRUE(spdy_server_list.GetString(1, &string_value_g));
+ ASSERT_EQ(spdy_server_g, string_value_g);
+
+ // Request for only one server and verify that we get only one server.
+ impl_.GetSpdyServerList(&spdy_server_list, 1);
+ ASSERT_EQ(1U, spdy_server_list.GetSize());
+ ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_m));
+ ASSERT_EQ(spdy_server_m, string_value_m);
+}
+
+TEST_F(SpdyServerPropertiesTest, MRUOfGetSpdyServerList) {
+ base::ListValue spdy_server_list;
+
+ std::string string_value_g;
+ std::string string_value_m;
+ HostPortPair spdy_server_google("www.google.com", 443);
+ std::string spdy_server_g =
+ HttpServerPropertiesImpl::GetFlattenedSpdyServer(spdy_server_google);
+ HostPortPair spdy_server_mail("mail.google.com", 443);
+ std::string spdy_server_m =
+ HttpServerPropertiesImpl::GetFlattenedSpdyServer(spdy_server_mail);
+
+ // Add www.google.com:443 as supporting SPDY.
+ impl_.SetSupportsSpdy(spdy_server_google, true);
+ impl_.GetSpdyServerList(&spdy_server_list, kMaxSupportsSpdyServerHosts);
+ ASSERT_EQ(1U, spdy_server_list.GetSize());
+ ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_g));
+ ASSERT_EQ(spdy_server_g, string_value_g);
+
+ // Add mail.google.com:443 as supporting SPDY. Verify mail.google.com:443 and
+ // www.google.com:443 are in the list.
+ impl_.SetSupportsSpdy(spdy_server_mail, true);
+ impl_.GetSpdyServerList(&spdy_server_list, kMaxSupportsSpdyServerHosts);
+ ASSERT_EQ(2U, spdy_server_list.GetSize());
+ ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_m));
+ ASSERT_EQ(spdy_server_m, string_value_m);
+ ASSERT_TRUE(spdy_server_list.GetString(1, &string_value_g));
+ ASSERT_EQ(spdy_server_g, string_value_g);
+
+ // Get www.google.com:443 should reorder SpdyServerHostPortMap. Verify that it
+ // is www.google.com:443 is the MRU server.
+ EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_google));
+ impl_.GetSpdyServerList(&spdy_server_list, kMaxSupportsSpdyServerHosts);
+ ASSERT_EQ(2U, spdy_server_list.GetSize());
ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_g));
+ ASSERT_EQ(spdy_server_g, string_value_g);
ASSERT_TRUE(spdy_server_list.GetString(1, &string_value_m));
- if (string_value_g.compare(spdy_server_g) == 0) {
- ASSERT_EQ(spdy_server_g, string_value_g);
- ASSERT_EQ(spdy_server_m, string_value_m);
- } else {
- ASSERT_EQ(spdy_server_g, string_value_m);
- ASSERT_EQ(spdy_server_m, string_value_g);
- }
+ ASSERT_EQ(spdy_server_m, string_value_m);
}
typedef HttpServerPropertiesImplTest AlternateProtocolServerPropertiesTest;
@@ -206,13 +260,27 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
HostPortPair test_host_port_pair2("foo2", 80);
impl_.SetAlternateProtocol(test_host_port_pair2, 443, NPN_SPDY_3);
- AlternateProtocolMap alternate_protocol_map;
+ AlternateProtocolMap alternate_protocol_map(
+ AlternateProtocolMap::NO_AUTO_EVICT);
PortAlternateProtocolPair port_alternate_protocol_pair;
port_alternate_protocol_pair.port = 123;
port_alternate_protocol_pair.protocol = NPN_SPDY_3;
- alternate_protocol_map[test_host_port_pair2] = port_alternate_protocol_pair;
+ alternate_protocol_map.Put(test_host_port_pair2,
+ port_alternate_protocol_pair);
+ HostPortPair test_host_port_pair3("foo3", 80);
+ port_alternate_protocol_pair.port = 1234;
+ alternate_protocol_map.Put(test_host_port_pair3,
+ port_alternate_protocol_pair);
impl_.InitializeAlternateProtocolServers(&alternate_protocol_map);
+ // Verify test_host_port_pair3 is the MRU server.
+ const net::AlternateProtocolMap& map = impl_.alternate_protocol_map();
+ net::AlternateProtocolMap::const_iterator it = map.begin();
+ it = map.begin();
+ EXPECT_TRUE(it->first.Equals(test_host_port_pair3));
+ EXPECT_EQ(1234, it->second.port);
+ EXPECT_EQ(NPN_SPDY_3, it->second.protocol);
+
ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair1));
ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair2));
port_alternate_protocol_pair =
@@ -224,6 +292,49 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
EXPECT_EQ(NPN_SPDY_3, port_alternate_protocol_pair.protocol);
}
+TEST_F(AlternateProtocolServerPropertiesTest, MRUOfHasAlternateProtocol) {
+ HostPortPair test_host_port_pair1("foo1", 80);
+ impl_.SetAlternateProtocol(test_host_port_pair1, 443, NPN_SPDY_3);
+ HostPortPair test_host_port_pair2("foo2", 80);
+ impl_.SetAlternateProtocol(test_host_port_pair2, 1234, NPN_SPDY_3);
+
+ const net::AlternateProtocolMap& map = impl_.alternate_protocol_map();
+ net::AlternateProtocolMap::const_iterator it = map.begin();
+ EXPECT_TRUE(it->first.Equals(test_host_port_pair2));
+ EXPECT_EQ(1234, it->second.port);
+ EXPECT_EQ(NPN_SPDY_3, it->second.protocol);
+
+ // HasAlternateProtocol should reoder the AlternateProtocol map.
+ ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair1));
+ it = map.begin();
+ EXPECT_TRUE(it->first.Equals(test_host_port_pair1));
+ EXPECT_EQ(443, it->second.port);
+ EXPECT_EQ(NPN_SPDY_3, it->second.protocol);
+}
+
+TEST_F(AlternateProtocolServerPropertiesTest, MRUOfGetAlternateProtocol) {
+ HostPortPair test_host_port_pair1("foo1", 80);
+ impl_.SetAlternateProtocol(test_host_port_pair1, 443, NPN_SPDY_3);
+ HostPortPair test_host_port_pair2("foo2", 80);
+ impl_.SetAlternateProtocol(test_host_port_pair2, 1234, NPN_SPDY_3);
+
+ const net::AlternateProtocolMap& map = impl_.alternate_protocol_map();
+ net::AlternateProtocolMap::const_iterator it = map.begin();
+ EXPECT_TRUE(it->first.Equals(test_host_port_pair2));
+ EXPECT_EQ(1234, it->second.port);
+ EXPECT_EQ(NPN_SPDY_3, it->second.protocol);
+
+ // GetAlternateProtocol should reoder the AlternateProtocol map.
+ PortAlternateProtocolPair alternate =
+ impl_.GetAlternateProtocol(test_host_port_pair1);
+ EXPECT_EQ(443, alternate.port);
+ EXPECT_EQ(NPN_SPDY_3, alternate.protocol);
+ it = map.begin();
+ EXPECT_TRUE(it->first.Equals(test_host_port_pair1));
+ EXPECT_EQ(443, it->second.port);
+ EXPECT_EQ(NPN_SPDY_3, it->second.protocol);
+}
+
TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
HostPortPair test_host_port_pair("foo", 80);
impl_.SetBrokenAlternateProtocol(test_host_port_pair);
@@ -241,6 +352,17 @@ TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
<< "Second attempt should be ignored.";
}
+TEST_F(AlternateProtocolServerPropertiesTest, ClearBroken) {
+ HostPortPair test_host_port_pair("foo", 80);
+ impl_.SetBrokenAlternateProtocol(test_host_port_pair);
+ ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+ PortAlternateProtocolPair alternate =
+ impl_.GetAlternateProtocol(test_host_port_pair);
+ EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
+ impl_.ClearAlternateProtocol(test_host_port_pair);
+ EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+}
+
TEST_F(AlternateProtocolServerPropertiesTest, Forced) {
// Test forced alternate protocols.
@@ -273,13 +395,39 @@ TEST_F(AlternateProtocolServerPropertiesTest, Forced) {
EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair2));
}
+TEST_F(AlternateProtocolServerPropertiesTest, Canonical) {
+ HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
+ EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+
+ HostPortPair canonical_port_pair("bar.c.youtube.com", 80);
+ EXPECT_FALSE(impl_.HasAlternateProtocol(canonical_port_pair));
+
+ PortAlternateProtocolPair canonical_protocol;
+ canonical_protocol.port = 1234;
+ canonical_protocol.protocol = QUIC;
+
+ impl_.SetAlternateProtocol(canonical_port_pair,
+ canonical_protocol.port,
+ canonical_protocol.protocol);
+ // Verify the forced protocol.
+ ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+ PortAlternateProtocolPair alternate =
+ impl_.GetAlternateProtocol(test_host_port_pair);
+ EXPECT_EQ(canonical_protocol.port, alternate.port);
+ EXPECT_EQ(canonical_protocol.protocol, alternate.protocol);
+
+ // Verify the canonical suffix.
+ EXPECT_EQ(".c.youtube.com", impl_.GetCanonicalSuffix(test_host_port_pair));
+ EXPECT_EQ(".c.youtube.com", impl_.GetCanonicalSuffix(canonical_port_pair));
+}
+
typedef HttpServerPropertiesImplTest SpdySettingsServerPropertiesTest;
TEST_F(SpdySettingsServerPropertiesTest, Initialize) {
HostPortPair spdy_server_google("www.google.com", 443);
// Check by initializing empty spdy settings.
- SpdySettingsMap spdy_settings_map;
+ SpdySettingsMap spdy_settings_map(SpdySettingsMap::NO_AUTO_EVICT);
impl_.InitializeSpdySettingsServers(&spdy_settings_map);
EXPECT_TRUE(impl_.GetSpdySettings(spdy_server_google).empty());
@@ -290,7 +438,7 @@ TEST_F(SpdySettingsServerPropertiesTest, Initialize) {
const uint32 value = 31337;
SettingsFlagsAndValue flags_and_value(flags, value);
settings_map[id] = flags_and_value;
- spdy_settings_map[spdy_server_google] = settings_map;
+ spdy_settings_map.Put(spdy_server_google, settings_map);
impl_.InitializeSpdySettingsServers(&spdy_settings_map);
const SettingsMap& settings_map2 = impl_.GetSpdySettings(spdy_server_google);
@@ -411,6 +559,55 @@ TEST_F(SpdySettingsServerPropertiesTest, Clear) {
EXPECT_EQ(0U, impl_.GetSpdySettings(spdy_server_docs).size());
}
+TEST_F(SpdySettingsServerPropertiesTest, MRUOfGetSpdySettings) {
+ // Add www.google.com:443 as persisting.
+ HostPortPair spdy_server_google("www.google.com", 443);
+ const SpdySettingsIds id1 = SETTINGS_UPLOAD_BANDWIDTH;
+ const SpdySettingsFlags flags1 = SETTINGS_FLAG_PLEASE_PERSIST;
+ const uint32 value1 = 31337;
+ EXPECT_TRUE(impl_.SetSpdySetting(spdy_server_google, id1, flags1, value1));
+
+ // Add docs.google.com:443 as persisting
+ HostPortPair spdy_server_docs("docs.google.com", 443);
+ const SpdySettingsIds id2 = SETTINGS_ROUND_TRIP_TIME;
+ const SpdySettingsFlags flags2 = SETTINGS_FLAG_PLEASE_PERSIST;
+ const uint32 value2 = 93997;
+ EXPECT_TRUE(impl_.SetSpdySetting(spdy_server_docs, id2, flags2, value2));
+
+ // Verify the first element is docs.google.com:443.
+ const net::SpdySettingsMap& map = impl_.spdy_settings_map();
+ net::SpdySettingsMap::const_iterator it = map.begin();
+ EXPECT_TRUE(it->first.Equals(spdy_server_docs));
+ const SettingsMap& settings_map2_ret = it->second;
+ ASSERT_EQ(1U, settings_map2_ret.size());
+ SettingsMap::const_iterator it2_ret = settings_map2_ret.find(id2);
+ EXPECT_TRUE(it2_ret != settings_map2_ret.end());
+ SettingsFlagsAndValue flags_and_value2_ret = it2_ret->second;
+ EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2_ret.first);
+ EXPECT_EQ(value2, flags_and_value2_ret.second);
+
+ // GetSpdySettings should reoder the SpdySettingsMap.
+ const SettingsMap& settings_map1_ret =
+ impl_.GetSpdySettings(spdy_server_google);
+ ASSERT_EQ(1U, settings_map1_ret.size());
+ SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
+ EXPECT_TRUE(it1_ret != settings_map1_ret.end());
+ SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
+ EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
+ EXPECT_EQ(value1, flags_and_value1_ret.second);
+
+ // Check the first entry is spdy_server_google by accessing it via iterator.
+ it = map.begin();
+ EXPECT_TRUE(it->first.Equals(spdy_server_google));
+ const SettingsMap& settings_map1_it_ret = it->second;
+ ASSERT_EQ(1U, settings_map1_it_ret.size());
+ it1_ret = settings_map1_it_ret.find(id1);
+ EXPECT_TRUE(it1_ret != settings_map1_it_ret.end());
+ flags_and_value1_ret = it1_ret->second;
+ EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
+ EXPECT_EQ(value1, flags_and_value1_ret.second);
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/http/http_stream.h b/chromium/net/http/http_stream.h
index 3680db3f862..22362e28991 100644
--- a/chromium/net/http/http_stream.h
+++ b/chromium/net/http/http_stream.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// HttpStream provides an abstraction for a basic http streams, http pipelining
-// implementations, and SPDY. The HttpStream subtype is expected to manage the
-// underlying transport appropriately. For example, a non-pipelined HttpStream
-// would return the transport socket to the pool for reuse. SPDY streams on the
-// other hand leave the transport socket management to the SpdySession.
+// HttpStream provides an abstraction for a basic http streams, SPDY, and QUIC.
+// The HttpStream subtype is expected to manage the underlying transport
+// appropriately. For example, a basic http stream will return the transport
+// socket to the pool for reuse. SPDY streams on the other hand leave the
+// transport socket management to the SpdySession.
#ifndef NET_HTTP_HTTP_STREAM_H_
#define NET_HTTP_HTTP_STREAM_H_
diff --git a/chromium/net/http/http_stream_base.h b/chromium/net/http/http_stream_base.h
index f5dcc29409e..76e57ef8ff8 100644
--- a/chromium/net/http/http_stream_base.h
+++ b/chromium/net/http/http_stream_base.h
@@ -48,21 +48,30 @@ class NET_EXPORT_PRIVATE HttpStreamBase {
// ERR_IO_PENDING is returned if the operation could not be completed
// synchronously, in which case the result will be passed to the callback
// when available. Returns OK on success.
- // |response| must outlive the HttpStreamBase.
+ //
+ // The callback will only be invoked once the first full set of headers have
+ // been received, at which point |response| will have been populated with that
+ // set of headers, and is safe to read, until/unless ReadResponseHeaders is
+ // called.
+ //
+ // |response| must remain valid until all sets of headers has been read, or
+ // the HttpStreamBase is destroyed. There's typically only one set of
+ // headers, except in the case of 1xx responses (See ReadResponseHeaders).
virtual int SendRequest(const HttpRequestHeaders& request_headers,
HttpResponseInfo* response,
const CompletionCallback& callback) = 0;
- // Reads from the underlying socket until the response headers have been
- // completely received. ERR_IO_PENDING is returned if the operation could
- // not be completed synchronously, in which case the result will be passed
- // to the callback when available. Returns OK on success. The response
- // headers are available in the HttpResponseInfo returned by GetResponseInfo
+ // Reads from the underlying socket until the next set of response headers
+ // have been completely received. This may only be called on 1xx responses
+ // after SendRequest has completed successfully, to read the next set of
+ // headers.
+ //
+ // ERR_IO_PENDING is returned if the operation could not be completed
+ // synchronously, in which case the result will be passed to the callback when
+ // available. Returns OK on success. The response headers are available in
+ // the HttpResponseInfo passed in to original call to SendRequest.
virtual int ReadResponseHeaders(const CompletionCallback& callback) = 0;
- // Provides access to HttpResponseInfo (owned by HttpStream).
- virtual const HttpResponseInfo* GetResponseInfo() const = 0;
-
// Reads response body data, up to |buf_len| bytes. |buf_len| should be a
// reasonable size (<2MB). The number of bytes read is returned, or an
// error is returned upon failure. 0 indicates that the request has been
diff --git a/chromium/net/http/http_stream_factory.cc b/chromium/net/http/http_stream_factory.cc
index e88046fba3c..70d1101d07b 100644
--- a/chromium/net/http/http_stream_factory.cc
+++ b/chromium/net/http/http_stream_factory.cc
@@ -1,261 +1,99 @@
-// Copyright (c) 2012 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.
-
-#include "net/http/http_stream_factory.h"
-
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "net/base/host_mapping_rules.h"
-#include "net/base/host_port_pair.h"
-#include "url/gurl.h"
-
-namespace net {
-
-// WARNING: If you modify or add any static flags, you must keep them in sync
-// with |ResetStaticSettingsToInit|. This is critical for unit test isolation.
-
-// static
-std::vector<std::string>* HttpStreamFactory::next_protos_ = NULL;
-// static
-bool HttpStreamFactory::enabled_protocols_[NUM_VALID_ALTERNATE_PROTOCOLS];
-// static
-bool HttpStreamFactory::spdy_enabled_ = true;
-// static
-bool HttpStreamFactory::use_alternate_protocols_ = false;
-// static
-bool HttpStreamFactory::force_spdy_over_ssl_ = true;
-// static
-bool HttpStreamFactory::force_spdy_always_ = false;
-// static
-std::list<HostPortPair>* HttpStreamFactory::forced_spdy_exclusions_ = NULL;
-
-HttpStreamFactory::~HttpStreamFactory() {}
-
-// static
-bool HttpStreamFactory::IsProtocolEnabled(AlternateProtocol protocol) {
- DCHECK(IsAlternateProtocolValid(protocol));
- return enabled_protocols_[
- protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION];
-}
-
-// static
-void HttpStreamFactory::SetProtocolEnabled(AlternateProtocol protocol) {
- DCHECK(IsAlternateProtocolValid(protocol));
- enabled_protocols_[
- protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] = true;
-}
-
-// static
-void HttpStreamFactory::ResetEnabledProtocols() {
- for (int i = ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION;
- i <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION; ++i) {
- enabled_protocols_[i - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] = false;
- }
-}
-
-// static
-void HttpStreamFactory::ResetStaticSettingsToInit() {
- // WARNING: These must match the initializers above.
- delete next_protos_;
- delete forced_spdy_exclusions_;
- next_protos_ = NULL;
- spdy_enabled_ = true;
- use_alternate_protocols_ = false;
- force_spdy_over_ssl_ = true;
- force_spdy_always_ = false;
- forced_spdy_exclusions_ = NULL;
- ResetEnabledProtocols();
-}
-
-void HttpStreamFactory::ProcessAlternateProtocol(
- const base::WeakPtr<HttpServerProperties>& http_server_properties,
- const std::string& alternate_protocol_str,
- const HostPortPair& http_host_port_pair) {
- std::vector<std::string> port_protocol_vector;
- base::SplitString(alternate_protocol_str, ':', &port_protocol_vector);
- if (port_protocol_vector.size() != 2) {
- DVLOG(1) << kAlternateProtocolHeader
- << " header has too many tokens: "
- << alternate_protocol_str;
- return;
- }
-
- int port;
- if (!base::StringToInt(port_protocol_vector[0], &port) ||
- port <= 0 || port >= 1 << 16) {
- DVLOG(1) << kAlternateProtocolHeader
- << " header has unrecognizable port: "
- << port_protocol_vector[0];
- return;
- }
-
- AlternateProtocol protocol =
- AlternateProtocolFromString(port_protocol_vector[1]);
- if (IsAlternateProtocolValid(protocol) && !IsProtocolEnabled(protocol)) {
- protocol = ALTERNATE_PROTOCOL_BROKEN;
- }
-
- if (protocol == ALTERNATE_PROTOCOL_BROKEN) {
- DVLOG(1) << kAlternateProtocolHeader
- << " header has unrecognized protocol: "
- << port_protocol_vector[1];
- return;
- }
-
- HostPortPair host_port(http_host_port_pair);
- const HostMappingRules* mapping_rules = GetHostMappingRules();
- if (mapping_rules)
- mapping_rules->RewriteHost(&host_port);
-
- if (http_server_properties->HasAlternateProtocol(host_port)) {
- const PortAlternateProtocolPair existing_alternate =
- http_server_properties->GetAlternateProtocol(host_port);
- // If we think the alternate protocol is broken, don't change it.
- if (existing_alternate.protocol == ALTERNATE_PROTOCOL_BROKEN)
- return;
- }
-
- http_server_properties->SetAlternateProtocol(host_port, port, protocol);
-}
-
-GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url,
- HostPortPair* endpoint) {
- const HostMappingRules* mapping_rules = GetHostMappingRules();
- if (mapping_rules && mapping_rules->RewriteHost(endpoint)) {
- url_canon::Replacements<char> replacements;
- const std::string port_str = base::IntToString(endpoint->port());
- replacements.SetPort(port_str.c_str(),
- url_parse::Component(0, port_str.size()));
- replacements.SetHost(endpoint->host().c_str(),
- url_parse::Component(0, endpoint->host().size()));
- return url.ReplaceComponents(replacements);
- }
- return url;
-}
-
-// static
-void HttpStreamFactory::add_forced_spdy_exclusion(const std::string& value) {
- HostPortPair pair = HostPortPair::FromURL(GURL(value));
- if (!forced_spdy_exclusions_)
- forced_spdy_exclusions_ = new std::list<HostPortPair>();
- forced_spdy_exclusions_->push_back(pair);
-}
-
-// static
-bool HttpStreamFactory::HasSpdyExclusion(const HostPortPair& endpoint) {
- std::list<HostPortPair>* exclusions = forced_spdy_exclusions_;
- if (!exclusions)
- return false;
-
- std::list<HostPortPair>::const_iterator it;
- for (it = exclusions->begin(); it != exclusions->end(); ++it)
- if (it->Equals(endpoint))
- return true;
- return false;
-}
-
-// static
-void HttpStreamFactory::EnableNpnHttpOnly() {
- // Avoid alternate protocol in this case. Otherwise, browser will try SSL
- // and then fallback to http. This introduces extra load.
- set_use_alternate_protocols(false);
- std::vector<NextProto> next_protos;
- next_protos.push_back(kProtoHTTP11);
- SetNextProtos(next_protos);
-}
-
-// static
-void HttpStreamFactory::EnableNpnSpdy3() {
- set_use_alternate_protocols(true);
- std::vector<NextProto> next_protos;
- next_protos.push_back(kProtoHTTP11);
- next_protos.push_back(kProtoQUIC1SPDY3);
- next_protos.push_back(kProtoSPDY3);
- SetNextProtos(next_protos);
-}
-
-// static
-void HttpStreamFactory::EnableNpnSpdy31() {
- set_use_alternate_protocols(true);
- std::vector<NextProto> next_protos;
- next_protos.push_back(kProtoHTTP11);
- next_protos.push_back(kProtoQUIC1SPDY3);
- next_protos.push_back(kProtoSPDY3);
- next_protos.push_back(kProtoSPDY31);
- SetNextProtos(next_protos);
-}
-
-// static
-void HttpStreamFactory::EnableNpnSpdy31WithSpdy2() {
- set_use_alternate_protocols(true);
- std::vector<NextProto> next_protos;
- next_protos.push_back(kProtoHTTP11);
- next_protos.push_back(kProtoQUIC1SPDY3);
- next_protos.push_back(kProtoDeprecatedSPDY2);
- next_protos.push_back(kProtoSPDY3);
- next_protos.push_back(kProtoSPDY31);
- SetNextProtos(next_protos);
-}
-
-// static
-void HttpStreamFactory::EnableNpnSpdy4a2() {
- set_use_alternate_protocols(true);
- std::vector<NextProto> next_protos;
- next_protos.push_back(kProtoHTTP11);
- next_protos.push_back(kProtoQUIC1SPDY3);
- next_protos.push_back(kProtoSPDY3);
- next_protos.push_back(kProtoSPDY31);
- next_protos.push_back(kProtoSPDY4a2);
- SetNextProtos(next_protos);
-}
-
-// static
-void HttpStreamFactory::EnableNpnHttp2Draft04() {
- set_use_alternate_protocols(true);
- std::vector<NextProto> next_protos;
- next_protos.push_back(kProtoHTTP11);
- next_protos.push_back(kProtoQUIC1SPDY3);
- next_protos.push_back(kProtoSPDY3);
- next_protos.push_back(kProtoSPDY31);
- next_protos.push_back(kProtoSPDY4a2);
- next_protos.push_back(kProtoHTTP2Draft04);
- SetNextProtos(next_protos);
-}
-
-// static
-void HttpStreamFactory::SetNextProtos(const std::vector<NextProto>& value) {
- if (!next_protos_)
- next_protos_ = new std::vector<std::string>;
-
- next_protos_->clear();
-
- ResetEnabledProtocols();
-
- // TODO(rtenneti): bug 116575 - consider combining the NextProto and
- // AlternateProtocol.
- for (uint32 i = 0; i < value.size(); ++i) {
- NextProto proto = value[i];
- // Add the protocol to the TLS next protocol list, except for QUIC
- // since it uses UDP.
- if (proto != kProtoQUIC1SPDY3) {
- next_protos_->push_back(SSLClientSocket::NextProtoToString(proto));
- }
-
- // Enable the corresponding alternate protocol, except for HTTP
- // which has not corresponding alternative.
- if (proto != kProtoHTTP11) {
- AlternateProtocol alternate = AlternateProtocolFromNextProto(proto);
- if (!IsAlternateProtocolValid(alternate)) {
- NOTREACHED() << "Invalid next proto: " << proto;
- continue;
- }
- SetProtocolEnabled(alternate);
- }
- }
-}
-
-HttpStreamFactory::HttpStreamFactory() {}
-
-} // namespace net
+// Copyright (c) 2012 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.
+
+#include "net/http/http_stream_factory.h"
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "net/base/host_mapping_rules.h"
+#include "net/base/host_port_pair.h"
+#include "net/http/http_network_session.h"
+#include "url/gurl.h"
+
+namespace net {
+
+// WARNING: If you modify or add any static flags, you must keep them in sync
+// with |ResetStaticSettingsToInit|. This is critical for unit test isolation.
+
+// static
+bool HttpStreamFactory::spdy_enabled_ = true;
+
+HttpStreamFactory::~HttpStreamFactory() {}
+
+// static
+void HttpStreamFactory::ResetStaticSettingsToInit() {
+ spdy_enabled_ = true;
+}
+
+void HttpStreamFactory::ProcessAlternateProtocol(
+ const base::WeakPtr<HttpServerProperties>& http_server_properties,
+ const std::string& alternate_protocol_str,
+ const HostPortPair& http_host_port_pair,
+ const HttpNetworkSession& session) {
+ std::vector<std::string> port_protocol_vector;
+ base::SplitString(alternate_protocol_str, ':', &port_protocol_vector);
+ if (port_protocol_vector.size() != 2) {
+ DVLOG(1) << kAlternateProtocolHeader
+ << " header has too many tokens: "
+ << alternate_protocol_str;
+ return;
+ }
+
+ int port;
+ if (!base::StringToInt(port_protocol_vector[0], &port) ||
+ port <= 0 || port >= 1 << 16) {
+ DVLOG(1) << kAlternateProtocolHeader
+ << " header has unrecognizable port: "
+ << port_protocol_vector[0];
+ return;
+ }
+
+ AlternateProtocol protocol =
+ AlternateProtocolFromString(port_protocol_vector[1]);
+ if (IsAlternateProtocolValid(protocol) &&
+ !session.IsProtocolEnabled(protocol)) {
+ protocol = ALTERNATE_PROTOCOL_BROKEN;
+ }
+
+ if (protocol == ALTERNATE_PROTOCOL_BROKEN) {
+ DVLOG(1) << kAlternateProtocolHeader
+ << " header has unrecognized protocol: "
+ << port_protocol_vector[1];
+ return;
+ }
+
+ HostPortPair host_port(http_host_port_pair);
+ const HostMappingRules* mapping_rules = GetHostMappingRules();
+ if (mapping_rules)
+ mapping_rules->RewriteHost(&host_port);
+
+ if (http_server_properties->HasAlternateProtocol(host_port)) {
+ const PortAlternateProtocolPair existing_alternate =
+ http_server_properties->GetAlternateProtocol(host_port);
+ // If we think the alternate protocol is broken, don't change it.
+ if (existing_alternate.protocol == ALTERNATE_PROTOCOL_BROKEN)
+ return;
+ }
+
+ http_server_properties->SetAlternateProtocol(host_port, port, protocol);
+}
+
+GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url,
+ HostPortPair* endpoint) {
+ const HostMappingRules* mapping_rules = GetHostMappingRules();
+ if (mapping_rules && mapping_rules->RewriteHost(endpoint)) {
+ url::Replacements<char> replacements;
+ const std::string port_str = base::IntToString(endpoint->port());
+ replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
+ replacements.SetHost(endpoint->host().c_str(),
+ url::Component(0, endpoint->host().size()));
+ return url.ReplaceComponents(replacements);
+ }
+ return url;
+}
+
+HttpStreamFactory::HttpStreamFactory() {}
+
+} // namespace net
diff --git a/chromium/net/http/http_stream_factory.h b/chromium/net/http/http_stream_factory.h
index 0d854a5dd9d..f3b0203ccfb 100644
--- a/chromium/net/http/http_stream_factory.h
+++ b/chromium/net/http/http_stream_factory.h
@@ -7,7 +7,6 @@
#include <list>
#include <string>
-#include <vector>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
@@ -17,7 +16,6 @@
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
#include "net/http/http_server_properties.h"
-#include "net/socket/ssl_client_socket.h"
// This file can be included from net/http even though
// it is in net/websockets because it doesn't
// introduce any link dependency to net/websockets.
@@ -36,6 +34,7 @@ class BoundNetLog;
class HostMappingRules;
class HostPortPair;
class HttpAuthController;
+class HttpNetworkSession;
class HttpResponseInfo;
class HttpServerProperties;
class HttpStreamBase;
@@ -181,7 +180,8 @@ class NET_EXPORT HttpStreamFactory {
void ProcessAlternateProtocol(
const base::WeakPtr<HttpServerProperties>& http_server_properties,
const std::string& alternate_protocol_str,
- const HostPortPair& http_host_port_pair);
+ const HostPortPair& http_host_port_pair,
+ const HttpNetworkSession& session);
GURL ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint);
@@ -216,11 +216,6 @@ class NET_EXPORT HttpStreamFactory {
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config) = 0;
- // If pipelining is supported, creates a Value summary of the currently active
- // pipelines. Caller assumes ownership of the returned value. Otherwise,
- // returns an empty Value.
- virtual base::Value* PipelineInfoToValue() const = 0;
-
virtual const HostMappingRules* GetHostMappingRules() const = 0;
// Static settings
@@ -229,87 +224,18 @@ class NET_EXPORT HttpStreamFactory {
static void ResetStaticSettingsToInit();
// Turns spdy on or off.
+ // TODO(mmenke): Figure out if this can be made a property of the
+ // HttpNetworkSession.
static void set_spdy_enabled(bool value) {
spdy_enabled_ = value;
- if (!spdy_enabled_) {
- delete next_protos_;
- next_protos_ = NULL;
- }
}
static bool spdy_enabled() { return spdy_enabled_; }
- // Controls whether or not we use the Alternate-Protocol header.
- static void set_use_alternate_protocols(bool value) {
- use_alternate_protocols_ = value;
- }
- static bool use_alternate_protocols() { return use_alternate_protocols_; }
-
- // Controls whether or not we use ssl when in spdy mode.
- static void set_force_spdy_over_ssl(bool value) {
- force_spdy_over_ssl_ = value;
- }
- static bool force_spdy_over_ssl() {
- return force_spdy_over_ssl_;
- }
-
- // Controls whether or not we use spdy without npn.
- static void set_force_spdy_always(bool value) {
- force_spdy_always_ = value;
- }
- static bool force_spdy_always() { return force_spdy_always_; }
-
- // Add a URL to exclude from forced SPDY.
- static void add_forced_spdy_exclusion(const std::string& value);
- // Check if a HostPortPair is excluded from using spdy.
- static bool HasSpdyExclusion(const HostPortPair& endpoint);
-
- // Sets http/1.1 as the only protocol supported via NPN or Alternate-Protocol.
- static void EnableNpnHttpOnly();
-
- // Sets http/1.1, quic, and spdy/3 as the protocols supported via
- // NPN or Alternate-Protocol.
- static void EnableNpnSpdy3();
-
- // Sets http/1.1, quic, spdy/3, and spdy/3.1 as the protocols
- // supported via NPN or Alternate-Protocol.
- static void EnableNpnSpdy31();
-
- // Sets http/1.1, quic, spdy/2, spdy/3, and spdy/3.1 as the
- // protocols supported via NPN or Alternate-Protocol.
- static void EnableNpnSpdy31WithSpdy2();
-
- // Sets http/1.1, quic, spdy/3, spdy/3.1, and spdy/4a2 as the
- // protocols supported via NPN or Alternate-Protocol.
- static void EnableNpnSpdy4a2();
-
- // Sets http/1.1, quic, spdy/3, spdy/3.1, spdy/4a2, and http/2 draft
- // 04 as the protocols supported via NPN or Alternate-Protocol.
- static void EnableNpnHttp2Draft04();
-
- // Sets the protocols supported by NPN (next protocol negotiation) during the
- // SSL handshake as well as by HTTP Alternate-Protocol.
- static void SetNextProtos(const std::vector<NextProto>& value);
- static bool has_next_protos() { return next_protos_ != NULL; }
- static const std::vector<std::string>& next_protos() {
- return *next_protos_;
- }
-
protected:
HttpStreamFactory();
private:
- // |protocol| must be a valid protocol value.
- static bool IsProtocolEnabled(AlternateProtocol protocol);
- static void SetProtocolEnabled(AlternateProtocol protocol);
- static void ResetEnabledProtocols();
-
- static std::vector<std::string>* next_protos_;
- static bool enabled_protocols_[NUM_VALID_ALTERNATE_PROTOCOLS];
static bool spdy_enabled_;
- static bool use_alternate_protocols_;
- static bool force_spdy_over_ssl_;
- static bool force_spdy_always_;
- static std::list<HostPortPair>* forced_spdy_exclusions_;
DISALLOW_COPY_AND_ASSIGN(HttpStreamFactory);
};
diff --git a/chromium/net/http/http_stream_factory_impl.cc b/chromium/net/http/http_stream_factory_impl.cc
index 056a0f6b879..4340e62fb6a 100644
--- a/chromium/net/http/http_stream_factory_impl.cc
+++ b/chromium/net/http/http_stream_factory_impl.cc
@@ -6,14 +6,12 @@
#include <string>
+#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/net_log.h"
#include "net/base/net_util.h"
#include "net/http/http_network_session.h"
-#include "net/http/http_pipelined_connection.h"
-#include "net/http/http_pipelined_host.h"
-#include "net/http/http_pipelined_stream.h"
#include "net/http/http_server_properties.h"
#include "net/http/http_stream_factory_impl_job.h"
#include "net/http/http_stream_factory_impl_request.h"
@@ -44,15 +42,11 @@ GURL UpgradeUrlToHttps(const GURL& original_url, int port) {
HttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session,
bool for_websockets)
: session_(session),
- http_pipelined_host_pool_(this, NULL,
- session_->http_server_properties(),
- session_->force_http_pipelining()),
for_websockets_(for_websockets) {}
HttpStreamFactoryImpl::~HttpStreamFactoryImpl() {
DCHECK(request_map_.empty());
DCHECK(spdy_session_request_map_.empty());
- DCHECK(http_pipelining_request_map_.empty());
std::set<const Job*> tmp_job_set;
tmp_job_set.swap(orphaned_job_set_);
@@ -178,18 +172,14 @@ void HttpStreamFactoryImpl::PreconnectStreams(
job->Preconnect(num_streams);
}
-base::Value* HttpStreamFactoryImpl::PipelineInfoToValue() const {
- return http_pipelined_host_pool_.PipelineInfoToValue();
-}
-
const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const {
return session_->params().host_mapping_rules;
}
PortAlternateProtocolPair HttpStreamFactoryImpl::GetAlternateProtocolRequestFor(
const GURL& original_url,
- GURL* alternate_url) const {
- if (!use_alternate_protocols())
+ GURL* alternate_url) {
+ if (!session_->params().use_alternate_protocols)
return kNoAlternateProtocol;
if (original_url.SchemeIs("ftp"))
@@ -198,15 +188,19 @@ PortAlternateProtocolPair HttpStreamFactoryImpl::GetAlternateProtocolRequestFor(
HostPortPair origin = HostPortPair(original_url.HostNoBrackets(),
original_url.EffectiveIntPort());
- const HttpServerProperties& http_server_properties =
+ HttpServerProperties& http_server_properties =
*session_->http_server_properties();
if (!http_server_properties.HasAlternateProtocol(origin))
return kNoAlternateProtocol;
PortAlternateProtocolPair alternate =
http_server_properties.GetAlternateProtocol(origin);
- if (alternate.protocol == ALTERNATE_PROTOCOL_BROKEN)
+ if (alternate.protocol == ALTERNATE_PROTOCOL_BROKEN) {
+ HistogramAlternateProtocolUsage(
+ ALTERNATE_PROTOCOL_USAGE_BROKEN,
+ http_server_properties.GetAlternateProtocolExperiment());
return kNoAlternateProtocol;
+ }
if (!IsAlternateProtocolValid(alternate.protocol)) {
NOTREACHED();
@@ -228,10 +222,10 @@ PortAlternateProtocolPair HttpStreamFactoryImpl::GetAlternateProtocolRequestFor(
origin.set_port(alternate.port);
if (alternate.protocol >= NPN_SPDY_MINIMUM_VERSION &&
alternate.protocol <= NPN_SPDY_MAXIMUM_VERSION) {
- if (!spdy_enabled())
+ if (!HttpStreamFactory::spdy_enabled())
return kNoAlternateProtocol;
- if (HttpStreamFactory::HasSpdyExclusion(origin))
+ if (session_->HasSpdyExclusion(origin))
return kNoAlternateProtocol;
*alternate_url = UpgradeUrlToHttps(original_url, alternate.port);
@@ -290,15 +284,9 @@ void HttpStreamFactoryImpl::OnNewSpdySessionReady(
using_spdy,
net_log);
if (for_websockets_) {
- WebSocketHandshakeStreamBase::CreateHelper* create_helper =
- request->websocket_handshake_stream_create_helper();
- DCHECK(create_helper);
- bool use_relative_url = direct || request->url().SchemeIs("wss");
- request->OnWebSocketHandshakeStreamReady(
- NULL,
- used_ssl_config,
- used_proxy_info,
- create_helper->CreateSpdyStream(spdy_session, use_relative_url));
+ // TODO(ricea): Restore this code path when WebSocket over SPDY
+ // implementation is ready.
+ NOTREACHED();
} else {
bool use_relative_url = direct || request->url().SchemeIs("https");
request->OnStreamReady(
@@ -322,40 +310,4 @@ void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) {
OnPreconnectsCompleteInternal();
}
-void HttpStreamFactoryImpl::OnHttpPipelinedHostHasAdditionalCapacity(
- HttpPipelinedHost* host) {
- while (ContainsKey(http_pipelining_request_map_, host->GetKey())) {
- HttpPipelinedStream* stream =
- http_pipelined_host_pool_.CreateStreamOnExistingPipeline(
- host->GetKey());
- if (!stream) {
- break;
- }
-
- Request* request = *http_pipelining_request_map_[host->GetKey()].begin();
- request->Complete(stream->was_npn_negotiated(),
- stream->protocol_negotiated(),
- false, // not using_spdy
- stream->net_log());
- request->OnStreamReady(NULL,
- stream->used_ssl_config(),
- stream->used_proxy_info(),
- stream);
- }
-}
-
-void HttpStreamFactoryImpl::AbortPipelinedRequestsWithKey(
- const Job* job, const HttpPipelinedHost::Key& key, int status,
- const SSLConfig& used_ssl_config) {
- RequestVector requests_to_fail = http_pipelining_request_map_[key];
- for (RequestVector::const_iterator it = requests_to_fail.begin();
- it != requests_to_fail.end(); ++it) {
- Request* request = *it;
- if (request == request_map_[job]) {
- continue;
- }
- request->OnStreamFailed(NULL, status, used_ssl_config);
- }
-}
-
} // namespace net
diff --git a/chromium/net/http/http_stream_factory_impl.h b/chromium/net/http/http_stream_factory_impl.h
index 4824dece14f..8a6fdaf4fc3 100644
--- a/chromium/net/http/http_stream_factory_impl.h
+++ b/chromium/net/http/http_stream_factory_impl.h
@@ -13,7 +13,6 @@
#include "base/memory/ref_counted.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_log.h"
-#include "net/http/http_pipelined_host_pool.h"
#include "net/http/http_stream_factory.h"
#include "net/proxy/proxy_server.h"
#include "net/socket/ssl_client_socket.h"
@@ -22,12 +21,9 @@
namespace net {
class HttpNetworkSession;
-class HttpPipelinedHost;
class SpdySession;
-class NET_EXPORT_PRIVATE HttpStreamFactoryImpl :
- public HttpStreamFactory,
- public HttpPipelinedHostPool::Delegate {
+class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : public HttpStreamFactory {
public:
// RequestStream may only be called if |for_websockets| is false.
// RequestWebSocketHandshakeStream may only be called if |for_websockets|
@@ -58,13 +54,8 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl :
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config) OVERRIDE;
- virtual base::Value* PipelineInfoToValue() const OVERRIDE;
virtual const HostMappingRules* GetHostMappingRules() const OVERRIDE;
- // HttpPipelinedHostPool::Delegate interface
- virtual void OnHttpPipelinedHostHasAdditionalCapacity(
- HttpPipelinedHost* host) OVERRIDE;
-
size_t num_orphaned_jobs() const { return orphaned_job_set_.size(); }
private:
@@ -74,10 +65,7 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl :
class NET_EXPORT_PRIVATE Job;
typedef std::set<Request*> RequestSet;
- typedef std::vector<Request*> RequestVector;
typedef std::map<SpdySessionKey, RequestSet> SpdySessionRequestMap;
- typedef std::map<HttpPipelinedHost::Key,
- RequestVector> HttpPipeliningRequestMap;
HttpStreamRequest* RequestStreamInternal(
const HttpRequestInfo& info,
@@ -90,7 +78,7 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl :
PortAlternateProtocolPair GetAlternateProtocolRequestFor(
const GURL& original_url,
- GURL* alternate_url) const;
+ GURL* alternate_url);
// Detaches |job| from |request|.
void OrphanJob(Job* job, const Request* request);
@@ -121,11 +109,6 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl :
// Called when the Preconnect completes. Used for testing.
virtual void OnPreconnectsCompleteInternal() {}
- void AbortPipelinedRequestsWithKey(const Job* job,
- const HttpPipelinedHost::Key& key,
- int status,
- const SSLConfig& used_ssl_config);
-
HttpNetworkSession* const session_;
// All Requests are handed out to clients. By the time HttpStreamFactoryImpl
@@ -134,9 +117,6 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl :
std::map<const Job*, Request*> request_map_;
SpdySessionRequestMap spdy_session_request_map_;
- HttpPipeliningRequestMap http_pipelining_request_map_;
-
- HttpPipelinedHostPool http_pipelined_host_pool_;
// These jobs correspond to jobs orphaned by Requests and now owned by
// HttpStreamFactoryImpl. Since they are no longer tied to Requests, they will
diff --git a/chromium/net/http/http_stream_factory_impl_job.cc b/chromium/net/http/http_stream_factory_impl_job.cc
index c86bee7495b..79a95361d43 100644
--- a/chromium/net/http/http_stream_factory_impl_job.cc
+++ b/chromium/net/http/http_stream_factory_impl_job.cc
@@ -20,10 +20,6 @@
#include "net/base/net_util.h"
#include "net/http/http_basic_stream.h"
#include "net/http/http_network_session.h"
-#include "net/http/http_pipelined_connection.h"
-#include "net/http/http_pipelined_host.h"
-#include "net/http/http_pipelined_host_pool.h"
-#include "net/http/http_pipelined_stream.h"
#include "net/http/http_proxy_client_socket.h"
#include "net/http/http_proxy_client_socket_pool.h"
#include "net/http/http_request_info.h"
@@ -98,15 +94,15 @@ HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory,
using_spdy_(false),
using_quic_(false),
quic_request_(session_->quic_stream_factory()),
- force_spdy_always_(HttpStreamFactory::force_spdy_always()),
- force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()),
+ using_existing_quic_session_(false),
spdy_certificate_error_(OK),
establishing_tunnel_(false),
was_npn_negotiated_(false),
protocol_negotiated_(kProtoUnknown),
num_streams_(0),
spdy_session_direct_(false),
- existing_available_pipeline_(false),
+ job_status_(STATUS_RUNNING),
+ other_job_status_(STATUS_RUNNING),
ptr_factory_(this) {
DCHECK(stream_factory);
DCHECK(session);
@@ -217,15 +213,17 @@ void HttpStreamFactoryImpl::Job::Orphan(const Request* request) {
blocking_job_->waiting_job_ = NULL;
blocking_job_ = NULL;
if (stream_factory_->for_websockets_ &&
- connection_ && connection_->socket())
+ connection_ && connection_->socket()) {
connection_->socket()->Disconnect();
+ }
stream_factory_->OnOrphanedJobComplete(this);
} else if (stream_factory_->for_websockets_) {
// We cancel this job because a WebSocketHandshakeStream can't be created
// without a WebSocketHandshakeStreamBase::CreateHelper which is stored in
// the Request class and isn't accessible from this job.
- if (connection_ && connection_->socket())
+ if (connection_ && connection_->socket()) {
connection_->socket()->Disconnect();
+ }
stream_factory_->OnOrphanedJobComplete(this);
}
}
@@ -291,10 +289,11 @@ bool HttpStreamFactoryImpl::Job::CanUseExistingSpdySession() const {
// The only time we can use an existing session is if the request URL is
// https (the normal case) or if we're connection to a SPDY proxy, or
// if we're running with force_spdy_always_. crbug.com/133176
+ // TODO(ricea): Add "wss" back to this list when SPDY WebSocket support is
+ // working.
return request_info_.url.SchemeIs("https") ||
- request_info_.url.SchemeIs("wss") ||
proxy_info_.proxy_server().is_https() ||
- force_spdy_always_;
+ session_->params().force_spdy_always;
}
void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() {
@@ -333,20 +332,26 @@ void HttpStreamFactoryImpl::Job::OnWebSocketHandshakeStreamReadyCallback() {
}
void HttpStreamFactoryImpl::Job::OnNewSpdySessionReadyCallback() {
- DCHECK(!stream_.get());
+ DCHECK(stream_.get());
DCHECK(!IsPreconnecting());
DCHECK(using_spdy());
- if (!new_spdy_session_)
- return;
+ // Note: an event loop iteration has passed, so |new_spdy_session_| may be
+ // NULL at this point if the SpdySession closed immediately after creation.
base::WeakPtr<SpdySession> spdy_session = new_spdy_session_;
new_spdy_session_.reset();
+
+ // TODO(jgraettinger): Notify the factory, and let that notify |request_|,
+ // rather than notifying |request_| directly.
if (IsOrphaned()) {
- stream_factory_->OnNewSpdySessionReady(
- spdy_session, spdy_session_direct_, server_ssl_config_, proxy_info_,
- was_npn_negotiated(), protocol_negotiated(), using_spdy(), net_log_);
+ if (spdy_session) {
+ stream_factory_->OnNewSpdySessionReady(
+ spdy_session, spdy_session_direct_, server_ssl_config_, proxy_info_,
+ was_npn_negotiated(), protocol_negotiated(), using_spdy(), net_log_);
+ }
stream_factory_->OnOrphanedJobComplete(this);
} else {
- request_->OnNewSpdySessionReady(this, spdy_session, spdy_session_direct_);
+ request_->OnNewSpdySessionReady(
+ this, stream_.Pass(), spdy_session, spdy_session_direct_);
}
// |this| may be deleted after this call.
}
@@ -451,9 +456,8 @@ int HttpStreamFactoryImpl::Job::RunLoop(int result) {
if (IsPreconnecting()) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(
- &HttpStreamFactoryImpl::Job::OnPreconnectsComplete,
- ptr_factory_.GetWeakPtr()));
+ base::Bind(&HttpStreamFactoryImpl::Job::OnPreconnectsComplete,
+ ptr_factory_.GetWeakPtr()));
return ERR_IO_PENDING;
}
@@ -464,64 +468,57 @@ int HttpStreamFactoryImpl::Job::RunLoop(int result) {
next_state_ = STATE_WAITING_USER_ACTION;
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(
- &HttpStreamFactoryImpl::Job::OnCertificateErrorCallback,
- ptr_factory_.GetWeakPtr(),
- result, ssl_info_));
+ base::Bind(&HttpStreamFactoryImpl::Job::OnCertificateErrorCallback,
+ ptr_factory_.GetWeakPtr(), result, ssl_info_));
return ERR_IO_PENDING;
}
switch (result) {
- case ERR_PROXY_AUTH_REQUESTED:
- {
- DCHECK(connection_.get());
- DCHECK(connection_->socket());
- DCHECK(establishing_tunnel_);
-
- ProxyClientSocket* proxy_socket =
- static_cast<ProxyClientSocket*>(connection_->socket());
- const HttpResponseInfo* tunnel_auth_response =
- proxy_socket->GetConnectResponseInfo();
-
- next_state_ = STATE_WAITING_USER_ACTION;
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &Job::OnNeedsProxyAuthCallback,
- ptr_factory_.GetWeakPtr(),
- *tunnel_auth_response,
- proxy_socket->GetAuthController()));
- }
+ case ERR_PROXY_AUTH_REQUESTED: {
+ UMA_HISTOGRAM_BOOLEAN("Net.ProxyAuthRequested.HasConnection",
+ connection_.get() != NULL);
+ if (!connection_.get())
+ return ERR_PROXY_AUTH_REQUESTED_WITH_NO_CONNECTION;
+ CHECK(connection_->socket());
+ CHECK(establishing_tunnel_);
+
+ next_state_ = STATE_WAITING_USER_ACTION;
+ ProxyClientSocket* proxy_socket =
+ static_cast<ProxyClientSocket*>(connection_->socket());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&Job::OnNeedsProxyAuthCallback, ptr_factory_.GetWeakPtr(),
+ *proxy_socket->GetConnectResponseInfo(),
+ proxy_socket->GetAuthController()));
return ERR_IO_PENDING;
+ }
case ERR_SSL_CLIENT_AUTH_CERT_NEEDED:
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(
- &Job::OnNeedsClientAuthCallback,
- ptr_factory_.GetWeakPtr(),
- connection_->ssl_error_response_info().cert_request_info));
+ base::Bind(&Job::OnNeedsClientAuthCallback, ptr_factory_.GetWeakPtr(),
+ connection_->ssl_error_response_info().cert_request_info));
return ERR_IO_PENDING;
- case ERR_HTTPS_PROXY_TUNNEL_RESPONSE:
- {
- DCHECK(connection_.get());
- DCHECK(connection_->socket());
- DCHECK(establishing_tunnel_);
+ case ERR_HTTPS_PROXY_TUNNEL_RESPONSE: {
+ DCHECK(connection_.get());
+ DCHECK(connection_->socket());
+ DCHECK(establishing_tunnel_);
- ProxyClientSocket* proxy_socket =
- static_cast<ProxyClientSocket*>(connection_->socket());
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &Job::OnHttpsProxyTunnelResponseCallback,
- ptr_factory_.GetWeakPtr(),
- *proxy_socket->GetConnectResponseInfo(),
- proxy_socket->CreateConnectResponseStream()));
- return ERR_IO_PENDING;
- }
+ ProxyClientSocket* proxy_socket =
+ static_cast<ProxyClientSocket*>(connection_->socket());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&Job::OnHttpsProxyTunnelResponseCallback,
+ ptr_factory_.GetWeakPtr(),
+ *proxy_socket->GetConnectResponseInfo(),
+ proxy_socket->CreateConnectResponseStream()));
+ return ERR_IO_PENDING;
+ }
case OK:
+ job_status_ = STATUS_SUCCEEDED;
+ MaybeMarkAlternateProtocolBroken();
next_state_ = STATE_DONE;
if (new_spdy_session_.get()) {
base::MessageLoop::current()->PostTask(
@@ -538,22 +535,22 @@ int HttpStreamFactoryImpl::Job::RunLoop(int result) {
DCHECK(stream_.get());
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(
- &Job::OnStreamReadyCallback,
- ptr_factory_.GetWeakPtr()));
+ base::Bind(&Job::OnStreamReadyCallback, ptr_factory_.GetWeakPtr()));
}
return ERR_IO_PENDING;
default:
+ if (job_status_ != STATUS_BROKEN) {
+ DCHECK_EQ(STATUS_RUNNING, job_status_);
+ job_status_ = STATUS_FAILED;
+ MaybeMarkAlternateProtocolBroken();
+ }
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(
- &Job::OnStreamFailedCallback,
- ptr_factory_.GetWeakPtr(),
- result));
+ base::Bind(&Job::OnStreamFailedCallback, ptr_factory_.GetWeakPtr(),
+ result));
return ERR_IO_PENDING;
}
- return result;
}
int HttpStreamFactoryImpl::Job::DoLoop(int result) {
@@ -627,7 +624,6 @@ int HttpStreamFactoryImpl::Job::DoStart() {
origin_ = HostPortPair(request_info_.url.HostNoBrackets(), port);
origin_url_ = stream_factory_->ApplyHostMappingRules(
request_info_.url, &origin_);
- http_pipelining_key_.reset(new HttpPipelinedHost::Key(origin_));
net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB,
base::Bind(&NetLogHttpStreamJobCallback,
@@ -674,7 +670,7 @@ int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
if (result == OK) {
// Remove unsupported proxies from the list.
proxy_info_.RemoveProxiesWithoutScheme(
- ProxyServer::SCHEME_DIRECT |
+ ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_QUIC |
ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS |
ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5);
@@ -682,6 +678,11 @@ int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
// No proxies/direct to choose from. This happens when we don't support
// any of the proxies in the returned list.
result = ERR_NO_SUPPORTED_PROXIES;
+ } else if (using_quic_ &&
+ (!proxy_info_.is_quic() && !proxy_info_.is_direct())) {
+ // QUIC can not be spoken to non-QUIC proxies. This error should not be
+ // user visible, because the non-alternate job should be resumed.
+ result = ERR_NO_SUPPORTED_PROXIES;
}
}
@@ -701,13 +702,15 @@ int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
}
bool HttpStreamFactoryImpl::Job::ShouldForceSpdySSL() const {
- bool rv = force_spdy_always_ && force_spdy_over_ssl_;
- return rv && !HttpStreamFactory::HasSpdyExclusion(origin_);
+ bool rv = session_->params().force_spdy_always &&
+ session_->params().force_spdy_over_ssl;
+ return rv && !session_->HasSpdyExclusion(origin_);
}
bool HttpStreamFactoryImpl::Job::ShouldForceSpdyWithoutSSL() const {
- bool rv = force_spdy_always_ && !force_spdy_over_ssl_;
- return rv && !HttpStreamFactory::HasSpdyExclusion(origin_);
+ bool rv = session_->params().force_spdy_always &&
+ !session_->params().force_spdy_over_ssl;
+ return rv && !session_->HasSpdyExclusion(origin_);
}
bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const {
@@ -742,19 +745,26 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() {
if (ShouldForceQuic())
using_quic_ = true;
+ if (proxy_info_.is_quic())
+ using_quic_ = true;
+
if (using_quic_) {
DCHECK(session_->params().enable_quic);
- if (!proxy_info_.is_direct()) {
+ if (proxy_info_.is_quic() && !request_info_.url.SchemeIs("http")) {
NOTREACHED();
- // TODO(rch): support QUIC proxies.
+ // TODO(rch): support QUIC proxies for HTTPS urls.
return ERR_NOT_IMPLEMENTED;
}
+ HostPortPair destination = proxy_info_.is_quic() ?
+ proxy_info_.proxy_server().host_port_pair() : origin_;
next_state_ = STATE_INIT_CONNECTION_COMPLETE;
- const ProxyServer& proxy_server = proxy_info_.proxy_server();
- int rv = quic_request_.Request(HostPortProxyPair(origin_, proxy_server),
- using_ssl_, session_->cert_verifier(),
- net_log_, io_callback_);
- if (rv != OK) {
+ bool secure_quic = using_ssl_ || proxy_info_.is_quic();
+ int rv = quic_request_.Request(
+ destination, secure_quic, request_info_.privacy_mode,
+ request_info_.method, net_log_, io_callback_);
+ if (rv == OK) {
+ using_existing_quic_session_ = true;
+ } else {
// OK, there's no available QUIC session. Let |waiting_job_| resume
// if it's paused.
if (waiting_job_) {
@@ -780,29 +790,10 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() {
next_state_ = STATE_CREATE_STREAM;
existing_spdy_session_ = spdy_session;
return OK;
- } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) {
+ } else if (request_ && !request_->HasSpdySessionKey() &&
+ (using_ssl_ || ShouldForceSpdyWithoutSSL())) {
// Update the spdy session key for the request that launched this job.
request_->SetSpdySessionKey(spdy_session_key);
- } else if (IsRequestEligibleForPipelining()) {
- // TODO(simonjam): With pipelining, we might be better off using fewer
- // connections and thus should make fewer preconnections. Explore
- // preconnecting fewer than the requested num_connections.
- //
- // Separate note: A forced pipeline is always available if one exists for
- // this key. This is different than normal pipelines, which may be
- // unavailable or unusable. So, there is no need to worry about a race
- // between when a pipeline becomes available and when this job blocks.
- existing_available_pipeline_ = stream_factory_->http_pipelined_host_pool_.
- IsExistingPipelineAvailableForKey(*http_pipelining_key_.get());
- if (existing_available_pipeline_) {
- return OK;
- } else {
- bool was_new_key = request_->SetHttpPipeliningKey(
- *http_pipelining_key_.get());
- if (!was_new_key && session_->force_http_pipelining()) {
- return ERR_IO_PENDING;
- }
- }
}
// OK, there's no available SPDY session. Let |waiting_job_| resume if it's
@@ -847,28 +838,32 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() {
request_info_.privacy_mode,
net_log_,
num_streams_);
- } else {
- // If we can't use a SPDY session, don't both checking for one after
- // the hostname is resolved.
- OnHostResolutionCallback resolution_callback = CanUseExistingSpdySession() ?
- base::Bind(&Job::OnHostResolution, session_->spdy_session_pool(),
- GetSpdySessionKey()) :
- OnHostResolutionCallback();
- if (stream_factory_->for_websockets_) {
- return InitSocketHandleForWebSocketRequest(
- origin_url_, request_info_.extra_headers, request_info_.load_flags,
- priority_, session_, proxy_info_, ShouldForceSpdySSL(),
- want_spdy_over_npn, server_ssl_config_, proxy_ssl_config_,
- request_info_.privacy_mode, net_log_,
- connection_.get(), resolution_callback, io_callback_);
- }
- return InitSocketHandleForHttpRequest(
+ }
+
+ // If we can't use a SPDY session, don't both checking for one after
+ // the hostname is resolved.
+ OnHostResolutionCallback resolution_callback = CanUseExistingSpdySession() ?
+ base::Bind(&Job::OnHostResolution, session_->spdy_session_pool(),
+ GetSpdySessionKey()) :
+ OnHostResolutionCallback();
+ if (stream_factory_->for_websockets_) {
+ // TODO(ricea): Re-enable NPN when WebSockets over SPDY is supported.
+ SSLConfig websocket_server_ssl_config = server_ssl_config_;
+ websocket_server_ssl_config.next_protos.clear();
+ return InitSocketHandleForWebSocketRequest(
origin_url_, request_info_.extra_headers, request_info_.load_flags,
priority_, session_, proxy_info_, ShouldForceSpdySSL(),
- want_spdy_over_npn, server_ssl_config_, proxy_ssl_config_,
+ want_spdy_over_npn, websocket_server_ssl_config, proxy_ssl_config_,
request_info_.privacy_mode, net_log_,
connection_.get(), resolution_callback, io_callback_);
}
+
+ return InitSocketHandleForHttpRequest(
+ origin_url_, request_info_.extra_headers, request_info_.load_flags,
+ priority_, session_, proxy_info_, ShouldForceSpdySSL(),
+ want_spdy_over_npn, server_ssl_config_, proxy_ssl_config_,
+ request_info_.privacy_mode, net_log_,
+ connection_.get(), resolution_callback, io_callback_);
}
int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
@@ -903,11 +898,6 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
waiting_job_ = NULL;
}
- if (result < 0 && session_->force_http_pipelining()) {
- stream_factory_->AbortPipelinedRequestsWithKey(
- this, *http_pipelining_key_.get(), result, server_ssl_config_);
- }
-
// |result| may be the result of any of the stacked pools. The following
// logic is used when determining how to interpret an error.
// If |result| < 0:
@@ -976,15 +966,17 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
}
if (!ssl_started && result < 0 && original_url_.get()) {
- // Mark the alternate protocol as broken and fallback.
- session_->http_server_properties()->SetBrokenAlternateProtocol(
- HostPortPair::FromURL(*original_url_));
+ job_status_ = STATUS_BROKEN;
+ MaybeMarkAlternateProtocolBroken();
return result;
}
if (using_quic_) {
- if (result < 0)
+ if (result < 0) {
+ job_status_ = STATUS_BROKEN;
+ MaybeMarkAlternateProtocolBroken();
return result;
+ }
stream_ = quic_request_.ReleaseStream();
next_state_ = STATE_NONE;
return OK;
@@ -1039,8 +1031,7 @@ int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) {
}
int HttpStreamFactoryImpl::Job::DoCreateStream() {
- DCHECK(connection_->socket() || existing_spdy_session_.get() ||
- existing_available_pipeline_ || using_quic_);
+ DCHECK(connection_->socket() || existing_spdy_session_.get() || using_quic_);
next_state_ = STATE_CREATE_STREAM_COMPLETE;
@@ -1055,31 +1046,12 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) &&
(request_info_.url.SchemeIs("http") ||
request_info_.url.SchemeIs("ftp"));
- if (stream_factory_->http_pipelined_host_pool_.
- IsExistingPipelineAvailableForKey(*http_pipelining_key_.get())) {
- DCHECK(!stream_factory_->for_websockets_);
- stream_.reset(stream_factory_->http_pipelined_host_pool_.
- CreateStreamOnExistingPipeline(
- *http_pipelining_key_.get()));
- CHECK(stream_.get());
- } else if (stream_factory_->for_websockets_) {
+ if (stream_factory_->for_websockets_) {
DCHECK(request_);
DCHECK(request_->websocket_handshake_stream_create_helper());
websocket_stream_.reset(
request_->websocket_handshake_stream_create_helper()
->CreateBasicStream(connection_.Pass(), using_proxy));
- } else if (!using_proxy && IsRequestEligibleForPipelining()) {
- // TODO(simonjam): Support proxies.
- stream_.reset(
- stream_factory_->http_pipelined_host_pool_.CreateStreamOnNewPipeline(
- *http_pipelining_key_.get(),
- connection_.release(),
- server_ssl_config_,
- proxy_info_,
- net_log_,
- was_npn_negotiated_,
- protocol_negotiated_));
- CHECK(stream_.get());
} else {
stream_.reset(new HttpBasicStream(connection_.release(), using_proxy));
}
@@ -1098,7 +1070,7 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
// We never use privacy mode for connection to proxy server.
spdy_session_key = SpdySessionKey(proxy_server.host_port_pair(),
ProxyServer::Direct(),
- kPrivacyModeDisabled);
+ PRIVACY_MODE_DISABLED);
direct = false;
}
@@ -1113,21 +1085,34 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
SpdySessionPool* spdy_pool = session_->spdy_session_pool();
spdy_session = spdy_pool->FindAvailableSession(spdy_session_key, net_log_);
if (!spdy_session) {
- int error =
+ base::WeakPtr<SpdySession> new_spdy_session =
spdy_pool->CreateAvailableSessionFromSocket(spdy_session_key,
connection_.Pass(),
net_log_,
spdy_certificate_error_,
- &new_spdy_session_,
using_ssl_);
- if (error != OK)
- return error;
+ if (!new_spdy_session->HasAcceptableTransportSecurity()) {
+ new_spdy_session->CloseSessionOnError(
+ ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, "");
+ return ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY;
+ }
+
+ new_spdy_session_ = new_spdy_session;
+ spdy_session_direct_ = direct;
const HostPortPair& host_port_pair = spdy_session_key.host_port_pair();
base::WeakPtr<HttpServerProperties> http_server_properties =
session_->http_server_properties();
if (http_server_properties)
http_server_properties->SetSupportsSpdy(host_port_pair, true);
- spdy_session_direct_ = direct;
+
+ // Create a SpdyHttpStream attached to the session;
+ // OnNewSpdySessionReadyCallback is not called until an event loop
+ // iteration later, so if the SpdySession is closed between then, allow
+ // reuse state from the underlying socket, sampled by SpdyHttpStream,
+ // bubble up to the request.
+ bool use_relative_url = direct || request_info_.url.SchemeIs("https");
+ stream_.reset(new SpdyHttpStream(new_spdy_session_, use_relative_url));
+
return OK;
}
}
@@ -1140,12 +1125,8 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
// will know when SpdySessions become available.
if (stream_factory_->for_websockets_) {
- DCHECK(request_);
- DCHECK(request_->websocket_handshake_stream_create_helper());
- bool use_relative_url = direct || request_info_.url.SchemeIs("wss");
- websocket_stream_.reset(
- request_->websocket_handshake_stream_create_helper()->CreateSpdyStream(
- spdy_session, use_relative_url));
+ // TODO(ricea): Restore this code when WebSockets over SPDY is implemented.
+ NOTREACHED();
} else {
bool use_relative_url = direct || request_info_.url.SchemeIs("https");
stream_.reset(new SpdyHttpStream(spdy_session, use_relative_url));
@@ -1194,10 +1175,8 @@ void HttpStreamFactoryImpl::Job::ReturnToStateInitConnection(
connection_->socket()->Disconnect();
connection_->Reset();
- if (request_) {
+ if (request_)
request_->RemoveRequestFromSpdySessionRequestMap();
- request_->RemoveRequestFromHttpPipeliningRequestMap();
- }
next_state_ = STATE_INIT_CONNECTION;
}
@@ -1282,7 +1261,7 @@ void HttpStreamFactoryImpl::Job::InitSSLConfig(
ssl_config->verify_ev_cert = true;
// Disable Channel ID if privacy mode is enabled.
- if (request_info_.privacy_mode == kPrivacyModeEnabled)
+ if (request_info_.privacy_mode == PRIVACY_MODE_ENABLED)
ssl_config->channel_id_enabled = false;
}
@@ -1338,21 +1317,20 @@ int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) {
if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) {
session_->ssl_client_auth_cache()->Remove(
- proxy_info_.proxy_server().host_port_pair().ToString());
+ proxy_info_.proxy_server().host_port_pair());
}
int rv = session_->proxy_service()->ReconsiderProxyAfterError(
- request_info_.url, &proxy_info_, io_callback_, &pac_request_, net_log_);
+ request_info_.url, error, &proxy_info_, io_callback_, &pac_request_,
+ net_log_);
if (rv == OK || rv == ERR_IO_PENDING) {
// If the error was during connection setup, there is no socket to
// disconnect.
if (connection_->socket())
connection_->socket()->Disconnect();
connection_->Reset();
- if (request_) {
+ if (request_)
request_->RemoveRequestFromSpdySessionRequestMap();
- request_->RemoveRequestFromHttpPipeliningRequestMap();
- }
next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
} else {
// If ReconsiderProxyAfterError() failed synchronously, it means
@@ -1446,33 +1424,59 @@ bool HttpStreamFactoryImpl::Job::IsOrphaned() const {
return !IsPreconnecting() && !request_;
}
-bool HttpStreamFactoryImpl::Job::IsRequestEligibleForPipelining() {
- if (IsPreconnecting() || !request_) {
- return false;
- }
- if (stream_factory_->for_websockets_) {
- return false;
- }
- if (session_->force_http_pipelining()) {
- return true;
- }
- if (!session_->params().http_pipelining_enabled) {
- return false;
+void HttpStreamFactoryImpl::Job::ReportJobSuccededForRequest() {
+ net::AlternateProtocolExperiment alternate_protocol_experiment =
+ ALTERNATE_PROTOCOL_NOT_PART_OF_EXPERIMENT;
+ base::WeakPtr<HttpServerProperties> http_server_properties =
+ session_->http_server_properties();
+ if (http_server_properties) {
+ alternate_protocol_experiment =
+ http_server_properties->GetAlternateProtocolExperiment();
}
- if (using_ssl_) {
- return false;
+ if (using_existing_quic_session_) {
+ // If an existing session was used, then no TCP connection was
+ // started.
+ HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE,
+ alternate_protocol_experiment);
+ } else if (original_url_) {
+ // This job was the alternate protocol job, and hence won the race.
+ HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE,
+ alternate_protocol_experiment);
+ } else {
+ // This job was the normal job, and hence the alternate protocol job lost
+ // the race.
+ HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE,
+ alternate_protocol_experiment);
}
- if (request_info_.method != "GET" && request_info_.method != "HEAD") {
- return false;
+}
+
+void HttpStreamFactoryImpl::Job::MarkOtherJobComplete(const Job& job) {
+ DCHECK_EQ(STATUS_RUNNING, other_job_status_);
+ other_job_status_ = job.job_status_;
+ MaybeMarkAlternateProtocolBroken();
+}
+
+void HttpStreamFactoryImpl::Job::MaybeMarkAlternateProtocolBroken() {
+ if (job_status_ == STATUS_RUNNING || other_job_status_ == STATUS_RUNNING)
+ return;
+
+ bool is_alternate_protocol_job = original_url_.get() != NULL;
+ if (is_alternate_protocol_job) {
+ if (job_status_ == STATUS_BROKEN && other_job_status_ == STATUS_SUCCEEDED) {
+ HistogramBrokenAlternateProtocolLocation(
+ BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT);
+ session_->http_server_properties()->SetBrokenAlternateProtocol(
+ HostPortPair::FromURL(*original_url_));
+ }
+ return;
}
- if (request_info_.load_flags &
- (net::LOAD_MAIN_FRAME | net::LOAD_SUB_FRAME | net::LOAD_PREFETCH |
- net::LOAD_IS_DOWNLOAD)) {
- // Avoid pipelining resources that may be streamed for a long time.
- return false;
+
+ if (job_status_ == STATUS_SUCCEEDED && other_job_status_ == STATUS_BROKEN) {
+ HistogramBrokenAlternateProtocolLocation(
+ BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN);
+ session_->http_server_properties()->SetBrokenAlternateProtocol(
+ HostPortPair::FromURL(request_info_.url));
}
- return stream_factory_->http_pipelined_host_pool_.IsKeyEligibleForPipelining(
- *http_pipelining_key_.get());
}
} // namespace net
diff --git a/chromium/net/http/http_stream_factory_impl_job.h b/chromium/net/http/http_stream_factory_impl_job.h
index 1970b5be08b..9659d45060a 100644
--- a/chromium/net/http/http_stream_factory_impl_job.h
+++ b/chromium/net/http/http_stream_factory_impl_job.h
@@ -13,7 +13,6 @@
#include "net/base/request_priority.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_controller.h"
-#include "net/http/http_pipelined_host.h"
#include "net/http/http_request_info.h"
#include "net/http/http_stream_factory_impl.h"
#include "net/proxy/proxy_service.h"
@@ -92,6 +91,13 @@ class HttpStreamFactoryImpl::Job {
// Indicates whether or not this Job has been orphaned by a Request.
bool IsOrphaned() const;
+ // Called to indicate that this job succeeded, and some other jobs
+ // will be orphaned.
+ void ReportJobSuccededForRequest();
+
+ // Marks that the other |job| has completed.
+ void MarkOtherJobComplete(const Job& job);
+
private:
enum State {
STATE_START,
@@ -129,6 +135,13 @@ class HttpStreamFactoryImpl::Job {
STATE_NONE
};
+ enum JobStatus {
+ STATUS_RUNNING,
+ STATUS_FAILED,
+ STATUS_BROKEN,
+ STATUS_SUCCEEDED
+ };
+
void OnStreamReadyCallback();
void OnWebSocketHandshakeStreamReadyCallback();
// This callback function is called when a new SPDY session is created.
@@ -216,7 +229,7 @@ class HttpStreamFactoryImpl::Job {
// Should we force QUIC for this stream request.
bool ShouldForceQuic() const;
- bool IsRequestEligibleForPipelining();
+ void MaybeMarkAlternateProtocolBroken();
// Record histograms of latency until Connect() completes.
static void LogHttpConnectedMetrics(const ClientSocketHandle& handle);
@@ -277,11 +290,8 @@ class HttpStreamFactoryImpl::Job {
bool using_quic_;
QuicStreamRequest quic_request_;
- // Force spdy for all connections.
- bool force_spdy_always_;
-
- // Force spdy only for SSL connections.
- bool force_spdy_over_ssl_;
+ // True if this job used an existing QUIC session.
+ bool using_existing_quic_session_;
// Force quic for a specific port.
int force_quic_port_;
@@ -318,11 +328,8 @@ class HttpStreamFactoryImpl::Job {
// Only used if |new_spdy_session_| is non-NULL.
bool spdy_session_direct_;
- // Key used to identify the HttpPipelinedHost for |request_|.
- scoped_ptr<HttpPipelinedHost::Key> http_pipelining_key_;
-
- // True if an existing pipeline can handle this job's request.
- bool existing_available_pipeline_;
+ JobStatus job_status_;
+ JobStatus other_job_status_;
base::WeakPtrFactory<Job> ptr_factory_;
diff --git a/chromium/net/http/http_stream_factory_impl_request.cc b/chromium/net/http/http_stream_factory_impl_request.cc
index d731d414b71..2cc497f2112 100644
--- a/chromium/net/http/http_stream_factory_impl_request.cc
+++ b/chromium/net/http/http_stream_factory_impl_request.cc
@@ -48,14 +48,13 @@ HttpStreamFactoryImpl::Request::~Request() {
factory_->request_map_.erase(*it);
RemoveRequestFromSpdySessionRequestMap();
- RemoveRequestFromHttpPipeliningRequestMap();
STLDeleteElements(&jobs_);
}
void HttpStreamFactoryImpl::Request::SetSpdySessionKey(
const SpdySessionKey& spdy_session_key) {
- DCHECK(!spdy_session_key_.get());
+ CHECK(!spdy_session_key_.get());
spdy_session_key_.reset(new SpdySessionKey(spdy_session_key));
RequestSet& request_set =
factory_->spdy_session_request_map_[spdy_session_key];
@@ -63,18 +62,6 @@ void HttpStreamFactoryImpl::Request::SetSpdySessionKey(
request_set.insert(this);
}
-bool HttpStreamFactoryImpl::Request::SetHttpPipeliningKey(
- const HttpPipelinedHost::Key& http_pipelining_key) {
- CHECK(!http_pipelining_key_.get());
- http_pipelining_key_.reset(new HttpPipelinedHost::Key(http_pipelining_key));
- bool was_new_key = !ContainsKey(factory_->http_pipelining_request_map_,
- http_pipelining_key);
- RequestVector& request_vector =
- factory_->http_pipelining_request_map_[http_pipelining_key];
- request_vector.push_back(this);
- return was_new_key;
-}
-
void HttpStreamFactoryImpl::Request::AttachJob(Job* job) {
DCHECK(job);
jobs_.insert(job);
@@ -131,21 +118,16 @@ void HttpStreamFactoryImpl::Request::OnStreamFailed(
int status,
const SSLConfig& used_ssl_config) {
DCHECK_NE(OK, status);
- // |job| should only be NULL if we're being canceled by a late bound
- // HttpPipelinedConnection (one that was not created by a job in our |jobs_|
- // set).
- if (!job) {
- DCHECK(!bound_job_.get());
- DCHECK(!jobs_.empty());
- // NOTE(willchan): We do *NOT* call OrphanJobs() here. The reason is because
- // we *WANT* to cancel the unnecessary Jobs from other requests if another
- // Job completes first.
- } else if (!bound_job_.get()) {
+ DCHECK(job);
+ if (!bound_job_.get()) {
// Hey, we've got other jobs! Maybe one of them will succeed, let's just
// ignore this failure.
if (jobs_.size() > 1) {
jobs_.erase(job);
factory_->request_map_.erase(job);
+ // Notify all the other jobs that this one failed.
+ for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
+ (*it)->MarkOtherJobComplete(*job);
delete job;
return;
} else {
@@ -268,34 +250,29 @@ HttpStreamFactoryImpl::Request::RemoveRequestFromSpdySessionRequestMap() {
}
}
-void
-HttpStreamFactoryImpl::Request::RemoveRequestFromHttpPipeliningRequestMap() {
- if (http_pipelining_key_.get()) {
- HttpPipeliningRequestMap& http_pipelining_request_map =
- factory_->http_pipelining_request_map_;
- DCHECK(ContainsKey(http_pipelining_request_map, *http_pipelining_key_));
- RequestVector& request_vector =
- http_pipelining_request_map[*http_pipelining_key_];
- for (RequestVector::iterator it = request_vector.begin();
- it != request_vector.end(); ++it) {
- if (*it == this) {
- request_vector.erase(it);
- break;
- }
- }
- if (request_vector.empty())
- http_pipelining_request_map.erase(*http_pipelining_key_);
- http_pipelining_key_.reset();
- }
+bool HttpStreamFactoryImpl::Request::HasSpdySessionKey() const {
+ return spdy_session_key_.get() != NULL;
}
+// TODO(jgraettinger): Currently, HttpStreamFactoryImpl::Job notifies a
+// Request that the session is ready, which in turn notifies it's delegate,
+// and then it notifies HttpStreamFactoryImpl so that /other/ requests may
+// be woken, but only if the spdy_session is still okay. This is tough to grok.
+// Instead, see if Job can notify HttpStreamFactoryImpl only, and have one
+// path for notifying any requests waiting for the session (including the
+// request which spawned it).
void HttpStreamFactoryImpl::Request::OnNewSpdySessionReady(
Job* job,
+ scoped_ptr<HttpStream> stream,
const base::WeakPtr<SpdySession>& spdy_session,
bool direct) {
DCHECK(job);
DCHECK(job->using_spdy());
+ // Note: |spdy_session| may be NULL. In that case, |delegate_| should still
+ // receive |stream| so the error propogates up correctly, however there is no
+ // point in broadcasting |spdy_session| to other requests.
+
// The first case is the usual case.
if (!bound_job_.get()) {
OrphanJobsExcept(job);
@@ -318,29 +295,24 @@ void HttpStreamFactoryImpl::Request::OnNewSpdySessionReady(
// Cache this so we can still use it if the request is deleted.
HttpStreamFactoryImpl* factory = factory_;
if (factory->for_websockets_) {
- DCHECK(websocket_handshake_stream_create_helper_);
- bool use_relative_url = direct || url().SchemeIs("wss");
- delegate_->OnWebSocketHandshakeStreamReady(
- job->server_ssl_config(),
- job->proxy_info(),
- websocket_handshake_stream_create_helper_->CreateSpdyStream(
- spdy_session, use_relative_url));
+ // TODO(ricea): Re-instate this code when WebSockets over SPDY is
+ // implemented.
+ NOTREACHED();
} else {
- bool use_relative_url = direct || url().SchemeIs("https");
- delegate_->OnStreamReady(
- job->server_ssl_config(),
- job->proxy_info(),
- new SpdyHttpStream(spdy_session, use_relative_url));
+ delegate_->OnStreamReady(job->server_ssl_config(), job->proxy_info(),
+ stream.release());
}
// |this| may be deleted after this point.
- factory->OnNewSpdySessionReady(spdy_session,
- direct,
- used_ssl_config,
- used_proxy_info,
- was_npn_negotiated,
- protocol_negotiated,
- using_spdy,
- net_log);
+ if (spdy_session && spdy_session->IsAvailable()) {
+ factory->OnNewSpdySessionReady(spdy_session,
+ direct,
+ used_ssl_config,
+ used_proxy_info,
+ was_npn_negotiated,
+ protocol_negotiated,
+ using_spdy,
+ net_log);
+ }
}
void HttpStreamFactoryImpl::Request::OrphanJobsExcept(Job* job) {
@@ -356,7 +328,6 @@ void HttpStreamFactoryImpl::Request::OrphanJobsExcept(Job* job) {
void HttpStreamFactoryImpl::Request::OrphanJobs() {
RemoveRequestFromSpdySessionRequestMap();
- RemoveRequestFromHttpPipeliningRequestMap();
std::set<Job*> tmp;
tmp.swap(jobs_);
@@ -367,8 +338,7 @@ void HttpStreamFactoryImpl::Request::OrphanJobs() {
void HttpStreamFactoryImpl::Request::OnJobSucceeded(Job* job) {
// |job| should only be NULL if we're being serviced by a late bound
- // SpdySession or HttpPipelinedConnection (one that was not created by a job
- // in our |jobs_| set).
+ // SpdySession (one that was not created by a job in our |jobs_| set).
if (!job) {
DCHECK(!bound_job_.get());
DCHECK(!jobs_.empty());
@@ -380,13 +350,23 @@ void HttpStreamFactoryImpl::Request::OnJobSucceeded(Job* job) {
// they complete? Or do we want to prevent connecting a new SpdySession if
// we've already got one available for a different hostname where the ip
// address matches up?
- } else if (!bound_job_.get()) {
+ return;
+ }
+ if (!bound_job_.get()) {
+ if (jobs_.size() > 1)
+ job->ReportJobSuccededForRequest();
+ // Notify all the other jobs that this one succeeded.
+ for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) {
+ if (*it != job) {
+ (*it)->MarkOtherJobComplete(*job);
+ }
+ }
// We may have other jobs in |jobs_|. For example, if we start multiple jobs
// for Alternate-Protocol.
OrphanJobsExcept(job);
- } else {
- DCHECK(jobs_.empty());
+ return;
}
+ DCHECK(jobs_.empty());
}
} // namespace net
diff --git a/chromium/net/http/http_stream_factory_impl_request.h b/chromium/net/http/http_stream_factory_impl_request.h
index 3d3b2c8bd63..eafc138925f 100644
--- a/chromium/net/http/http_stream_factory_impl_request.h
+++ b/chromium/net/http/http_stream_factory_impl_request.h
@@ -16,6 +16,7 @@
namespace net {
class ClientSocketHandle;
+class HttpStream;
class SpdySession;
class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
@@ -36,12 +37,7 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
// for this SpdySessionKey, since we may need to wait for NPN to complete
// before knowing if SPDY is available.
void SetSpdySessionKey(const SpdySessionKey& spdy_session_key);
-
- // Called when the Job determines the appropriate |http_pipelining_key| for
- // the Request. Registers this Request with the factory, so that if an
- // existing pipeline becomes available, this Request can be late bound to it.
- // Returns true if this is this key was new to the factory.
- bool SetHttpPipeliningKey(const HttpPipelinedHost::Key& http_pipelining_key);
+ bool HasSpdySessionKey() const;
// Attaches |job| to this request. Does not mean that Request will use |job|,
// but Request will own |job|.
@@ -58,12 +54,9 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
// SpdySessionRequestMap.
void RemoveRequestFromSpdySessionRequestMap();
- // If this Request has a |http_pipelining_key_|, remove this session from the
- // HttpPipeliningRequestMap.
- void RemoveRequestFromHttpPipeliningRequestMap();
-
// Called by an attached Job if it sets up a SpdySession.
void OnNewSpdySessionReady(Job* job,
+ scoped_ptr<HttpStream> stream,
const base::WeakPtr<SpdySession>& spdy_session,
bool direct);
@@ -135,7 +128,6 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
scoped_ptr<Job> bound_job_;
std::set<HttpStreamFactoryImpl::Job*> jobs_;
scoped_ptr<const SpdySessionKey> spdy_session_key_;
- scoped_ptr<const HttpPipelinedHost::Key> http_pipelining_key_;
bool completed_;
bool was_npn_negotiated_;
diff --git a/chromium/net/http/http_stream_factory_impl_request_unittest.cc b/chromium/net/http/http_stream_factory_impl_request_unittest.cc
index b3b12bfa5a3..14c06ef7107 100644
--- a/chromium/net/http/http_stream_factory_impl_request_unittest.cc
+++ b/chromium/net/http/http_stream_factory_impl_request_unittest.cc
@@ -20,8 +20,7 @@ INSTANTIATE_TEST_CASE_P(
NextProto,
HttpStreamFactoryImplRequestTest,
testing::Values(kProtoDeprecatedSPDY2,
- kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
- kProtoHTTP2Draft04));
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
namespace {
diff --git a/chromium/net/http/http_stream_factory_impl_unittest.cc b/chromium/net/http/http_stream_factory_impl_unittest.cc
index e3169b65993..e98edbad576 100644
--- a/chromium/net/http/http_stream_factory_impl_unittest.cc
+++ b/chromium/net/http/http_stream_factory_impl_unittest.cc
@@ -43,20 +43,6 @@ namespace net {
namespace {
-class UseAlternateProtocolsScopedSetter {
- public:
- explicit UseAlternateProtocolsScopedSetter(bool use_alternate_protocols)
- : use_alternate_protocols_(HttpStreamFactory::use_alternate_protocols()) {
- HttpStreamFactory::set_use_alternate_protocols(use_alternate_protocols);
- }
- ~UseAlternateProtocolsScopedSetter() {
- HttpStreamFactory::set_use_alternate_protocols(use_alternate_protocols_);
- }
-
- private:
- bool use_alternate_protocols_;
-};
-
class MockWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
public:
enum StreamType {
@@ -87,9 +73,6 @@ class MockWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
return ERR_IO_PENDING;
}
- virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE {
- return NULL;
- }
virtual int ReadResponseBody(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) OVERRIDE {
@@ -420,19 +403,19 @@ CapturePreconnectsSSLSocketPool::CapturePreconnectsSocketPool(
CertVerifier* cert_verifier)
: SSLClientSocketPool(0,
0,
- NULL,
+ NULL, // ssl_histograms
host_resolver,
cert_verifier,
+ NULL, // server_bound_cert_store
+ NULL, // transport_security_state
+ NULL, // cert_transparency_verifier
+ std::string(), // ssl_session_cache_shard
+ NULL, // deterministic_socket_factory
+ NULL, // transport_socket_pool
NULL,
NULL,
- NULL,
- std::string(),
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL),
+ NULL, // ssl_config_service
+ NULL), // net_log
last_num_streams_(-1) {}
class HttpStreamFactoryTest : public ::testing::Test,
@@ -443,8 +426,7 @@ INSTANTIATE_TEST_CASE_P(
NextProto,
HttpStreamFactoryTest,
testing::Values(kProtoDeprecatedSPDY2,
- kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
- kProtoHTTP2Draft04));
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
TEST_P(HttpStreamFactoryTest, PreconnectDirect) {
for (size_t i = 0; i < arraysize(kTests); ++i) {
@@ -546,7 +528,7 @@ TEST_P(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) {
// Put a SpdySession in the pool.
HostPortPair host_port_pair("www.google.com", 443);
SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
- kPrivacyModeDisabled);
+ PRIVACY_MODE_DISABLED);
ignore_result(CreateFakeSpdySession(session->spdy_session_pool(), key));
CapturePreconnectsTransportSocketPool* transport_conn_pool =
@@ -657,13 +639,13 @@ TEST_P(HttpStreamFactoryTest, PrivacyModeDisablesChannelId) {
// Set an existing SpdySession in the pool.
HostPortPair host_port_pair("www.google.com", 443);
SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
- kPrivacyModeEnabled);
+ PRIVACY_MODE_ENABLED);
HttpRequestInfo request_info;
request_info.method = "GET";
request_info.url = GURL("https://www.google.com");
request_info.load_flags = 0;
- request_info.privacy_mode = kPrivacyModeDisabled;
+ request_info.privacy_mode = PRIVACY_MODE_DISABLED;
SSLConfig ssl_config;
StreamRequestWaiter waiter;
@@ -716,7 +698,7 @@ TEST_P(HttpStreamFactoryTest, PrivacyModeUsesDifferentSocketPoolGroup) {
request_info.method = "GET";
request_info.url = GURL("https://www.google.com");
request_info.load_flags = 0;
- request_info.privacy_mode = kPrivacyModeDisabled;
+ request_info.privacy_mode = PRIVACY_MODE_DISABLED;
SSLConfig ssl_config;
StreamRequestWaiter waiter;
@@ -737,7 +719,7 @@ TEST_P(HttpStreamFactoryTest, PrivacyModeUsesDifferentSocketPoolGroup) {
EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 1);
- request_info.privacy_mode = kPrivacyModeEnabled;
+ request_info.privacy_mode = PRIVACY_MODE_ENABLED;
scoped_ptr<HttpStreamRequest> request3(
session->http_stream_factory()->RequestStream(
request_info, DEFAULT_PRIORITY, ssl_config, ssl_config,
@@ -1127,7 +1109,64 @@ TEST_P(HttpStreamFactoryTest, RequestSpdyHttpStream) {
EXPECT_TRUE(waiter.used_proxy_info().is_direct());
}
-TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyHandshakeStream) {
+// TODO(ricea): This test can be removed once the new WebSocket stack supports
+// SPDY. Currently, even if we connect to a SPDY-supporting server, we need to
+// use plain SSL.
+TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyHandshakeStreamButGetSSL) {
+ SpdySessionDependencies session_deps(GetParam(),
+ ProxyService::CreateDirect());
+
+ MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
+ StaticSocketDataProvider socket_data(&mock_read, 1, NULL, 0);
+ socket_data.set_connect_data(MockConnect(ASYNC, OK));
+ session_deps.socket_factory->AddSocketDataProvider(&socket_data);
+
+ SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
+ session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
+
+ HostPortPair host_port_pair("www.google.com", 80);
+ scoped_refptr<HttpNetworkSession>
+ session(SpdySessionDependencies::SpdyCreateSession(&session_deps));
+
+ // Now request a stream.
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("wss://www.google.com");
+ request_info.load_flags = 0;
+
+ SSLConfig ssl_config;
+ StreamRequestWaiter waiter1;
+ WebSocketStreamCreateHelper create_helper;
+ scoped_ptr<HttpStreamRequest> request1(
+ session->http_stream_factory_for_websocket()
+ ->RequestWebSocketHandshakeStream(request_info,
+ DEFAULT_PRIORITY,
+ ssl_config,
+ ssl_config,
+ &waiter1,
+ &create_helper,
+ BoundNetLog()));
+ waiter1.WaitForStream();
+ EXPECT_TRUE(waiter1.stream_done());
+ ASSERT_TRUE(NULL != waiter1.websocket_stream());
+ EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic,
+ waiter1.websocket_stream()->type());
+ EXPECT_TRUE(NULL == waiter1.stream());
+
+ EXPECT_EQ(0, GetSocketPoolGroupCount(
+ session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)));
+ EXPECT_EQ(0, GetSocketPoolGroupCount(
+ session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)));
+ EXPECT_EQ(1, GetSocketPoolGroupCount(
+ session->GetTransportSocketPool(
+ HttpNetworkSession::WEBSOCKET_SOCKET_POOL)));
+ EXPECT_EQ(1, GetSocketPoolGroupCount(
+ session->GetSSLSocketPool(HttpNetworkSession::WEBSOCKET_SOCKET_POOL)));
+ EXPECT_TRUE(waiter1.used_proxy_info().is_direct());
+}
+
+// TODO(ricea): Re-enable once WebSocket-over-SPDY is implemented.
+TEST_P(HttpStreamFactoryTest, DISABLED_RequestWebSocketSpdyHandshakeStream) {
SpdySessionDependencies session_deps(GetParam(),
ProxyService::CreateDirect());
@@ -1203,10 +1242,11 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyHandshakeStream) {
EXPECT_TRUE(waiter1.used_proxy_info().is_direct());
}
-TEST_P(HttpStreamFactoryTest, OrphanedWebSocketStream) {
- UseAlternateProtocolsScopedSetter use_alternate_protocols(true);
+// TODO(ricea): Re-enable once WebSocket over SPDY is implemented.
+TEST_P(HttpStreamFactoryTest, DISABLED_OrphanedWebSocketStream) {
SpdySessionDependencies session_deps(GetParam(),
ProxyService::CreateDirect());
+ session_deps.use_alternate_protocols = true;
MockRead mock_read(ASYNC, OK);
DeterministicSocketData socket_data(&mock_read, 1, NULL, 0);
diff --git a/chromium/net/http/http_stream_parser.cc b/chromium/net/http/http_stream_parser.cc
index 0821c848652..86b188b6a1f 100644
--- a/chromium/net/http/http_stream_parser.cc
+++ b/chromium/net/http/http_stream_parser.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
+#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "net/base/io_buffer.h"
@@ -19,12 +20,14 @@
#include "net/socket/client_socket_handle.h"
#include "net/socket/ssl_client_socket.h"
+namespace net {
+
namespace {
const size_t kMaxMergedHeaderAndBodySize = 1400;
const size_t kRequestBodyBufferSize = 1 << 14; // 16KB
-std::string GetResponseHeaderLines(const net::HttpResponseHeaders& headers) {
+std::string GetResponseHeaderLines(const HttpResponseHeaders& headers) {
std::string raw_headers = headers.raw_headers();
const char* null_separated_headers = raw_headers.c_str();
const char* header_line = null_separated_headers;
@@ -39,9 +42,8 @@ std::string GetResponseHeaderLines(const net::HttpResponseHeaders& headers) {
// Return true if |headers| contain multiple |field_name| fields with different
// values.
-bool HeadersContainMultipleCopiesOfField(
- const net::HttpResponseHeaders& headers,
- const std::string& field_name) {
+bool HeadersContainMultipleCopiesOfField(const HttpResponseHeaders& headers,
+ const std::string& field_name) {
void* it = NULL;
std::string field_value;
if (!headers.EnumerateHeader(&it, field_name, &field_value))
@@ -56,11 +58,10 @@ bool HeadersContainMultipleCopiesOfField(
return false;
}
-base::Value* NetLogSendRequestBodyCallback(
- int length,
- bool is_chunked,
- bool did_merge,
- net::NetLog::LogLevel /* log_level */) {
+base::Value* NetLogSendRequestBodyCallback(int length,
+ bool is_chunked,
+ bool did_merge,
+ NetLog::LogLevel /* log_level */) {
base::DictionaryValue* dict = new base::DictionaryValue();
dict->SetInteger("length", length);
dict->SetBoolean("is_chunked", is_chunked);
@@ -68,9 +69,14 @@ base::Value* NetLogSendRequestBodyCallback(
return dict;
}
-} // namespace
+// Returns true if |error_code| is an error for which we give the server a
+// chance to send a body containing error information, if the error was received
+// while trying to upload a request body.
+bool ShouldTryReadingOnUploadError(int error_code) {
+ return (error_code == ERR_CONNECTION_RESET);
+}
-namespace net {
+} // namespace
// Similar to DrainableIOBuffer(), but this version comes with its own
// storage. The motivation is to avoid repeated allocations of
@@ -101,7 +107,7 @@ namespace net {
// // size() == BytesRemaining() == BytesConsumed() == 0.
// // data() points to the beginning of the buffer.
//
-class HttpStreamParser::SeekableIOBuffer : public net::IOBuffer {
+class HttpStreamParser::SeekableIOBuffer : public IOBuffer {
public:
explicit SeekableIOBuffer(int capacity)
: IOBuffer(capacity),
@@ -176,6 +182,7 @@ HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection,
: io_state_(STATE_NONE),
request_(request),
request_headers_(NULL),
+ request_headers_length_(0),
read_buf_(read_buffer),
read_buf_unused_offset_(0),
response_header_start_offset_(-1),
@@ -187,6 +194,7 @@ HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection,
connection_(connection),
net_log_(net_log),
sent_last_chunk_(false),
+ upload_error_(OK),
weak_ptr_factory_(this) {
io_callback_ = base::Bind(&HttpStreamParser::OnIOComplete,
weak_ptr_factory_.GetWeakPtr());
@@ -223,6 +231,7 @@ int HttpStreamParser::SendRequest(const std::string& request_line,
response_->socket_address = HostPortPair::FromIPEndPoint(ip_endpoint);
std::string request = request_line + headers.ToString();
+ request_headers_length_ = request.size();
if (request_->upload_data_stream != NULL) {
request_body_send_buf_ = new SeekableIOBuffer(kRequestBodyBufferSize);
@@ -237,13 +246,14 @@ int HttpStreamParser::SendRequest(const std::string& request_line,
}
}
- io_state_ = STATE_SENDING_HEADERS;
+ io_state_ = STATE_SEND_HEADERS;
// If we have a small request body, then we'll merge with the headers into a
// single write.
bool did_merge = false;
if (ShouldMergeRequestHeadersAndBody(request, request_->upload_data_stream)) {
- size_t merged_size = request.size() + request_->upload_data_stream->size();
+ size_t merged_size =
+ request_headers_length_ + request_->upload_data_stream->size();
scoped_refptr<IOBuffer> merged_request_headers_and_body(
new IOBuffer(merged_size));
// We'll repurpose |request_headers_| to store the merged headers and
@@ -251,8 +261,8 @@ int HttpStreamParser::SendRequest(const std::string& request_line,
request_headers_ = new DrainableIOBuffer(
merged_request_headers_and_body.get(), merged_size);
- memcpy(request_headers_->data(), request.data(), request.size());
- request_headers_->DidConsume(request.size());
+ memcpy(request_headers_->data(), request.data(), request_headers_length_);
+ request_headers_->DidConsume(request_headers_length_);
size_t todo = request_->upload_data_stream->size();
while (todo) {
@@ -291,7 +301,7 @@ int HttpStreamParser::SendRequest(const std::string& request_line,
}
int HttpStreamParser::ReadResponseHeaders(const CompletionCallback& callback) {
- DCHECK(io_state_ == STATE_REQUEST_SENT || io_state_ == STATE_DONE);
+ DCHECK(io_state_ == STATE_NONE || io_state_ == STATE_DONE);
DCHECK(callback_.is_null());
DCHECK(!callback.is_null());
DCHECK_EQ(0, read_buf_unused_offset_);
@@ -327,7 +337,7 @@ void HttpStreamParser::Close(bool not_reusable) {
int HttpStreamParser::ReadResponseBody(IOBuffer* buf, int buf_len,
const CompletionCallback& callback) {
- DCHECK(io_state_ == STATE_BODY_PENDING || io_state_ == STATE_DONE);
+ DCHECK(io_state_ == STATE_NONE || io_state_ == STATE_DONE);
DCHECK(callback_.is_null());
DCHECK(!callback.is_null());
DCHECK_LE(buf_len, kMaxBufSize);
@@ -359,30 +369,33 @@ void HttpStreamParser::OnIOComplete(int result) {
}
int HttpStreamParser::DoLoop(int result) {
- bool can_do_more = true;
do {
- switch (io_state_) {
- case STATE_SENDING_HEADERS:
- if (result < 0)
- can_do_more = false;
- else
- result = DoSendHeaders(result);
+ DCHECK_NE(ERR_IO_PENDING, result);
+ DCHECK_NE(STATE_DONE, io_state_);
+ DCHECK_NE(STATE_NONE, io_state_);
+ State state = io_state_;
+ io_state_ = STATE_NONE;
+ switch (state) {
+ case STATE_SEND_HEADERS:
+ DCHECK_EQ(OK, result);
+ result = DoSendHeaders();
break;
- case STATE_SENDING_BODY:
- if (result < 0)
- can_do_more = false;
- else
- result = DoSendBody(result);
+ case STATE_SEND_HEADERS_COMPLETE:
+ result = DoSendHeadersComplete(result);
break;
- case STATE_SEND_REQUEST_READING_BODY:
- result = DoSendRequestReadingBody(result);
+ case STATE_SEND_BODY:
+ DCHECK_EQ(OK, result);
+ result = DoSendBody();
break;
- case STATE_REQUEST_SENT:
- DCHECK(result != ERR_IO_PENDING);
- can_do_more = false;
+ case STATE_SEND_BODY_COMPLETE:
+ result = DoSendBodyComplete(result);
+ break;
+ case STATE_SEND_REQUEST_READ_BODY_COMPLETE:
+ result = DoSendRequestReadBodyComplete(result);
break;
case STATE_READ_HEADERS:
net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS);
+ DCHECK_GE(result, 0);
result = DoReadHeaders();
break;
case STATE_READ_HEADERS_COMPLETE:
@@ -390,68 +403,79 @@ int HttpStreamParser::DoLoop(int result) {
net_log_.EndEventWithNetErrorCode(
NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, result);
break;
- case STATE_BODY_PENDING:
- DCHECK(result != ERR_IO_PENDING);
- can_do_more = false;
- break;
case STATE_READ_BODY:
+ DCHECK_GE(result, 0);
result = DoReadBody();
- // DoReadBodyComplete handles error conditions.
break;
case STATE_READ_BODY_COMPLETE:
result = DoReadBodyComplete(result);
break;
- case STATE_DONE:
- DCHECK(result != ERR_IO_PENDING);
- can_do_more = false;
- break;
default:
NOTREACHED();
- can_do_more = false;
break;
}
- } while (result != ERR_IO_PENDING && can_do_more);
+ } while (result != ERR_IO_PENDING &&
+ (io_state_ != STATE_DONE && io_state_ != STATE_NONE));
return result;
}
-int HttpStreamParser::DoSendHeaders(int result) {
- request_headers_->DidConsume(result);
+int HttpStreamParser::DoSendHeaders() {
int bytes_remaining = request_headers_->BytesRemaining();
- if (bytes_remaining > 0) {
- // Record our best estimate of the 'request time' as the time when we send
- // out the first bytes of the request headers.
- if (bytes_remaining == request_headers_->size()) {
- response_->request_time = base::Time::Now();
+ DCHECK_GT(bytes_remaining, 0);
+
+ // Record our best estimate of the 'request time' as the time when we send
+ // out the first bytes of the request headers.
+ if (bytes_remaining == request_headers_->size())
+ response_->request_time = base::Time::Now();
+
+ io_state_ = STATE_SEND_HEADERS_COMPLETE;
+ return connection_->socket()
+ ->Write(request_headers_.get(), bytes_remaining, io_callback_);
+}
+
+int HttpStreamParser::DoSendHeadersComplete(int result) {
+ if (result < 0) {
+ // In the unlikely case that the headers and body were merged, all the
+ // the headers were sent, but not all of the body way, and |result| is
+ // an error that this should try reading after, stash the error for now and
+ // act like the request was successfully sent.
+ if (request_headers_->BytesConsumed() >= request_headers_length_ &&
+ ShouldTryReadingOnUploadError(result)) {
+ upload_error_ = result;
+ return OK;
}
- result = connection_->socket()
- ->Write(request_headers_.get(), bytes_remaining, io_callback_);
- } else if (request_->upload_data_stream != NULL &&
- (request_->upload_data_stream->is_chunked() ||
- // !IsEOF() indicates that the body wasn't merged.
- (request_->upload_data_stream->size() > 0 &&
- !request_->upload_data_stream->IsEOF()))) {
+ return result;
+ }
+
+ request_headers_->DidConsume(result);
+ if (request_headers_->BytesRemaining() > 0) {
+ io_state_ = STATE_SEND_HEADERS;
+ return OK;
+ }
+
+ if (request_->upload_data_stream != NULL &&
+ (request_->upload_data_stream->is_chunked() ||
+ // !IsEOF() indicates that the body wasn't merged.
+ (request_->upload_data_stream->size() > 0 &&
+ !request_->upload_data_stream->IsEOF()))) {
net_log_.AddEvent(
NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY,
base::Bind(&NetLogSendRequestBodyCallback,
request_->upload_data_stream->size(),
request_->upload_data_stream->is_chunked(),
false /* not merged */));
- io_state_ = STATE_SENDING_BODY;
- result = OK;
- } else {
- io_state_ = STATE_REQUEST_SENT;
+ io_state_ = STATE_SEND_BODY;
+ return OK;
}
- return result;
-}
-int HttpStreamParser::DoSendBody(int result) {
- // |result| is the number of bytes sent from the last call to
- // DoSendBody(), or 0 (i.e. OK).
+ // Finished sending the request.
+ return OK;
+}
- // Send the remaining data in the request body buffer.
- request_body_send_buf_->DidConsume(result);
+int HttpStreamParser::DoSendBody() {
if (request_body_send_buf_->BytesRemaining() > 0) {
+ io_state_ = STATE_SEND_BODY_COMPLETE;
return connection_->socket()
->Write(request_body_send_buf_.get(),
request_body_send_buf_->BytesRemaining(),
@@ -459,18 +483,35 @@ int HttpStreamParser::DoSendBody(int result) {
}
if (request_->upload_data_stream->is_chunked() && sent_last_chunk_) {
- io_state_ = STATE_REQUEST_SENT;
+ // Finished sending the request.
return OK;
}
request_body_read_buf_->Clear();
- io_state_ = STATE_SEND_REQUEST_READING_BODY;
+ io_state_ = STATE_SEND_REQUEST_READ_BODY_COMPLETE;
return request_->upload_data_stream->Read(request_body_read_buf_.get(),
request_body_read_buf_->capacity(),
io_callback_);
}
-int HttpStreamParser::DoSendRequestReadingBody(int result) {
+int HttpStreamParser::DoSendBodyComplete(int result) {
+ if (result < 0) {
+ // If |result| is an error that this should try reading after, stash the
+ // error for now and act like the request was successfully sent.
+ if (ShouldTryReadingOnUploadError(result)) {
+ upload_error_ = result;
+ return OK;
+ }
+ return result;
+ }
+
+ request_body_send_buf_->DidConsume(result);
+
+ io_state_ = STATE_SEND_BODY;
+ return OK;
+}
+
+int HttpStreamParser::DoSendRequestReadBodyComplete(int result) {
// |result| is the result of read from the request body from the last call to
// DoSendBody().
DCHECK_GE(result, 0); // There won't be errors.
@@ -494,11 +535,11 @@ int HttpStreamParser::DoSendRequestReadingBody(int result) {
// chunked. (i.e. No need to send the terminal chunk.)
DCHECK(request_->upload_data_stream->IsEOF());
DCHECK(!request_->upload_data_stream->is_chunked());
- io_state_ = STATE_REQUEST_SENT;
+ // Finished sending the request.
} else if (result > 0) {
request_body_send_buf_->DidAppend(result);
result = 0;
- io_state_ = STATE_SENDING_BODY;
+ io_state_ = STATE_SEND_BODY;
}
return result;
}
@@ -519,110 +560,50 @@ int HttpStreamParser::DoReadHeaders() {
}
int HttpStreamParser::DoReadHeadersComplete(int result) {
- DCHECK_EQ(0, read_buf_unused_offset_);
+ result = HandleReadHeaderResult(result);
- if (result == 0)
- result = ERR_CONNECTION_CLOSED;
+ // TODO(mmenke): The code below is ugly and hacky. A much better and more
+ // flexible long term solution would be to separate out the read and write
+ // loops, though this would involve significant changes, both here and
+ // elsewhere (WebSockets, for instance).
- if (result < 0 && result != ERR_CONNECTION_CLOSED) {
- io_state_ = STATE_DONE;
+ // If still reading the headers, or there was no error uploading the request
+ // body, just return the result.
+ if (io_state_ == STATE_READ_HEADERS || upload_error_ == OK)
return result;
- }
- // If we've used the connection before, then we know it is not a HTTP/0.9
- // response and return ERR_CONNECTION_CLOSED.
- if (result == ERR_CONNECTION_CLOSED && read_buf_->offset() == 0 &&
- connection_->is_reused()) {
+
+ // If the result is ERR_IO_PENDING, |io_state_| should be STATE_READ_HEADERS.
+ DCHECK_NE(ERR_IO_PENDING, result);
+
+ // On errors, use the original error received when sending the request.
+ // The main cases where these are different is when there's a header-related
+ // error code, or when there's an ERR_CONNECTION_CLOSED, which can result in
+ // special handling of partial responses and HTTP/0.9 responses.
+ if (result < 0) {
+ // Nothing else to do. In the HTTP/0.9 or only partial headers received
+ // cases, can normally go to other states after an error reading headers.
io_state_ = STATE_DONE;
- return result;
+ // Don't let caller see the headers.
+ response_->headers = NULL;
+ return upload_error_;
}
- // Record our best estimate of the 'response time' as the time when we read
- // the first bytes of the response headers.
- if (read_buf_->offset() == 0 && result != ERR_CONNECTION_CLOSED)
- response_->response_time = base::Time::Now();
-
- if (result == ERR_CONNECTION_CLOSED) {
- // The connection closed before we detected the end of the headers.
- if (read_buf_->offset() == 0) {
- // The connection was closed before any data was sent. Likely an error
- // rather than empty HTTP/0.9 response.
- io_state_ = STATE_DONE;
- return ERR_EMPTY_RESPONSE;
- } else if (request_->url.SchemeIsSecure()) {
- // The connection was closed in the middle of the headers. For HTTPS we
- // don't parse partial headers. Return a different error code so that we
- // know that we shouldn't attempt to retry the request.
- io_state_ = STATE_DONE;
- return ERR_RESPONSE_HEADERS_TRUNCATED;
- }
- // Parse things as well as we can and let the caller decide what to do.
- int end_offset;
- if (response_header_start_offset_ >= 0) {
- io_state_ = STATE_READ_BODY_COMPLETE;
- end_offset = read_buf_->offset();
- } else {
- io_state_ = STATE_BODY_PENDING;
- end_offset = 0;
- }
- int rv = DoParseResponseHeaders(end_offset);
- if (rv < 0)
- return rv;
+ // Skip over 1xx responses as usual, and allow 4xx/5xx error responses to
+ // override the error received while uploading the body.
+ int response_code_class = response_->headers->response_code() / 100;
+ if (response_code_class == 1 || response_code_class == 4 ||
+ response_code_class == 5) {
return result;
}
- read_buf_->set_offset(read_buf_->offset() + result);
- DCHECK_LE(read_buf_->offset(), read_buf_->capacity());
- DCHECK_GE(result, 0);
-
- int end_of_header_offset = ParseResponseHeaders();
-
- // Note: -1 is special, it indicates we haven't found the end of headers.
- // Anything less than -1 is a net::Error, so we bail out.
- if (end_of_header_offset < -1)
- return end_of_header_offset;
-
- if (end_of_header_offset == -1) {
- io_state_ = STATE_READ_HEADERS;
- // Prevent growing the headers buffer indefinitely.
- if (read_buf_->offset() >= kMaxHeaderBufSize) {
- io_state_ = STATE_DONE;
- return ERR_RESPONSE_HEADERS_TOO_BIG;
- }
- } else {
- CalculateResponseBodySize();
- // If the body is zero length, the caller may not call ReadResponseBody,
- // which is where any extra data is copied to read_buf_, so we move the
- // data here.
- if (response_body_length_ == 0) {
- int extra_bytes = read_buf_->offset() - end_of_header_offset;
- if (extra_bytes) {
- CHECK_GT(extra_bytes, 0);
- memmove(read_buf_->StartOfBuffer(),
- read_buf_->StartOfBuffer() + end_of_header_offset,
- extra_bytes);
- }
- read_buf_->SetCapacity(extra_bytes);
- if (response_->headers->response_code() / 100 == 1) {
- // After processing a 1xx response, the caller will ask for the next
- // header, so reset state to support that. We don't completely ignore a
- // 1xx response because it cannot be returned in reply to a CONNECT
- // request so we return OK here, which lets the caller inspect the
- // response and reject it in the event that we're setting up a CONNECT
- // tunnel.
- response_header_start_offset_ = -1;
- response_body_length_ = -1;
- io_state_ = STATE_REQUEST_SENT;
- } else {
- io_state_ = STATE_DONE;
- }
- return OK;
- }
+ // All other status codes are not allowed after an error during upload, to
+ // make sure the consumer has some indication there was an error.
- // Note where the headers stop.
- read_buf_unused_offset_ = end_of_header_offset;
- io_state_ = STATE_BODY_PENDING;
- }
- return result;
+ // Nothing else to do.
+ io_state_ = STATE_DONE;
+ // Don't let caller see the headers.
+ response_->headers = NULL;
+ return upload_error_;
}
int HttpStreamParser::DoReadBody() {
@@ -751,7 +732,7 @@ int HttpStreamParser::DoReadBodyComplete(int result) {
}
read_buf_unused_offset_ = 0;
} else {
- io_state_ = STATE_BODY_PENDING;
+ // Now waiting for more of the body to be read.
user_read_buf_ = NULL;
user_read_buf_len_ = 0;
}
@@ -759,6 +740,113 @@ int HttpStreamParser::DoReadBodyComplete(int result) {
return result;
}
+int HttpStreamParser::HandleReadHeaderResult(int result) {
+ DCHECK_EQ(0, read_buf_unused_offset_);
+
+ if (result == 0)
+ result = ERR_CONNECTION_CLOSED;
+
+ if (result < 0 && result != ERR_CONNECTION_CLOSED) {
+ io_state_ = STATE_DONE;
+ return result;
+ }
+ // If we've used the connection before, then we know it is not a HTTP/0.9
+ // response and return ERR_CONNECTION_CLOSED.
+ if (result == ERR_CONNECTION_CLOSED && read_buf_->offset() == 0 &&
+ connection_->is_reused()) {
+ io_state_ = STATE_DONE;
+ return result;
+ }
+
+ // Record our best estimate of the 'response time' as the time when we read
+ // the first bytes of the response headers.
+ if (read_buf_->offset() == 0 && result != ERR_CONNECTION_CLOSED)
+ response_->response_time = base::Time::Now();
+
+ if (result == ERR_CONNECTION_CLOSED) {
+ // The connection closed before we detected the end of the headers.
+ if (read_buf_->offset() == 0) {
+ // The connection was closed before any data was sent. Likely an error
+ // rather than empty HTTP/0.9 response.
+ io_state_ = STATE_DONE;
+ return ERR_EMPTY_RESPONSE;
+ } else if (request_->url.SchemeIsSecure()) {
+ // The connection was closed in the middle of the headers. For HTTPS we
+ // don't parse partial headers. Return a different error code so that we
+ // know that we shouldn't attempt to retry the request.
+ io_state_ = STATE_DONE;
+ return ERR_RESPONSE_HEADERS_TRUNCATED;
+ }
+ // Parse things as well as we can and let the caller decide what to do.
+ int end_offset;
+ if (response_header_start_offset_ >= 0) {
+ io_state_ = STATE_READ_BODY_COMPLETE;
+ end_offset = read_buf_->offset();
+ } else {
+ // Now waiting for the body to be read.
+ end_offset = 0;
+ }
+ int rv = DoParseResponseHeaders(end_offset);
+ if (rv < 0)
+ return rv;
+ return result;
+ }
+
+ read_buf_->set_offset(read_buf_->offset() + result);
+ DCHECK_LE(read_buf_->offset(), read_buf_->capacity());
+ DCHECK_GE(result, 0);
+
+ int end_of_header_offset = ParseResponseHeaders();
+
+ // Note: -1 is special, it indicates we haven't found the end of headers.
+ // Anything less than -1 is a net::Error, so we bail out.
+ if (end_of_header_offset < -1)
+ return end_of_header_offset;
+
+ if (end_of_header_offset == -1) {
+ io_state_ = STATE_READ_HEADERS;
+ // Prevent growing the headers buffer indefinitely.
+ if (read_buf_->offset() >= kMaxHeaderBufSize) {
+ io_state_ = STATE_DONE;
+ return ERR_RESPONSE_HEADERS_TOO_BIG;
+ }
+ } else {
+ CalculateResponseBodySize();
+ // If the body is zero length, the caller may not call ReadResponseBody,
+ // which is where any extra data is copied to read_buf_, so we move the
+ // data here.
+ if (response_body_length_ == 0) {
+ int extra_bytes = read_buf_->offset() - end_of_header_offset;
+ if (extra_bytes) {
+ CHECK_GT(extra_bytes, 0);
+ memmove(read_buf_->StartOfBuffer(),
+ read_buf_->StartOfBuffer() + end_of_header_offset,
+ extra_bytes);
+ }
+ read_buf_->SetCapacity(extra_bytes);
+ if (response_->headers->response_code() / 100 == 1) {
+ // After processing a 1xx response, the caller will ask for the next
+ // header, so reset state to support that. We don't completely ignore a
+ // 1xx response because it cannot be returned in reply to a CONNECT
+ // request so we return OK here, which lets the caller inspect the
+ // response and reject it in the event that we're setting up a CONNECT
+ // tunnel.
+ response_header_start_offset_ = -1;
+ response_body_length_ = -1;
+ // Now waiting for the second set of headers to be read.
+ } else {
+ io_state_ = STATE_DONE;
+ }
+ return OK;
+ }
+
+ // Note where the headers stop.
+ read_buf_unused_offset_ = end_of_header_offset;
+ // Now waiting for the body to be read.
+ }
+ return result;
+}
+
int HttpStreamParser::ParseResponseHeaders() {
int end_offset = -1;
DCHECK_EQ(0, read_buf_unused_offset_);
@@ -876,10 +964,6 @@ UploadProgress HttpStreamParser::GetUploadProgress() const {
request_->upload_data_stream->size());
}
-HttpResponseInfo* HttpStreamParser::GetResponseInfo() {
- return response_;
-}
-
bool HttpStreamParser::IsResponseBodyComplete() const {
if (chunked_decoder_.get())
return chunked_decoder_->reached_eof();
@@ -904,7 +988,7 @@ bool HttpStreamParser::IsConnectionReused() const {
}
void HttpStreamParser::SetConnectionReused() {
- connection_->set_is_reused(true);
+ connection_->set_reuse_type(ClientSocketHandle::REUSED_IDLE);
}
bool HttpStreamParser::IsConnectionReusable() const {
diff --git a/chromium/net/http/http_stream_parser.h b/chromium/net/http/http_stream_parser.h
index e3690322bbd..a8d0447a086 100644
--- a/chromium/net/http/http_stream_parser.h
+++ b/chromium/net/http/http_stream_parser.h
@@ -63,8 +63,6 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
// zero, but position will not be.
UploadProgress GetUploadProgress() const;
- HttpResponseInfo* GetResponseInfo();
-
bool IsResponseBodyComplete() const;
bool CanFindEndOfResponse() const;
@@ -110,17 +108,16 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
// FOO_COMPLETE states implement the second half of potentially asynchronous
// operations and don't necessarily mean that FOO is complete.
enum State {
+ // STATE_NONE indicates that this is waiting on an external call before
+ // continuing.
STATE_NONE,
- STATE_SENDING_HEADERS,
- // If the request comes with a body, either of the following two
- // states will be executed, depending on whether the body is chunked
- // or not.
- STATE_SENDING_BODY,
- STATE_SEND_REQUEST_READING_BODY,
- STATE_REQUEST_SENT,
+ STATE_SEND_HEADERS,
+ STATE_SEND_HEADERS_COMPLETE,
+ STATE_SEND_BODY,
+ STATE_SEND_BODY_COMPLETE,
+ STATE_SEND_REQUEST_READ_BODY_COMPLETE,
STATE_READ_HEADERS,
STATE_READ_HEADERS_COMPLETE,
- STATE_BODY_PENDING,
STATE_READ_BODY,
STATE_READ_BODY_COMPLETE,
STATE_DONE
@@ -146,14 +143,19 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
int DoLoop(int result);
// The implementations of each state of the state machine.
- int DoSendHeaders(int result);
- int DoSendBody(int result);
- int DoSendRequestReadingBody(int result);
+ int DoSendHeaders();
+ int DoSendHeadersComplete(int result);
+ int DoSendBody();
+ int DoSendBodyComplete(int result);
+ int DoSendRequestReadBodyComplete(int result);
int DoReadHeaders();
int DoReadHeadersComplete(int result);
int DoReadBody();
int DoReadBodyComplete(int result);
+ // This handles most of the logic for DoReadHeadersComplete.
+ int HandleReadHeaderResult(int result);
+
// Examines |read_buf_| to find the start and end of the headers. If they are
// found, parse them with DoParseResponseHeaders(). Return the offset for
// the end of the headers, or -1 if the complete headers were not found, or
@@ -167,15 +169,19 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
// Examine the parsed headers to try to determine the response body size.
void CalculateResponseBodySize();
- // Current state of the request.
+ // Next state of the request, when the current one completes.
State io_state_;
// The request to send.
const HttpRequestInfo* request_;
- // The request header data.
+ // The request header data. May include a merged request body.
scoped_refptr<DrainableIOBuffer> request_headers_;
+ // Size of just the request headers. May be less than the length of
+ // |request_headers_| if the body was merged with the headers.
+ int request_headers_length_;
+
// Temporary buffer for reading.
scoped_refptr<GrowableIOBuffer> read_buf_;
@@ -192,7 +198,10 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
// value may be bigger than final.
int64 received_bytes_;
- // The parsed response headers. Owned by the caller.
+ // The parsed response headers. Owned by the caller of SendRequest. This
+ // cannot be safely accessed after reading the final set of headers, as the
+ // caller of SendRequest may have been destroyed - this happens in the case an
+ // HttpResponseBodyDrainer is used.
HttpResponseInfo* response_;
// Indicates the content length. If this value is less than zero
@@ -235,6 +244,9 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
scoped_refptr<SeekableIOBuffer> request_body_send_buf_;
bool sent_last_chunk_;
+ // Error received when uploading the body, if any.
+ int upload_error_;
+
base::WeakPtrFactory<HttpStreamParser> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(HttpStreamParser);
diff --git a/chromium/net/http/http_stream_parser_unittest.cc b/chromium/net/http/http_stream_parser_unittest.cc
index dcaf1f3e9c3..33910395cbc 100644
--- a/chromium/net/http/http_stream_parser_unittest.cc
+++ b/chromium/net/http/http_stream_parser_unittest.cc
@@ -804,6 +804,63 @@ TEST(HttpStreamParser, ReceivedBytesIncludesContinueHeader) {
EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
}
+// Test that an HttpStreamParser can be read from after it's received headers
+// and data structures owned by its owner have been deleted. This happens
+// when a ResponseBodyDrainer is used.
+TEST(HttpStreamParser, ReadAfterUnownedObjectsDestroyed) {
+ MockWrite writes[] = {
+ MockWrite(SYNCHRONOUS, 0,
+ "GET /foo.html HTTP/1.1\r\n\r\n"),
+ MockWrite(SYNCHRONOUS, 1, "1"),
+ };
+
+ const int kBodySize = 1;
+ MockRead reads[] = {
+ MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
+ MockRead(SYNCHRONOUS, 6, "Content-Length: 1\r\n\r\n"),
+ MockRead(SYNCHRONOUS, 6, "Connection: Keep-Alive\r\n\r\n"),
+ MockRead(SYNCHRONOUS, 7, "1"),
+ MockRead(SYNCHRONOUS, 0, 8), // EOF
+ };
+
+ StaticSocketDataProvider data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
+
+ scoped_ptr<MockTCPClientSocket> transport(
+ new MockTCPClientSocket(AddressList(), NULL, &data));
+
+ TestCompletionCallback callback;
+ ASSERT_EQ(OK, transport->Connect(callback.callback()));
+
+ scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle);
+ socket_handle->SetSocket(transport.PassAs<StreamSocket>());
+
+ scoped_ptr<HttpRequestInfo> request_info(new HttpRequestInfo());
+ request_info->method = "GET";
+ request_info->url = GURL("http://somewhere/foo.html");
+
+ scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer);
+ HttpStreamParser parser(socket_handle.get(), request_info.get(),
+ read_buffer.get(), BoundNetLog());
+
+ scoped_ptr<HttpRequestHeaders> request_headers(new HttpRequestHeaders());
+ scoped_ptr<HttpResponseInfo> response_info(new HttpResponseInfo());
+ ASSERT_EQ(OK, parser.SendRequest("GET /foo.html HTTP/1.1\r\n",
+ *request_headers, response_info.get(), callback.callback()));
+ ASSERT_EQ(OK, parser.ReadResponseHeaders(callback.callback()));
+
+ // If the object that owns the HttpStreamParser is deleted, it takes the
+ // objects passed to the HttpStreamParser with it.
+ request_info.reset();
+ request_headers.reset();
+ response_info.reset();
+
+ scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize));
+ ASSERT_EQ(kBodySize, parser.ReadResponseBody(
+ body_buffer.get(), kBodySize, callback.callback()));
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/http/http_transaction.h b/chromium/net/http/http_transaction.h
index 849d03af50c..ed1b20dac2f 100644
--- a/chromium/net/http/http_transaction.h
+++ b/chromium/net/http/http_transaction.h
@@ -21,6 +21,7 @@ struct HttpRequestInfo;
class HttpResponseInfo;
class IOBuffer;
struct LoadTimingInfo;
+class QuicServerInfo;
class X509Certificate;
// Represents a single HTTP transaction (i.e., a single request/response pair).
@@ -28,6 +29,10 @@ class X509Certificate;
// answered. Cookies are assumed to be managed by the caller.
class NET_EXPORT_PRIVATE HttpTransaction {
public:
+ // If |*defer| is set to true, the transaction will wait until
+ // ResumeNetworkStart is called before establishing a connection.
+ typedef base::Callback<void(bool* defer)> BeforeNetworkStartCallback;
+
// Stops any pending IO and destroys the transaction object.
virtual ~HttpTransaction() {}
@@ -106,6 +111,9 @@ class NET_EXPORT_PRIVATE HttpTransaction {
// otherwise, returns false and does not modify headers.
virtual bool GetFullRequestHeaders(HttpRequestHeaders* headers) const = 0;
+ // Get the number of bytes received from network.
+ virtual int64 GetTotalReceivedBytes() const = 0;
+
// Called to tell the transaction that we have successfully reached the end
// of the stream. This is equivalent to performing an extra Read() at the end
// that should return 0 bytes. This method should not be called if the
@@ -126,6 +134,10 @@ class NET_EXPORT_PRIVATE HttpTransaction {
// zero will be returned. This does not include the request headers.
virtual UploadProgress GetUploadProgress() const = 0;
+ // SetQuicServerInfo sets a object which reads and writes public information
+ // about a QUIC server.
+ virtual void SetQuicServerInfo(QuicServerInfo* quic_server_info) = 0;
+
// Populates all of load timing, except for request start times and receive
// headers time.
// |load_timing_info| must have all null times when called. Returns false and
@@ -141,6 +153,13 @@ class NET_EXPORT_PRIVATE HttpTransaction {
// Start(). Ownership of |create_helper| remains with the caller.
virtual void SetWebSocketHandshakeStreamCreateHelper(
WebSocketHandshakeStreamBase::CreateHelper* create_helper) = 0;
+
+ // Set the callback to receive notification just before network use.
+ virtual void SetBeforeNetworkStartCallback(
+ const BeforeNetworkStartCallback& callback) = 0;
+
+ // Resumes the transaction after being deferred.
+ virtual int ResumeNetworkStart() = 0;
};
} // namespace net
diff --git a/chromium/net/http/http_transaction_delegate.h b/chromium/net/http/http_transaction_delegate.h
deleted file mode 100644
index 18493733bff..00000000000
--- a/chromium/net/http/http_transaction_delegate.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2012 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_HTTP_HTTP_TRANSACTION_DELEGATE_H_
-#define NET_HTTP_HTTP_TRANSACTION_DELEGATE_H_
-
-namespace net {
-
-// Delegate class receiving notifications when cache or network actions start
-// and finish, i.e. when the object starts and finishes waiting on an
-// underlying cache or the network. The owner of a HttpTransaction can use
-// this to register a delegate to receive notifications when these events
-// happen.
-class HttpTransactionDelegate {
- public:
- virtual ~HttpTransactionDelegate() {}
- virtual void OnCacheActionStart() = 0;
- virtual void OnCacheActionFinish() = 0;
- virtual void OnNetworkActionStart() = 0;
- virtual void OnNetworkActionFinish() = 0;
-};
-
-} // namespace net
-
-#endif // NET_HTTP_HTTP_TRANSACTION_DELEGATE_H_
diff --git a/chromium/net/http/http_transaction_factory.h b/chromium/net/http/http_transaction_factory.h
index d9870be914b..673a6f921e3 100644
--- a/chromium/net/http/http_transaction_factory.h
+++ b/chromium/net/http/http_transaction_factory.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_HTTP_HTTP_TRANSACTION_FACTORY_H__
-#define NET_HTTP_HTTP_TRANSACTION_FACTORY_H__
+#ifndef NET_HTTP_HTTP_TRANSACTION_FACTORY_H_
+#define NET_HTTP_HTTP_TRANSACTION_FACTORY_H_
#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
@@ -14,7 +14,6 @@ namespace net {
class HttpCache;
class HttpNetworkSession;
class HttpTransaction;
-class HttpTransactionDelegate;
// An interface to a class that can create HttpTransaction objects.
class NET_EXPORT HttpTransactionFactory {
@@ -24,8 +23,7 @@ class NET_EXPORT HttpTransactionFactory {
// Creates a HttpTransaction object. On success, saves the new
// transaction to |*trans| and returns OK.
virtual int CreateTransaction(RequestPriority priority,
- scoped_ptr<HttpTransaction>* trans,
- HttpTransactionDelegate* delegate) = 0;
+ scoped_ptr<HttpTransaction>* trans) = 0;
// Returns the associated cache if any (may be NULL).
virtual HttpCache* GetCache() = 0;
@@ -36,4 +34,4 @@ class NET_EXPORT HttpTransactionFactory {
} // namespace net
-#endif // NET_HTTP_HTTP_TRANSACTION_FACTORY_H__
+#endif // NET_HTTP_HTTP_TRANSACTION_FACTORY_H_
diff --git a/chromium/net/http/http_transaction_unittest.cc b/chromium/net/http/http_transaction_test_util.cc
index e161ecac506..f3d086c5133 100644
--- a/chromium/net/http/http_transaction_unittest.cc
+++ b/chromium/net/http/http_transaction_test_util.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2014 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.
-#include "net/http/http_transaction_unittest.h"
+#include "net/http/http_transaction_test_util.h"
#include <algorithm>
@@ -157,7 +157,7 @@ TestTransactionConsumer::TestTransactionConsumer(
net::HttpTransactionFactory* factory)
: state_(IDLE), error_(net::OK) {
// Disregard the error code.
- factory->CreateTransaction(priority, &trans_, NULL);
+ factory->CreateTransaction(priority, &trans_);
++quit_counter_;
}
@@ -226,10 +226,12 @@ MockNetworkTransaction::MockNetworkTransaction(
net::RequestPriority priority,
MockNetworkLayer* factory)
: weak_factory_(this),
+ request_(NULL),
data_cursor_(0),
priority_(priority),
websocket_handshake_stream_create_helper_(NULL),
transaction_factory_(factory->AsWeakPtr()),
+ received_bytes_(0),
socket_log_id_(net::NetLog::Source::kInvalidId) {
}
@@ -238,54 +240,11 @@ MockNetworkTransaction::~MockNetworkTransaction() {}
int MockNetworkTransaction::Start(const net::HttpRequestInfo* request,
const net::CompletionCallback& callback,
const net::BoundNetLog& net_log) {
- const MockTransaction* t = FindMockTransaction(request->url);
- if (!t)
+ if (request_)
return net::ERR_FAILED;
- test_mode_ = t->test_mode;
-
- // Return immediately if we're returning an error.
- if (net::OK != t->return_code) {
- if (test_mode_ & TEST_MODE_SYNC_NET_START)
- return t->return_code;
- CallbackLater(callback, t->return_code);
- return net::ERR_IO_PENDING;
- }
-
- std::string resp_status = t->status;
- std::string resp_headers = t->response_headers;
- std::string resp_data = t->data;
- if (t->handler)
- (t->handler)(request, &resp_status, &resp_headers, &resp_data);
-
- std::string header_data = base::StringPrintf(
- "%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
- std::replace(header_data.begin(), header_data.end(), '\n', '\0');
-
- response_.request_time = base::Time::Now();
- if (!t->request_time.is_null())
- response_.request_time = t->request_time;
-
- response_.was_cached = false;
- response_.network_accessed = true;
-
- response_.response_time = base::Time::Now();
- if (!t->response_time.is_null())
- response_.response_time = t->response_time;
-
- response_.headers = new net::HttpResponseHeaders(header_data);
- response_.vary_data.Init(*request, *response_.headers.get());
- response_.ssl_info.cert_status = t->cert_status;
- data_ = resp_data;
-
- if (net_log.net_log())
- socket_log_id_ = net_log.net_log()->NextID();
-
- if (test_mode_ & TEST_MODE_SYNC_NET_START)
- return net::OK;
-
- CallbackLater(callback, net::OK);
- return net::ERR_IO_PENDING;
+ request_ = request;
+ return StartInternal(request, callback, net_log);
}
int MockNetworkTransaction::RestartIgnoringLastError(
@@ -302,17 +261,32 @@ int MockNetworkTransaction::RestartWithCertificate(
int MockNetworkTransaction::RestartWithAuth(
const net::AuthCredentials& credentials,
const net::CompletionCallback& callback) {
- return net::ERR_FAILED;
+ if (!IsReadyToRestartForAuth())
+ return net::ERR_FAILED;
+
+ net::HttpRequestInfo auth_request_info = *request_;
+ auth_request_info.extra_headers.AddHeaderFromString("Authorization: Bar");
+
+ // Let the MockTransactionHandler worry about this: the only way for this
+ // test to succeed is by using an explicit handler for the transaction so
+ // that server behavior can be simulated.
+ return StartInternal(&auth_request_info, callback, net::BoundNetLog());
}
bool MockNetworkTransaction::IsReadyToRestartForAuth() {
- return false;
+ if (!request_)
+ return false;
+
+ // Only mock auth when the test asks for it.
+ return request_->extra_headers.HasHeader("X-Require-Mock-Auth");
}
int MockNetworkTransaction::Read(net::IOBuffer* buf, int buf_len,
const net::CompletionCallback& callback) {
int data_len = static_cast<int>(data_.size());
int num = std::min(buf_len, data_len - data_cursor_);
+ if (test_mode_ & TEST_MODE_SLOW_READ)
+ num = std::min(num, 1);
if (num) {
memcpy(buf->data(), data_.data() + data_cursor_, num);
data_cursor_ += num;
@@ -324,13 +298,20 @@ int MockNetworkTransaction::Read(net::IOBuffer* buf, int buf_len,
return net::ERR_IO_PENDING;
}
-void MockNetworkTransaction::StopCaching() {}
+void MockNetworkTransaction::StopCaching() {
+ if (transaction_factory_.get())
+ transaction_factory_->TransactionStopCaching();
+}
bool MockNetworkTransaction::GetFullRequestHeaders(
net::HttpRequestHeaders* headers) const {
return false;
}
+int64 MockNetworkTransaction::GetTotalReceivedBytes() const {
+ return received_bytes_;
+}
+
void MockNetworkTransaction::DoneReading() {
if (transaction_factory_.get())
transaction_factory_->TransactionDoneReading();
@@ -350,6 +331,9 @@ net::UploadProgress MockNetworkTransaction::GetUploadProgress() const {
return net::UploadProgress();
}
+void MockNetworkTransaction::SetQuicServerInfo(
+ net::QuicServerInfo* quic_server_info) {}
+
bool MockNetworkTransaction::GetLoadTimingInfo(
net::LoadTimingInfo* load_timing_info) const {
if (socket_log_id_ != net::NetLog::Source::kInvalidId) {
@@ -381,6 +365,70 @@ void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
websocket_handshake_stream_create_helper_ = create_helper;
}
+int MockNetworkTransaction::StartInternal(
+ const net::HttpRequestInfo* request,
+ const net::CompletionCallback& callback,
+ const net::BoundNetLog& net_log) {
+ const MockTransaction* t = FindMockTransaction(request->url);
+ if (!t)
+ return net::ERR_FAILED;
+
+ test_mode_ = t->test_mode;
+
+ // Return immediately if we're returning an error.
+ if (net::OK != t->return_code) {
+ if (test_mode_ & TEST_MODE_SYNC_NET_START)
+ return t->return_code;
+ CallbackLater(callback, t->return_code);
+ return net::ERR_IO_PENDING;
+ }
+
+ std::string resp_status = t->status;
+ std::string resp_headers = t->response_headers;
+ std::string resp_data = t->data;
+ received_bytes_ = resp_status.size() + resp_headers.size() + resp_data.size();
+ if (t->handler)
+ (t->handler)(request, &resp_status, &resp_headers, &resp_data);
+
+ std::string header_data = base::StringPrintf(
+ "%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
+ std::replace(header_data.begin(), header_data.end(), '\n', '\0');
+
+ response_.request_time = base::Time::Now();
+ if (!t->request_time.is_null())
+ response_.request_time = t->request_time;
+
+ response_.was_cached = false;
+ response_.network_accessed = true;
+
+ response_.response_time = base::Time::Now();
+ if (!t->response_time.is_null())
+ response_.response_time = t->response_time;
+
+ response_.headers = new net::HttpResponseHeaders(header_data);
+ response_.vary_data.Init(*request, *response_.headers.get());
+ response_.ssl_info.cert_status = t->cert_status;
+ data_ = resp_data;
+
+ if (net_log.net_log())
+ socket_log_id_ = net_log.net_log()->NextID();
+
+ if (test_mode_ & TEST_MODE_SYNC_NET_START)
+ return net::OK;
+
+ CallbackLater(callback, net::OK);
+ return net::ERR_IO_PENDING;
+}
+
+void MockNetworkTransaction::SetBeforeNetworkStartCallback(
+ const BeforeNetworkStartCallback& callback) {
+}
+
+int MockNetworkTransaction::ResumeNetworkStart() {
+ // Should not get here.
+ return net::ERR_FAILED;
+}
+
void MockNetworkTransaction::CallbackLater(
const net::CompletionCallback& callback, int result) {
base::MessageLoop::current()->PostTask(
@@ -396,6 +444,7 @@ void MockNetworkTransaction::RunCallback(
MockNetworkLayer::MockNetworkLayer()
: transaction_count_(0),
done_reading_called_(false),
+ stop_caching_called_(false),
last_create_transaction_priority_(net::DEFAULT_PRIORITY) {}
MockNetworkLayer::~MockNetworkLayer() {}
@@ -404,10 +453,13 @@ void MockNetworkLayer::TransactionDoneReading() {
done_reading_called_ = true;
}
+void MockNetworkLayer::TransactionStopCaching() {
+ stop_caching_called_ = true;
+}
+
int MockNetworkLayer::CreateTransaction(
net::RequestPriority priority,
- scoped_ptr<net::HttpTransaction>* trans,
- net::HttpTransactionDelegate* delegate) {
+ scoped_ptr<net::HttpTransaction>* trans) {
transaction_count_++;
last_create_transaction_priority_ = priority;
scoped_ptr<MockNetworkTransaction> mock_transaction(
diff --git a/chromium/net/http/http_transaction_unittest.h b/chromium/net/http/http_transaction_test_util.h
index 3d6bb0287fb..f123794529b 100644
--- a/chromium/net/http/http_transaction_unittest.h
+++ b/chromium/net/http/http_transaction_test_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2014 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.
@@ -43,7 +43,8 @@ enum {
TEST_MODE_SYNC_CACHE_WRITE = 1 << 4,
TEST_MODE_SYNC_ALL = (TEST_MODE_SYNC_NET_START | TEST_MODE_SYNC_NET_READ |
TEST_MODE_SYNC_CACHE_START | TEST_MODE_SYNC_CACHE_READ |
- TEST_MODE_SYNC_CACHE_WRITE)
+ TEST_MODE_SYNC_CACHE_WRITE),
+ TEST_MODE_SLOW_READ = 1 << 5
};
typedef void (*MockTransactionHandler)(const net::HttpRequestInfo* request,
@@ -193,6 +194,8 @@ class MockNetworkTransaction
virtual bool GetFullRequestHeaders(
net::HttpRequestHeaders* headers) const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
+
virtual void DoneReading() OVERRIDE;
virtual const net::HttpResponseInfo* GetResponseInfo() const OVERRIDE;
@@ -201,6 +204,9 @@ class MockNetworkTransaction
virtual net::UploadProgress GetUploadProgress() const OVERRIDE;
+ virtual void SetQuicServerInfo(
+ net::QuicServerInfo* quic_server_info) OVERRIDE;
+
virtual bool GetLoadTimingInfo(
net::LoadTimingInfo* load_timing_info) const OVERRIDE;
@@ -209,16 +215,25 @@ class MockNetworkTransaction
virtual void SetWebSocketHandshakeStreamCreateHelper(
CreateHelper* create_helper) OVERRIDE;
+ virtual void SetBeforeNetworkStartCallback(
+ const BeforeNetworkStartCallback& callback) OVERRIDE;
+
+ virtual int ResumeNetworkStart() OVERRIDE;
+
CreateHelper* websocket_handshake_stream_create_helper() {
return websocket_handshake_stream_create_helper_;
}
net::RequestPriority priority() const { return priority_; }
private:
+ int StartInternal(const net::HttpRequestInfo* request,
+ const net::CompletionCallback& callback,
+ const net::BoundNetLog& net_log);
void CallbackLater(const net::CompletionCallback& callback, int result);
void RunCallback(const net::CompletionCallback& callback, int result);
base::WeakPtrFactory<MockNetworkTransaction> weak_factory_;
+ const net::HttpRequestInfo* request_;
net::HttpResponseInfo response_;
std::string data_;
int data_cursor_;
@@ -226,6 +241,7 @@ class MockNetworkTransaction
net::RequestPriority priority_;
CreateHelper* websocket_handshake_stream_create_helper_;
base::WeakPtr<MockNetworkLayer> transaction_factory_;
+ int64 received_bytes_;
// NetLog ID of the fake / non-existent underlying socket used by the
// connection. Requires Start() be passed a BoundNetLog with a real NetLog to
@@ -241,7 +257,9 @@ class MockNetworkLayer : public net::HttpTransactionFactory,
int transaction_count() const { return transaction_count_; }
bool done_reading_called() const { return done_reading_called_; }
+ bool stop_caching_called() const { return stop_caching_called_; }
void TransactionDoneReading();
+ void TransactionStopCaching();
// Returns the last priority passed to CreateTransaction, or
// DEFAULT_PRIORITY if it hasn't been called yet.
@@ -267,14 +285,14 @@ class MockNetworkLayer : public net::HttpTransactionFactory,
// net::HttpTransactionFactory:
virtual int CreateTransaction(
net::RequestPriority priority,
- scoped_ptr<net::HttpTransaction>* trans,
- net::HttpTransactionDelegate* delegate) OVERRIDE;
+ scoped_ptr<net::HttpTransaction>* trans) OVERRIDE;
virtual net::HttpCache* GetCache() OVERRIDE;
virtual net::HttpNetworkSession* GetSession() OVERRIDE;
private:
int transaction_count_;
bool done_reading_called_;
+ bool stop_caching_called_;
net::RequestPriority last_create_transaction_priority_;
base::WeakPtr<MockNetworkTransaction> last_transaction_;
};
diff --git a/chromium/net/http/http_util.cc b/chromium/net/http/http_util.cc
index 77f498133bc..f4f994af605 100644
--- a/chromium/net/http/http_util.cc
+++ b/chromium/net/http/http_util.cc
@@ -18,54 +18,40 @@
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
-using std::string;
namespace net {
-//-----------------------------------------------------------------------------
+// Helpers --------------------------------------------------------------------
-// Return the index of the closing quote of the string, if any.
-static size_t FindStringEnd(const string& line, size_t start, char delim) {
- DCHECK(start < line.length() && line[start] == delim &&
- (delim == '"' || delim == '\''));
+// Returns the index of the closing quote of the string, if any. |start| points
+// at the opening quote.
+static size_t FindStringEnd(const std::string& line, size_t start, char delim) {
+ DCHECK_LT(start, line.length());
+ DCHECK_EQ(line[start], delim);
+ DCHECK((delim == '"') || (delim == '\''));
const char set[] = { delim, '\\', '\0' };
- for (;;) {
- // start points to either the start quote or the last
- // escaped char (the char following a '\\')
-
- size_t end = line.find_first_of(set, start + 1);
- if (end == string::npos)
- return line.length();
-
- if (line[end] == '\\') {
- // Hit a backslash-escaped char. Need to skip over it.
- start = end + 1;
- if (start == line.length())
- return start;
-
- // Go back to looking for the next escape or the string end
- continue;
- }
-
- return end;
+ for (size_t end = line.find_first_of(set, start + 1);
+ end != std::string::npos; end = line.find_first_of(set, end + 2)) {
+ if (line[end] != '\\')
+ return end;
}
-
- NOTREACHED();
return line.length();
}
-//-----------------------------------------------------------------------------
+
+// HttpUtil -------------------------------------------------------------------
// static
-size_t HttpUtil::FindDelimiter(const string& line, size_t search_start,
+size_t HttpUtil::FindDelimiter(const std::string& line,
+ size_t search_start,
char delimiter) {
do {
// search_start points to the spot from which we should start looking
// for the delimiter.
const char delim_str[] = { delimiter, '"', '\'', '\0' };
size_t cur_delim_pos = line.find_first_of(delim_str, search_start);
- if (cur_delim_pos == string::npos)
+ if (cur_delim_pos == std::string::npos)
return line.length();
char ch = line[cur_delim_pos];
@@ -91,12 +77,12 @@ size_t HttpUtil::FindDelimiter(const string& line, size_t search_start,
}
// static
-void HttpUtil::ParseContentType(const string& content_type_str,
- string* mime_type,
- string* charset,
+void HttpUtil::ParseContentType(const std::string& content_type_str,
+ std::string* mime_type,
+ std::string* charset,
bool* had_charset,
- string* boundary) {
- const string::const_iterator begin = content_type_str.begin();
+ std::string* boundary) {
+ const std::string::const_iterator begin = content_type_str.begin();
// Trim leading and trailing whitespace from type. We include '(' in
// the trailing trim set to catch media-type comments, which are not at all
@@ -104,7 +90,7 @@ void HttpUtil::ParseContentType(const string& content_type_str,
size_t type_val = content_type_str.find_first_not_of(HTTP_LWS);
type_val = std::min(type_val, content_type_str.length());
size_t type_end = content_type_str.find_first_of(HTTP_LWS ";(", type_val);
- if (string::npos == type_end)
+ if (type_end == std::string::npos)
type_end = content_type_str.length();
size_t charset_val = 0;
@@ -113,22 +99,22 @@ void HttpUtil::ParseContentType(const string& content_type_str,
// Iterate over parameters
size_t param_start = content_type_str.find_first_of(';', type_end);
- if (param_start != string::npos) {
+ if (param_start != std::string::npos) {
base::StringTokenizer tokenizer(begin + param_start, content_type_str.end(),
";");
tokenizer.set_quote_chars("\"");
while (tokenizer.GetNext()) {
- string::const_iterator equals_sign =
+ std::string::const_iterator equals_sign =
std::find(tokenizer.token_begin(), tokenizer.token_end(), '=');
if (equals_sign == tokenizer.token_end())
continue;
- string::const_iterator param_name_begin = tokenizer.token_begin();
- string::const_iterator param_name_end = equals_sign;
+ std::string::const_iterator param_name_begin = tokenizer.token_begin();
+ std::string::const_iterator param_name_end = equals_sign;
TrimLWS(&param_name_begin, &param_name_end);
- string::const_iterator param_value_begin = equals_sign + 1;
- string::const_iterator param_value_end = tokenizer.token_end();
+ std::string::const_iterator param_value_begin = equals_sign + 1;
+ std::string::const_iterator param_value_end = tokenizer.token_end();
DCHECK(param_value_begin <= tokenizer.token_end());
TrimLWS(&param_value_begin, &param_value_end);
@@ -172,7 +158,7 @@ void HttpUtil::ParseContentType(const string& content_type_str,
// include a comma, so this check makes us a bit more tolerant.
if (content_type_str.length() != 0 &&
content_type_str != "*/*" &&
- content_type_str.find_first_of('/') != string::npos) {
+ content_type_str.find_first_of('/') != std::string::npos) {
// Common case here is that mime_type is empty
bool eq = !mime_type->empty() && LowerCaseEqualsASCII(begin + type_val,
begin + type_end,
@@ -291,7 +277,7 @@ bool HttpUtil::ParseRangeHeader(const std::string& ranges_specifier,
// static
bool HttpUtil::HasHeader(const std::string& headers, const char* name) {
size_t name_len = strlen(name);
- string::const_iterator it =
+ std::string::const_iterator it =
std::search(headers.begin(),
headers.end(),
name,
@@ -379,8 +365,8 @@ std::string HttpUtil::StripHeaders(const std::string& headers,
}
// static
-bool HttpUtil::IsNonCoalescingHeader(string::const_iterator name_begin,
- string::const_iterator name_end) {
+bool HttpUtil::IsNonCoalescingHeader(std::string::const_iterator name_begin,
+ std::string::const_iterator name_end) {
// NOTE: "set-cookie2" headers do not support expires attributes, so we don't
// have to list them here.
const char* kNonCoalescingHeaders[] = {
@@ -409,8 +395,8 @@ bool HttpUtil::IsLWS(char c) {
return strchr(HTTP_LWS, c) != NULL;
}
-void HttpUtil::TrimLWS(string::const_iterator* begin,
- string::const_iterator* end) {
+void HttpUtil::TrimLWS(std::string::const_iterator* begin,
+ std::string::const_iterator* end) {
// leading whitespace
while (*begin < *end && IsLWS((*begin)[0]))
++(*begin);
@@ -427,8 +413,8 @@ bool HttpUtil::IsQuote(char c) {
}
// See RFC 2616 Sec 2.2 for the definition of |token|.
-bool HttpUtil::IsToken(string::const_iterator begin,
- string::const_iterator end) {
+bool HttpUtil::IsToken(std::string::const_iterator begin,
+ std::string::const_iterator end) {
if (begin == end)
return false;
for (std::string::const_iterator iter = begin; iter != end; ++iter) {
@@ -764,9 +750,10 @@ int HttpUtil::MapStatusCodeForHistogram(int code) {
// of token, separators, and quoted-string>
//
-HttpUtil::HeadersIterator::HeadersIterator(string::const_iterator headers_begin,
- string::const_iterator headers_end,
- const std::string& line_delimiter)
+HttpUtil::HeadersIterator::HeadersIterator(
+ std::string::const_iterator headers_begin,
+ std::string::const_iterator headers_end,
+ const std::string& line_delimiter)
: lines_(headers_begin, headers_end, line_delimiter) {
}
@@ -778,7 +765,7 @@ bool HttpUtil::HeadersIterator::GetNext() {
name_begin_ = lines_.token_begin();
values_end_ = lines_.token_end();
- string::const_iterator colon = std::find(name_begin_, values_end_, ':');
+ std::string::const_iterator colon(std::find(name_begin_, values_end_, ':'));
if (colon == values_end_)
continue; // skip malformed header
@@ -818,10 +805,10 @@ bool HttpUtil::HeadersIterator::AdvanceTo(const char* name) {
}
HttpUtil::ValuesIterator::ValuesIterator(
- string::const_iterator values_begin,
- string::const_iterator values_end,
+ std::string::const_iterator values_begin,
+ std::string::const_iterator values_end,
char delimiter)
- : values_(values_begin, values_end, string(1, delimiter)) {
+ : values_(values_begin, values_end, std::string(1, delimiter)) {
values_.set_quote_chars("\'\"");
}
@@ -842,8 +829,8 @@ bool HttpUtil::ValuesIterator::GetNext() {
}
HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
- string::const_iterator begin,
- string::const_iterator end,
+ std::string::const_iterator begin,
+ std::string::const_iterator end,
char delimiter)
: props_(begin, end, delimiter),
valid_(true),
diff --git a/chromium/net/http/http_util.h b/chromium/net/http/http_util.h
index ae65146e6e4..14117c00289 100644
--- a/chromium/net/http/http_util.h
+++ b/chromium/net/http/http_util.h
@@ -56,8 +56,8 @@ class NET_EXPORT HttpUtil {
// if "Range" exists and the first one of it is well formatted then returns
// true, |ranges| will contain a list of valid ranges. If return
// value is false then values in |ranges| should not be used. The format of
- // "Range" header is defined in RFC 2616 Section 14.35.1.
- // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
+ // "Range" header is defined in RFC 7233 Section 2.1.
+ // https://tools.ietf.org/html/rfc7233#section-2.1
static bool ParseRanges(const std::string& headers,
std::vector<HttpByteRange>* ranges);
diff --git a/chromium/net/http/mock_http_cache.cc b/chromium/net/http/mock_http_cache.cc
index a3d55b17e6b..5dbd486df0f 100644
--- a/chromium/net/http/mock_http_cache.cc
+++ b/chromium/net/http/mock_http_cache.cc
@@ -512,6 +512,10 @@ MockDiskCache* MockHttpCache::disk_cache() {
return (rv == net::OK) ? static_cast<MockDiskCache*>(backend) : NULL;
}
+int MockHttpCache::CreateTransaction(scoped_ptr<net::HttpTransaction>* trans) {
+ return http_cache_.CreateTransaction(net::DEFAULT_PRIORITY, trans);
+}
+
bool MockHttpCache::ReadResponseInfo(disk_cache::Entry* disk_entry,
net::HttpResponseInfo* response_info,
bool* response_truncated) {
diff --git a/chromium/net/http/mock_http_cache.h b/chromium/net/http/mock_http_cache.h
index 90399ec4ff0..0fd192e597e 100644
--- a/chromium/net/http/mock_http_cache.h
+++ b/chromium/net/http/mock_http_cache.h
@@ -13,7 +13,7 @@
#include "base/containers/hash_tables.h"
#include "net/disk_cache/disk_cache.h"
#include "net/http/http_cache.h"
-#include "net/http/http_transaction_unittest.h"
+#include "net/http/http_transaction_test_util.h"
//-----------------------------------------------------------------------------
// Mock disk cache (a very basic memory cache implementation).
@@ -174,6 +174,9 @@ class MockHttpCache {
}
MockDiskCache* disk_cache();
+ // Wrapper around http_cache()->CreateTransaction(net::DEFAULT_PRIORITY...)
+ int CreateTransaction(scoped_ptr<net::HttpTransaction>* trans);
+
// Helper function for reading response info from the disk cache.
static bool ReadResponseInfo(disk_cache::Entry* disk_entry,
net::HttpResponseInfo* response_info,
diff --git a/chromium/net/http/partial_data.cc b/chromium/net/http/partial_data.cc
index ee3678b5ea0..a05c2189754 100644
--- a/chromium/net/http/partial_data.cc
+++ b/chromium/net/http/partial_data.cc
@@ -382,40 +382,26 @@ void PartialData::FixResponseHeaders(HttpResponseHeaders* headers,
if (truncated_)
return;
+ if (byte_range_.IsValid() && success) {
+ headers->UpdateWithNewRange(byte_range_, resource_size_, !sparse_entry_);
+ return;
+ }
+
headers->RemoveHeader(kLengthHeader);
headers->RemoveHeader(kRangeHeader);
- int64 range_len, start, end;
if (byte_range_.IsValid()) {
- if (success) {
- if (!sparse_entry_)
- headers->ReplaceStatusLine("HTTP/1.1 206 Partial Content");
-
- DCHECK(byte_range_.HasFirstBytePosition());
- DCHECK(byte_range_.HasLastBytePosition());
- start = byte_range_.first_byte_position();
- end = byte_range_.last_byte_position();
- range_len = end - start + 1;
- } else {
- headers->ReplaceStatusLine(
- "HTTP/1.1 416 Requested Range Not Satisfiable");
- start = 0;
- end = 0;
- range_len = 0;
- }
-
- headers->AddHeader(
- base::StringPrintf("%s: bytes %" PRId64 "-%" PRId64 "/%" PRId64,
- kRangeHeader, start, end, resource_size_));
+ headers->ReplaceStatusLine("HTTP/1.1 416 Requested Range Not Satisfiable");
+ headers->AddHeader(base::StringPrintf("%s: bytes 0-0/%" PRId64,
+ kRangeHeader, resource_size_));
+ headers->AddHeader(base::StringPrintf("%s: 0", kLengthHeader));
} else {
// TODO(rvargas): Is it safe to change the protocol version?
headers->ReplaceStatusLine("HTTP/1.1 200 OK");
DCHECK_NE(resource_size_, 0);
- range_len = resource_size_;
+ headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader,
+ resource_size_));
}
-
- headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader,
- range_len));
}
void PartialData::FixContentLength(HttpResponseHeaders* headers) {
diff --git a/chromium/net/http/proxy_connect_redirect_http_stream.cc b/chromium/net/http/proxy_connect_redirect_http_stream.cc
index 0857a7451ca..b859d37de63 100644
--- a/chromium/net/http/proxy_connect_redirect_http_stream.cc
+++ b/chromium/net/http/proxy_connect_redirect_http_stream.cc
@@ -43,12 +43,6 @@ int ProxyConnectRedirectHttpStream::ReadResponseHeaders(
return OK;
}
-const HttpResponseInfo*
-ProxyConnectRedirectHttpStream::GetResponseInfo() const {
- NOTREACHED();
- return NULL;
-}
-
int ProxyConnectRedirectHttpStream::ReadResponseBody(
IOBuffer* buf,
int buf_len,
diff --git a/chromium/net/http/proxy_connect_redirect_http_stream.h b/chromium/net/http/proxy_connect_redirect_http_stream.h
index 0547654ab92..f848c64fcd1 100644
--- a/chromium/net/http/proxy_connect_redirect_http_stream.h
+++ b/chromium/net/http/proxy_connect_redirect_http_stream.h
@@ -33,7 +33,6 @@ class ProxyConnectRedirectHttpStream : public HttpStream {
HttpResponseInfo* response,
const CompletionCallback& callback) OVERRIDE;
virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE;
- virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE;
virtual int ReadResponseBody(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) OVERRIDE;
diff --git a/chromium/net/http/transport_security_persister.cc b/chromium/net/http/transport_security_persister.cc
index 771d07dc1bc..7310b590f7e 100644
--- a/chromium/net/http/transport_security_persister.cc
+++ b/chromium/net/http/transport_security_persister.cc
@@ -26,14 +26,15 @@ using net::TransportSecurityState;
namespace {
-ListValue* SPKIHashesToListValue(const HashValueVector& hashes) {
- ListValue* pins = new ListValue;
+base::ListValue* SPKIHashesToListValue(const HashValueVector& hashes) {
+ base::ListValue* pins = new base::ListValue;
for (size_t i = 0; i != hashes.size(); i++)
- pins->Append(new StringValue(hashes[i].ToString()));
+ pins->Append(new base::StringValue(hashes[i].ToString()));
return pins;
}
-void SPKIHashesFromListValue(const ListValue& pins, HashValueVector* hashes) {
+void SPKIHashesFromListValue(const base::ListValue& pins,
+ HashValueVector* hashes) {
size_t num_pins = pins.GetSize();
for (size_t i = 0; i < num_pins; ++i) {
std::string type_and_base64;
@@ -71,14 +72,14 @@ const char kPkpIncludeSubdomains[] = "pkp_include_subdomains";
const char kMode[] = "mode";
const char kExpiry[] = "expiry";
const char kDynamicSPKIHashesExpiry[] = "dynamic_spki_hashes_expiry";
-const char kStaticSPKIHashes[] = "static_spki_hashes";
-const char kPreloadedSPKIHashes[] = "preloaded_spki_hashes";
const char kDynamicSPKIHashes[] = "dynamic_spki_hashes";
const char kForceHTTPS[] = "force-https";
const char kStrict[] = "strict";
const char kDefault[] = "default";
const char kPinningOnly[] = "pinning-only";
const char kCreated[] = "created";
+const char kStsObserved[] = "sts_observed";
+const char kPkpObserved[] = "pkp_observed";
std::string LoadState(const base::FilePath& path) {
std::string result;
@@ -135,7 +136,7 @@ void TransportSecurityPersister::StateIsDirty(
bool TransportSecurityPersister::SerializeData(std::string* output) {
DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
- DictionaryValue toplevel;
+ base::DictionaryValue toplevel;
base::Time now = base::Time::Now();
TransportSecurityState::Iterator state(*transport_security_state_);
for (; state.HasNext(); state.Advance()) {
@@ -143,17 +144,20 @@ bool TransportSecurityPersister::SerializeData(std::string* output) {
const TransportSecurityState::DomainState& domain_state =
state.domain_state();
- DictionaryValue* serialized = new DictionaryValue;
+ base::DictionaryValue* serialized = new base::DictionaryValue;
serialized->SetBoolean(kStsIncludeSubdomains,
- domain_state.sts_include_subdomains);
+ domain_state.sts.include_subdomains);
serialized->SetBoolean(kPkpIncludeSubdomains,
- domain_state.pkp_include_subdomains);
- serialized->SetDouble(kCreated, domain_state.created.ToDoubleT());
- serialized->SetDouble(kExpiry, domain_state.upgrade_expiry.ToDoubleT());
+ domain_state.pkp.include_subdomains);
+ serialized->SetDouble(kStsObserved,
+ domain_state.sts.last_observed.ToDoubleT());
+ serialized->SetDouble(kPkpObserved,
+ domain_state.pkp.last_observed.ToDoubleT());
+ serialized->SetDouble(kExpiry, domain_state.sts.expiry.ToDoubleT());
serialized->SetDouble(kDynamicSPKIHashesExpiry,
- domain_state.dynamic_spki_hashes_expiry.ToDoubleT());
+ domain_state.pkp.expiry.ToDoubleT());
- switch (domain_state.upgrade_mode) {
+ switch (domain_state.sts.upgrade_mode) {
case TransportSecurityState::DomainState::MODE_FORCE_HTTPS:
serialized->SetString(kMode, kForceHTTPS);
break;
@@ -166,12 +170,9 @@ bool TransportSecurityPersister::SerializeData(std::string* output) {
continue;
}
- serialized->Set(kStaticSPKIHashes,
- SPKIHashesToListValue(domain_state.static_spki_hashes));
-
- if (now < domain_state.dynamic_spki_hashes_expiry) {
+ if (now < domain_state.pkp.expiry) {
serialized->Set(kDynamicSPKIHashes,
- SPKIHashesToListValue(domain_state.dynamic_spki_hashes));
+ SPKIHashesToListValue(domain_state.pkp.spki_hashes));
}
toplevel.Set(HashedDomainToExternalString(hostname), serialized);
@@ -195,23 +196,23 @@ bool TransportSecurityPersister::LoadEntries(const std::string& serialized,
bool TransportSecurityPersister::Deserialize(const std::string& serialized,
bool* dirty,
TransportSecurityState* state) {
- scoped_ptr<Value> value(base::JSONReader::Read(serialized));
- DictionaryValue* dict_value = NULL;
+ scoped_ptr<base::Value> value(base::JSONReader::Read(serialized));
+ base::DictionaryValue* dict_value = NULL;
if (!value.get() || !value->GetAsDictionary(&dict_value))
return false;
const base::Time current_time(base::Time::Now());
bool dirtied = false;
- for (DictionaryValue::Iterator i(*dict_value); !i.IsAtEnd(); i.Advance()) {
- const DictionaryValue* parsed = NULL;
+ for (base::DictionaryValue::Iterator i(*dict_value);
+ !i.IsAtEnd(); i.Advance()) {
+ const base::DictionaryValue* parsed = NULL;
if (!i.value().GetAsDictionary(&parsed)) {
LOG(WARNING) << "Could not parse entry " << i.key() << "; skipping entry";
continue;
}
std::string mode_string;
- double created;
double expiry;
double dynamic_spki_hashes_expiry = 0.0;
TransportSecurityState::DomainState domain_state;
@@ -222,14 +223,14 @@ bool TransportSecurityPersister::Deserialize(const std::string& serialized,
bool include_subdomains = false;
bool parsed_include_subdomains = parsed->GetBoolean(kIncludeSubdomains,
&include_subdomains);
- domain_state.sts_include_subdomains = include_subdomains;
- domain_state.pkp_include_subdomains = include_subdomains;
+ domain_state.sts.include_subdomains = include_subdomains;
+ domain_state.pkp.include_subdomains = include_subdomains;
if (parsed->GetBoolean(kStsIncludeSubdomains, &include_subdomains)) {
- domain_state.sts_include_subdomains = include_subdomains;
+ domain_state.sts.include_subdomains = include_subdomains;
parsed_include_subdomains = true;
}
if (parsed->GetBoolean(kPkpIncludeSubdomains, &include_subdomains)) {
- domain_state.pkp_include_subdomains = include_subdomains;
+ domain_state.pkp.include_subdomains = include_subdomains;
parsed_include_subdomains = true;
}
@@ -245,21 +246,16 @@ bool TransportSecurityPersister::Deserialize(const std::string& serialized,
parsed->GetDouble(kDynamicSPKIHashesExpiry,
&dynamic_spki_hashes_expiry);
- const ListValue* pins_list = NULL;
- // preloaded_spki_hashes is a legacy synonym for static_spki_hashes.
- if (parsed->GetList(kStaticSPKIHashes, &pins_list))
- SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes);
- else if (parsed->GetList(kPreloadedSPKIHashes, &pins_list))
- SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes);
-
- if (parsed->GetList(kDynamicSPKIHashes, &pins_list))
- SPKIHashesFromListValue(*pins_list, &domain_state.dynamic_spki_hashes);
+ const base::ListValue* pins_list = NULL;
+ if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) {
+ SPKIHashesFromListValue(*pins_list, &domain_state.pkp.spki_hashes);
+ }
if (mode_string == kForceHTTPS || mode_string == kStrict) {
- domain_state.upgrade_mode =
+ domain_state.sts.upgrade_mode =
TransportSecurityState::DomainState::MODE_FORCE_HTTPS;
} else if (mode_string == kDefault || mode_string == kPinningOnly) {
- domain_state.upgrade_mode =
+ domain_state.sts.upgrade_mode =
TransportSecurityState::DomainState::MODE_DEFAULT;
} else {
LOG(WARNING) << "Unknown TransportSecurityState mode string "
@@ -268,20 +264,34 @@ bool TransportSecurityPersister::Deserialize(const std::string& serialized,
continue;
}
- domain_state.upgrade_expiry = base::Time::FromDoubleT(expiry);
- domain_state.dynamic_spki_hashes_expiry =
+ domain_state.sts.expiry = base::Time::FromDoubleT(expiry);
+ domain_state.pkp.expiry =
base::Time::FromDoubleT(dynamic_spki_hashes_expiry);
- if (parsed->GetDouble(kCreated, &created)) {
- domain_state.created = base::Time::FromDoubleT(created);
+
+ double sts_observed;
+ double pkp_observed;
+ if (parsed->GetDouble(kStsObserved, &sts_observed)) {
+ domain_state.sts.last_observed = base::Time::FromDoubleT(sts_observed);
+ } else if (parsed->GetDouble(kCreated, &sts_observed)) {
+ // kCreated is a legacy synonym for both kStsObserved and kPkpObserved.
+ domain_state.sts.last_observed = base::Time::FromDoubleT(sts_observed);
} else {
- // We're migrating an old entry with no creation date. Make sure we
+ // We're migrating an old entry with no observation date. Make sure we
// write the new date back in a reasonable time frame.
dirtied = true;
- domain_state.created = base::Time::Now();
+ domain_state.sts.last_observed = base::Time::Now();
+ }
+ if (parsed->GetDouble(kPkpObserved, &pkp_observed)) {
+ domain_state.pkp.last_observed = base::Time::FromDoubleT(pkp_observed);
+ } else if (parsed->GetDouble(kCreated, &pkp_observed)) {
+ domain_state.pkp.last_observed = base::Time::FromDoubleT(pkp_observed);
+ } else {
+ dirtied = true;
+ domain_state.pkp.last_observed = base::Time::Now();
}
- if (domain_state.upgrade_expiry <= current_time &&
- domain_state.dynamic_spki_hashes_expiry <= current_time) {
+ if (domain_state.sts.expiry <= current_time &&
+ domain_state.pkp.expiry <= current_time) {
// Make sure we dirty the state if we drop an entry.
dirtied = true;
continue;
diff --git a/chromium/net/http/transport_security_persister_unittest.cc b/chromium/net/http/transport_security_persister_unittest.cc
index 8c41f9e81da..a30edae94f7 100644
--- a/chromium/net/http/transport_security_persister_unittest.cc
+++ b/chromium/net/http/transport_security_persister_unittest.cc
@@ -57,7 +57,8 @@ TEST_F(TransportSecurityPersisterTest, SerializeData2) {
const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
static const char kYahooDomain[] = "yahoo.com";
- EXPECT_FALSE(state_.GetDomainState(kYahooDomain, true, &domain_state));
+ EXPECT_FALSE(state_.GetStaticDomainState(kYahooDomain, true, &domain_state));
+ EXPECT_FALSE(state_.GetDynamicDomainState(kYahooDomain, &domain_state));
bool include_subdomains = true;
state_.AddHSTS(kYahooDomain, expiry, include_subdomains);
@@ -67,20 +68,20 @@ TEST_F(TransportSecurityPersisterTest, SerializeData2) {
EXPECT_TRUE(persister_->SerializeData(&output));
EXPECT_TRUE(persister_->LoadEntries(output, &dirty));
- EXPECT_TRUE(state_.GetDomainState(kYahooDomain, true, &domain_state));
- EXPECT_EQ(domain_state.upgrade_mode,
+ EXPECT_TRUE(state_.GetDynamicDomainState(kYahooDomain, &domain_state));
+ EXPECT_EQ(domain_state.sts.upgrade_mode,
TransportSecurityState::DomainState::MODE_FORCE_HTTPS);
- EXPECT_TRUE(state_.GetDomainState("foo.yahoo.com", true, &domain_state));
- EXPECT_EQ(domain_state.upgrade_mode,
+ EXPECT_TRUE(state_.GetDynamicDomainState("foo.yahoo.com", &domain_state));
+ EXPECT_EQ(domain_state.sts.upgrade_mode,
TransportSecurityState::DomainState::MODE_FORCE_HTTPS);
- EXPECT_TRUE(state_.GetDomainState("foo.bar.yahoo.com", true, &domain_state));
- EXPECT_EQ(domain_state.upgrade_mode,
+ EXPECT_TRUE(state_.GetDynamicDomainState("foo.bar.yahoo.com", &domain_state));
+ EXPECT_EQ(domain_state.sts.upgrade_mode,
TransportSecurityState::DomainState::MODE_FORCE_HTTPS);
- EXPECT_TRUE(state_.GetDomainState("foo.bar.baz.yahoo.com", true,
- &domain_state));
- EXPECT_EQ(domain_state.upgrade_mode,
+ EXPECT_TRUE(
+ state_.GetDynamicDomainState("foo.bar.baz.yahoo.com", &domain_state));
+ EXPECT_EQ(domain_state.sts.upgrade_mode,
TransportSecurityState::DomainState::MODE_FORCE_HTTPS);
- EXPECT_FALSE(state_.GetDomainState("com", true, &domain_state));
+ EXPECT_FALSE(state_.GetStaticDomainState("com", true, &domain_state));
}
TEST_F(TransportSecurityPersisterTest, SerializeData3) {
@@ -127,8 +128,7 @@ TEST_F(TransportSecurityPersisterTest, SerializeData3) {
// than block.) Use a different basename just for cleanliness.
base::FilePath path =
temp_dir_.path().AppendASCII("TransportSecurityPersisterTest");
- EXPECT_TRUE(file_util::WriteFile(path, serialized.c_str(),
- serialized.size()));
+ EXPECT_TRUE(base::WriteFile(path, serialized.c_str(), serialized.size()));
// Read the data back.
std::string persisted;
@@ -167,35 +167,40 @@ TEST_F(TransportSecurityPersisterTest, SerializeDataOld) {
TEST_F(TransportSecurityPersisterTest, PublicKeyHashes) {
TransportSecurityState::DomainState domain_state;
static const char kTestDomain[] = "example.com";
- EXPECT_FALSE(state_.GetDomainState(kTestDomain, false, &domain_state));
+ EXPECT_FALSE(state_.GetDynamicDomainState(kTestDomain, &domain_state));
net::HashValueVector hashes;
- EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes));
+ std::string failure_log;
+ EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes, &failure_log));
net::HashValue sha1(net::HASH_VALUE_SHA1);
memset(sha1.data(), '1', sha1.size());
- domain_state.dynamic_spki_hashes.push_back(sha1);
+ domain_state.pkp.spki_hashes.push_back(sha1);
- EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes));
+ EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes, &failure_log));
hashes.push_back(sha1);
- EXPECT_TRUE(domain_state.CheckPublicKeyPins(hashes));
+ EXPECT_TRUE(domain_state.CheckPublicKeyPins(hashes, &failure_log));
hashes[0].data()[0] = '2';
- EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes));
+ EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes, &failure_log));
const base::Time current_time(base::Time::Now());
const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
bool include_subdomains = false;
state_.AddHSTS(kTestDomain, expiry, include_subdomains);
- state_.AddHPKP(kTestDomain, expiry, include_subdomains,
- domain_state.dynamic_spki_hashes);
- std::string ser;
- EXPECT_TRUE(persister_->SerializeData(&ser));
+ state_.AddHPKP(
+ kTestDomain, expiry, include_subdomains, domain_state.pkp.spki_hashes);
+ std::string serialized;
+ EXPECT_TRUE(persister_->SerializeData(&serialized));
bool dirty;
- EXPECT_TRUE(persister_->LoadEntries(ser, &dirty));
- EXPECT_TRUE(state_.GetDomainState(kTestDomain, false, &domain_state));
- EXPECT_EQ(1u, domain_state.dynamic_spki_hashes.size());
- EXPECT_EQ(sha1.tag, domain_state.dynamic_spki_hashes[0].tag);
- EXPECT_EQ(0, memcmp(domain_state.dynamic_spki_hashes[0].data(), sha1.data(),
- sha1.size()));
+ EXPECT_TRUE(persister_->LoadEntries(serialized, &dirty));
+
+ TransportSecurityState::DomainState new_domain_state;
+ EXPECT_TRUE(state_.GetDynamicDomainState(kTestDomain, &new_domain_state));
+ EXPECT_EQ(1u, new_domain_state.pkp.spki_hashes.size());
+ EXPECT_EQ(sha1.tag, new_domain_state.pkp.spki_hashes[0].tag);
+ EXPECT_EQ(0,
+ memcmp(new_domain_state.pkp.spki_hashes[0].data(),
+ sha1.data(),
+ sha1.size()));
}
diff --git a/chromium/net/http/transport_security_state.cc b/chromium/net/http/transport_security_state.cc
index f9ba807ff79..f50b26483d1 100644
--- a/chromium/net/http/transport_security_state.cc
+++ b/chromium/net/http/transport_security_state.cc
@@ -95,6 +95,61 @@ TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state)
TransportSecurityState::Iterator::~Iterator() {}
+bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host,
+ bool sni_enabled) {
+ DomainState state;
+ if (GetStaticDomainState(host, sni_enabled, &state))
+ return true;
+ return GetDynamicDomainState(host, &state);
+}
+
+bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host,
+ bool sni_enabled) {
+ DomainState dynamic_state;
+ if (GetDynamicDomainState(host, &dynamic_state))
+ return dynamic_state.ShouldUpgradeToSSL();
+
+ DomainState static_state;
+ if (GetStaticDomainState(host, sni_enabled, &static_state) &&
+ static_state.ShouldUpgradeToSSL()) {
+ return true;
+ }
+
+ return false;
+}
+
+bool TransportSecurityState::CheckPublicKeyPins(const std::string& host,
+ bool sni_enabled,
+ const HashValueVector& hashes,
+ std::string* failure_log) {
+ DomainState dynamic_state;
+ if (GetDynamicDomainState(host, &dynamic_state))
+ return dynamic_state.CheckPublicKeyPins(hashes, failure_log);
+
+ DomainState static_state;
+ if (GetStaticDomainState(host, sni_enabled, &static_state) &&
+ static_state.CheckPublicKeyPins(hashes, failure_log)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool TransportSecurityState::HasPublicKeyPins(const std::string& host,
+ bool sni_enabled) {
+ DomainState dynamic_state;
+ if (GetDynamicDomainState(host, &dynamic_state))
+ return dynamic_state.HasPublicKeyPins();
+
+ DomainState static_state;
+ if (GetStaticDomainState(host, sni_enabled, &static_state)) {
+ if (static_state.HasPublicKeyPins())
+ return true;
+ }
+
+ return false;
+}
+
void TransportSecurityState::SetDelegate(
TransportSecurityState::Delegate* delegate) {
DCHECK(CalledOnValidThread());
@@ -135,61 +190,6 @@ bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
return false;
}
-bool TransportSecurityState::GetDomainState(const std::string& host,
- bool sni_enabled,
- DomainState* result) {
- DCHECK(CalledOnValidThread());
-
- DomainState state;
- const std::string canonicalized_host = CanonicalizeHost(host);
- if (canonicalized_host.empty())
- return false;
-
- bool has_preload = GetStaticDomainState(canonicalized_host, sni_enabled,
- &state);
- std::string canonicalized_preload = CanonicalizeHost(state.domain);
- GetDynamicDomainState(host, &state);
-
- base::Time current_time(base::Time::Now());
-
- for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
- std::string host_sub_chunk(&canonicalized_host[i],
- canonicalized_host.size() - i);
- // Exact match of a preload always wins.
- if (has_preload && host_sub_chunk == canonicalized_preload) {
- *result = state;
- return true;
- }
-
- DomainStateMap::iterator j =
- enabled_hosts_.find(HashHost(host_sub_chunk));
- if (j == enabled_hosts_.end())
- continue;
-
- if (current_time > j->second.upgrade_expiry &&
- current_time > j->second.dynamic_spki_hashes_expiry) {
- enabled_hosts_.erase(j);
- DirtyNotify();
- continue;
- }
-
- state = j->second;
- state.domain = DNSDomainToString(host_sub_chunk);
-
- // Succeed if we matched the domain exactly or if subdomain matches are
- // allowed.
- if (i == 0 || j->second.sts_include_subdomains ||
- j->second.pkp_include_subdomains) {
- *result = state;
- return true;
- }
-
- return false;
- }
-
- return false;
-}
-
void TransportSecurityState::ClearDynamicData() {
DCHECK(CalledOnValidThread());
enabled_hosts_.clear();
@@ -199,15 +199,24 @@ void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
DCHECK(CalledOnValidThread());
bool dirtied = false;
-
DomainStateMap::iterator i = enabled_hosts_.begin();
while (i != enabled_hosts_.end()) {
- if (i->second.created >= time) {
+ if (i->second.sts.last_observed >= time &&
+ i->second.pkp.last_observed >= time) {
dirtied = true;
enabled_hosts_.erase(i++);
- } else {
- i++;
+ continue;
+ }
+
+ if (i->second.sts.last_observed >= time) {
+ dirtied = true;
+ i->second.sts.upgrade_mode = DomainState::MODE_DEFAULT;
+ } else if (i->second.pkp.last_observed >= time) {
+ dirtied = true;
+ i->second.pkp.spki_hashes.clear();
+ i->second.pkp.expiry = base::Time();
}
+ ++i;
}
if (dirtied)
@@ -515,6 +524,7 @@ enum SecondLevelDomainName {
DOMAIN_LAVABIT_COM,
DOMAIN_GOOGLETAGMANAGER_COM,
+ DOMAIN_GOOGLETAGSERVICES_COM,
// Boundary value for UMA_HISTOGRAM_ENUMERATION:
DOMAIN_NUM_EVENTS
@@ -547,22 +557,27 @@ static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries,
if (!entries[j].include_subdomains && i != 0) {
*ret = false;
} else {
- out->sts_include_subdomains = entries[j].include_subdomains;
- out->pkp_include_subdomains = entries[j].include_subdomains;
+ out->sts.include_subdomains = entries[j].include_subdomains;
+ out->sts.last_observed = base::GetBuildTime();
+ out->pkp.include_subdomains = entries[j].include_subdomains;
+ out->pkp.last_observed = base::GetBuildTime();
*ret = true;
+ out->sts.upgrade_mode =
+ TransportSecurityState::DomainState::MODE_FORCE_HTTPS;
if (!entries[j].https_required)
- out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT;
+ out->sts.upgrade_mode =
+ TransportSecurityState::DomainState::MODE_DEFAULT;
if (entries[j].pins.required_hashes) {
const char* const* sha1_hash = entries[j].pins.required_hashes;
while (*sha1_hash) {
- AddHash(*sha1_hash, &out->static_spki_hashes);
+ AddHash(*sha1_hash, &out->pkp.spki_hashes);
sha1_hash++;
}
}
if (entries[j].pins.excluded_hashes) {
const char* const* sha1_hash = entries[j].pins.excluded_hashes;
while (*sha1_hash) {
- AddHash(*sha1_hash, &out->bad_static_spki_hashes);
+ AddHash(*sha1_hash, &out->pkp.bad_spki_hashes);
sha1_hash++;
}
}
@@ -610,14 +625,14 @@ bool TransportSecurityState::AddHSTSHeader(const std::string& host,
base::TimeDelta max_age;
TransportSecurityState::DomainState domain_state;
GetDynamicDomainState(host, &domain_state);
- if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) {
- // Handle max-age == 0
+ if (ParseHSTSHeader(value, &max_age, &domain_state.sts.include_subdomains)) {
+ // Handle max-age == 0.
if (max_age.InSeconds() == 0)
- domain_state.upgrade_mode = DomainState::MODE_DEFAULT;
+ domain_state.sts.upgrade_mode = DomainState::MODE_DEFAULT;
else
- domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
- domain_state.created = now;
- domain_state.upgrade_expiry = now + max_age;
+ domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
+ domain_state.sts.last_observed = now;
+ domain_state.sts.expiry = now + max_age;
EnableHost(host, domain_state);
return true;
}
@@ -633,12 +648,16 @@ bool TransportSecurityState::AddHPKPHeader(const std::string& host,
base::TimeDelta max_age;
TransportSecurityState::DomainState domain_state;
GetDynamicDomainState(host, &domain_state);
- if (ParseHPKPHeader(value, ssl_info.public_key_hashes,
- &max_age, &domain_state.pkp_include_subdomains,
- &domain_state.dynamic_spki_hashes)) {
- // TODO(palmer): http://crbug.com/243865 handle max-age == 0.
- domain_state.created = now;
- domain_state.dynamic_spki_hashes_expiry = now + max_age;
+ if (ParseHPKPHeader(value,
+ ssl_info.public_key_hashes,
+ &max_age,
+ &domain_state.pkp.include_subdomains,
+ &domain_state.pkp.spki_hashes)) {
+ // Handle max-age == 0.
+ if (max_age.InSeconds() == 0)
+ domain_state.pkp.spki_hashes.clear();
+ domain_state.pkp.last_observed = now;
+ domain_state.pkp.expiry = now + max_age;
EnableHost(host, domain_state);
return true;
}
@@ -659,10 +678,10 @@ bool TransportSecurityState::AddHSTS(const std::string& host,
if (i != enabled_hosts_.end())
domain_state = i->second;
- domain_state.created = base::Time::Now();
- domain_state.sts_include_subdomains = include_subdomains;
- domain_state.upgrade_expiry = expiry;
- domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
+ domain_state.sts.last_observed = base::Time::Now();
+ domain_state.sts.include_subdomains = include_subdomains;
+ domain_state.sts.expiry = expiry;
+ domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
EnableHost(host, domain_state);
return true;
}
@@ -682,10 +701,10 @@ bool TransportSecurityState::AddHPKP(const std::string& host,
if (i != enabled_hosts_.end())
domain_state = i->second;
- domain_state.created = base::Time::Now();
- domain_state.pkp_include_subdomains = include_subdomains;
- domain_state.dynamic_spki_hashes_expiry = expiry;
- domain_state.dynamic_spki_hashes = hashes;
+ domain_state.pkp.last_observed = base::Time::Now();
+ domain_state.pkp.include_subdomains = include_subdomains;
+ domain_state.pkp.expiry = expiry;
+ domain_state.pkp.spki_hashes = hashes;
EnableHost(host, domain_state);
return true;
}
@@ -742,15 +761,16 @@ bool TransportSecurityState::IsBuildTimely() {
return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
}
-bool TransportSecurityState::GetStaticDomainState(
- const std::string& canonicalized_host,
- bool sni_enabled,
- DomainState* out) {
+bool TransportSecurityState::GetStaticDomainState(const std::string& host,
+ bool sni_enabled,
+ DomainState* out) const {
DCHECK(CalledOnValidThread());
- out->upgrade_mode = DomainState::MODE_FORCE_HTTPS;
- out->sts_include_subdomains = false;
- out->pkp_include_subdomains = false;
+ const std::string canonicalized_host = CanonicalizeHost(host);
+
+ out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
+ out->sts.include_subdomains = false;
+ out->pkp.include_subdomains = false;
const bool is_build_timely = IsBuildTimely();
@@ -794,8 +814,8 @@ bool TransportSecurityState::GetDynamicDomainState(const std::string& host,
if (j == enabled_hosts_.end())
continue;
- if (current_time > j->second.upgrade_expiry &&
- current_time > j->second.dynamic_spki_hashes_expiry) {
+ if (current_time > j->second.sts.expiry &&
+ current_time > j->second.pkp.expiry) {
enabled_hosts_.erase(j);
DirtyNotify();
continue;
@@ -806,8 +826,8 @@ bool TransportSecurityState::GetDynamicDomainState(const std::string& host,
// Succeed if we matched the domain exactly or if subdomain matches are
// allowed.
- if (i == 0 || j->second.sts_include_subdomains ||
- j->second.pkp_include_subdomains) {
+ if (i == 0 || j->second.sts.include_subdomains ||
+ j->second.pkp.include_subdomains) {
*result = state;
return true;
}
@@ -818,60 +838,57 @@ bool TransportSecurityState::GetDynamicDomainState(const std::string& host,
return false;
}
-
void TransportSecurityState::AddOrUpdateEnabledHosts(
const std::string& hashed_host, const DomainState& state) {
DCHECK(CalledOnValidThread());
enabled_hosts_[hashed_host] = state;
}
-TransportSecurityState::DomainState::DomainState()
- : upgrade_mode(MODE_DEFAULT),
- created(base::Time::Now()),
- sts_include_subdomains(false),
- pkp_include_subdomains(false) {
+TransportSecurityState::DomainState::DomainState() {
+ sts.upgrade_mode = MODE_DEFAULT;
+ sts.include_subdomains = false;
+ pkp.include_subdomains = false;
}
TransportSecurityState::DomainState::~DomainState() {
}
bool TransportSecurityState::DomainState::CheckPublicKeyPins(
- const HashValueVector& hashes) const {
+ const HashValueVector& hashes, std::string* failure_log) const {
// Validate that hashes is not empty. By the time this code is called (in
// production), that should never happen, but it's good to be defensive.
// And, hashes *can* be empty in some test scenarios.
if (hashes.empty()) {
- LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned "
- "domain " << domain;
+ failure_log->append(
+ "Rejecting empty public key chain for public-key-pinned domains: " +
+ domain);
return false;
}
- if (HashesIntersect(bad_static_spki_hashes, hashes)) {
- LOG(ERROR) << "Rejecting public key chain for domain " << domain
- << ". Validated chain: " << HashesToBase64String(hashes)
- << ", matches one or more bad hashes: "
- << HashesToBase64String(bad_static_spki_hashes);
+ if (HashesIntersect(pkp.bad_spki_hashes, hashes)) {
+ failure_log->append("Rejecting public key chain for domain " + domain +
+ ". Validated chain: " + HashesToBase64String(hashes) +
+ ", matches one or more bad hashes: " +
+ HashesToBase64String(pkp.bad_spki_hashes));
return false;
}
// If there are no pins, then any valid chain is acceptable.
- if (dynamic_spki_hashes.empty() && static_spki_hashes.empty())
+ if (pkp.spki_hashes.empty())
return true;
- if (HashesIntersect(dynamic_spki_hashes, hashes) ||
- HashesIntersect(static_spki_hashes, hashes)) {
+ if (HashesIntersect(pkp.spki_hashes, hashes)) {
return true;
}
- LOG(ERROR) << "Rejecting public key chain for domain " << domain
- << ". Validated chain: " << HashesToBase64String(hashes)
- << ", expected: " << HashesToBase64String(dynamic_spki_hashes)
- << " or: " << HashesToBase64String(static_spki_hashes);
+ failure_log->append("Rejecting public key chain for domain " + domain +
+ ". Validated chain: " + HashesToBase64String(hashes) +
+ ", expected: " + HashesToBase64String(pkp.spki_hashes));
return false;
}
bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const {
- return upgrade_mode == MODE_FORCE_HTTPS;
+ return sts.upgrade_mode == MODE_FORCE_HTTPS;
}
bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const {
@@ -879,9 +896,13 @@ bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const {
}
bool TransportSecurityState::DomainState::HasPublicKeyPins() const {
- return static_spki_hashes.size() > 0 ||
- bad_static_spki_hashes.size() > 0 ||
- dynamic_spki_hashes.size() > 0;
+ return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0;
+}
+
+TransportSecurityState::DomainState::PKPState::PKPState() {
+}
+
+TransportSecurityState::DomainState::PKPState::~PKPState() {
}
} // namespace
diff --git a/chromium/net/http/transport_security_state.h b/chromium/net/http/transport_security_state.h
index 97b4d7c1fc8..36459379145 100644
--- a/chromium/net/http/transport_security_state.h
+++ b/chromium/net/http/transport_security_state.h
@@ -61,6 +61,44 @@ class NET_EXPORT TransportSecurityState
DomainState();
~DomainState();
+ struct STSState {
+ // The absolute time (UTC) when the |upgrade_mode| (and other state) was
+ // observed.
+ base::Time last_observed;
+
+ // The absolute time (UTC) when the |upgrade_mode|, if set to
+ // MODE_FORCE_HTTPS, downgrades to MODE_DEFAULT.
+ base::Time expiry;
+
+ UpgradeMode upgrade_mode;
+
+ // Are subdomains subject to this policy state?
+ bool include_subdomains;
+ };
+
+ struct PKPState {
+ PKPState();
+ ~PKPState();
+
+ // The absolute time (UTC) when the |spki_hashes| (and other state) were
+ // observed.
+ base::Time last_observed;
+
+ // The absolute time (UTC) when the |spki_hashes| expire.
+ base::Time expiry;
+
+ // Optional; hashes of pinned SubjectPublicKeyInfos.
+ HashValueVector spki_hashes;
+
+ // Optional; hashes of static known-bad SubjectPublicKeyInfos which MUST
+ // NOT intersect with the set of SPKIs in the TLS server's certificate
+ // chain.
+ HashValueVector bad_spki_hashes;
+
+ // Are subdomains subject to this policy state?
+ bool include_subdomains;
+ };
+
// Takes a set of SubjectPublicKeyInfo |hashes| and returns true if:
// 1) |bad_static_spki_hashes| does not intersect |hashes|; AND
// 2) Both |static_spki_hashes| and |dynamic_spki_hashes| are empty
@@ -77,67 +115,29 @@ class NET_EXPORT TransportSecurityState
//
// |bad_static_spki_hashes| contains public keys that we don't want to
// trust.
- bool CheckPublicKeyPins(const HashValueVector& hashes) const;
+ bool CheckPublicKeyPins(const HashValueVector& hashes,
+ std::string* failure_log) const;
// Returns true if any of the HashValueVectors |static_spki_hashes|,
// |bad_static_spki_hashes|, or |dynamic_spki_hashes| contains any
// items.
bool HasPublicKeyPins() const;
- // ShouldUpgradeToSSL returns true iff, given the |mode| of this
- // DomainState, HTTP requests should be internally redirected to HTTPS
- // (also if the "ws" WebSocket request should be upgraded to "wss")
+ // ShouldUpgradeToSSL returns true iff HTTP requests should be internally
+ // redirected to HTTPS (also if WS should be upgraded to WSS).
bool ShouldUpgradeToSSL() const;
// ShouldSSLErrorsBeFatal returns true iff HTTPS errors should cause
- // hard-fail behavior (e.g. if HSTS is set for the domain)
+ // hard-fail behavior (e.g. if HSTS is set for the domain).
bool ShouldSSLErrorsBeFatal() const;
- UpgradeMode upgrade_mode;
-
- // The absolute time (UTC) when this DomainState was first created.
- //
- // Static entries do not have a created time.
- base::Time created;
-
- // The absolute time (UTC) when the |upgrade_mode|, if set to
- // UPGRADE_ALWAYS, downgrades to UPGRADE_NEVER.
- base::Time upgrade_expiry;
-
- // Are subdomains subject to this DomainState, for the purposes of
- // upgrading to HTTPS?
- bool sts_include_subdomains;
-
- // Are subdomains subject to this DomainState, for the purposes of
- // Pin Validation?
- bool pkp_include_subdomains;
-
- // Optional; hashes of static pinned SubjectPublicKeyInfos. Unless both
- // are empty, at least one of |static_spki_hashes| and
- // |dynamic_spki_hashes| MUST intersect with the set of SPKIs in the TLS
- // server's certificate chain.
- //
- // |dynamic_spki_hashes| take precedence over |static_spki_hashes|.
- // That is, |IsChainOfPublicKeysPermitted| first checks dynamic pins and
- // then checks static pins.
- HashValueVector static_spki_hashes;
-
- // Optional; hashes of dynamically pinned SubjectPublicKeyInfos.
- HashValueVector dynamic_spki_hashes;
-
- // The absolute time (UTC) when the |dynamic_spki_hashes| expire.
- base::Time dynamic_spki_hashes_expiry;
-
- // Optional; hashes of static known-bad SubjectPublicKeyInfos which
- // MUST NOT intersect with the set of SPKIs in the TLS server's
- // certificate chain.
- HashValueVector bad_static_spki_hashes;
+ STSState sts;
+ PKPState pkp;
// The following members are not valid when stored in |enabled_hosts_|:
// The domain which matched during a search for this DomainState entry.
- // Updated by |GetDomainState|, |GetDynamicDomainState|, and
- // |GetStaticDomainState|.
+ // Updated by |GetDynamicDomainState| and |GetStaticDomainState|.
std::string domain;
};
@@ -156,6 +156,17 @@ class NET_EXPORT TransportSecurityState
std::map<std::string, DomainState>::const_iterator end_;
};
+ // These functions search for static and dynamic DomainStates, and invoke the
+ // functions of the same name on them. These functions are the primary public
+ // interface; direct access to DomainStates is best left to tests.
+ bool ShouldSSLErrorsBeFatal(const std::string& host, bool sni_enabled);
+ bool ShouldUpgradeToSSL(const std::string& host, bool sni_enabled);
+ bool CheckPublicKeyPins(const std::string& host,
+ bool sni_enabled,
+ const HashValueVector& hashes,
+ std::string* failure_log);
+ bool HasPublicKeyPins(const std::string& host, bool sni_enabled);
+
// Assign a |Delegate| for persisting the transport security state. If
// |NULL|, state will not be persisted. The caller retains
// ownership of |delegate|.
@@ -195,20 +206,31 @@ class NET_EXPORT TransportSecurityState
// the Delegate (if any).
bool DeleteDynamicDataForHost(const std::string& host);
- // Returns true and updates |*result| iff there is a DomainState for
- // |host|.
+ // Returns true and updates |*result| iff there is a static (built-in)
+ // DomainState for |host|.
//
- // If |sni_enabled| is true, searches the static pins defined for
- // SNI-using hosts as well as the rest of the pins.
+ // If |sni_enabled| is true, searches the static pins defined for SNI-using
+ // hosts as well as the rest of the pins.
//
- // If |host| matches both an exact entry and is a subdomain of another
- // entry, the exact match determines the return value.
+ // If |host| matches both an exact entry and is a subdomain of another entry,
+ // the exact match determines the return value.
//
// Note that this method is not const because it opportunistically removes
// entries that have expired.
- bool GetDomainState(const std::string& host,
- bool sni_enabled,
- DomainState* result);
+ bool GetStaticDomainState(const std::string& host,
+ bool sni_enabled,
+ DomainState* result) const;
+
+ // Returns true and updates |*result| iff there is a dynamic DomainState
+ // (learned from HSTS or HPKP headers, or set by the user, or other means) for
+ // |host|.
+ //
+ // If |host| matches both an exact entry and is a subdomain of another entry,
+ // the exact match determines the return value.
+ //
+ // Note that this method is not const because it opportunistically removes
+ // entries that have expired.
+ bool GetDynamicDomainState(const std::string& host, DomainState* result);
// Processes an HSTS header value from the host, adding entries to
// dynamic state if necessary.
@@ -282,39 +304,6 @@ class NET_EXPORT TransportSecurityState
// the result.
static std::string CanonicalizeHost(const std::string& hostname);
- // Returns true and updates |*result| iff there is a static DomainState for
- // |host|.
- //
- // |GetStaticDomainState| is identical to |GetDomainState| except that it
- // searches only the statically-defined transport security state, ignoring
- // all dynamically-added DomainStates.
- //
- // If |sni_enabled| is true, searches the static pins defined for
- // SNI-using hosts as well as the rest of the pins.
- //
- // If |host| matches both an exact entry and is a subdomain of another
- // entry, the exact match determines the return value.
- //
- // Note that this method is not const because it opportunistically removes
- // entries that have expired.
- bool GetStaticDomainState(const std::string& host,
- bool sni_enabled,
- DomainState* result);
-
- // Returns true and updates |*result| iff there is a dynamic DomainState for
- // |host|.
- //
- // |GetDynamicDomainState| is identical to |GetDomainState| except that it
- // searches only the dynamically-added transport security state, ignoring
- // all statically-defined DomainStates.
- //
- // If |host| matches both an exact entry and is a subdomain of another
- // entry, the exact match determines the return value.
- //
- // Note that this method is not const because it opportunistically removes
- // entries that have expired.
- bool GetDynamicDomainState(const std::string& host, DomainState* result);
-
// The set of hosts that have enabled TransportSecurity.
DomainStateMap enabled_hosts_;
diff --git a/chromium/net/http/transport_security_state_static.h b/chromium/net/http/transport_security_state_static.h
index 6a28ca4562b..3723deafb3d 100644
--- a/chromium/net/http/transport_security_state_static.h
+++ b/chromium/net/http/transport_security_state_static.h
@@ -389,7 +389,7 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{17, true, "\004docs\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{18, true, "\005sites\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{25, true, "\014spreadsheets\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
- {22, false, "\011appengine\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
+ {22, true, "\011appengine\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{22, true, "\011encrypted\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{21, true, "\010accounts\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{21, true, "\010profiles\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
@@ -405,6 +405,7 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{17, true, "\004goto\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{18, true, "\005cloud\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{18, true, "\005glass\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
+ {18, true, "\005admin\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{17, false, "\004play\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{20, true, "\006market\007android\003com", true, kGooglePins, DOMAIN_ANDROID_COM },
{26, true, "\003ssl\020google-analytics\003com", true, kGooglePins, DOMAIN_GOOGLE_ANALYTICS_COM },
@@ -420,6 +421,21 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{16, true, "\012googlecode\003com", false, kGooglePins, DOMAIN_GOOGLECODE_COM },
{15, true, "\002dl\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{26, true, "\011translate\012googleapis\003com", true, kGooglePins, DOMAIN_GOOGLEAPIS_COM },
+ {24, true, "\012webfilings\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {35, true, "\025webfilings-mirror-hrd\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {27, true, "\015webfilings-eu\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {34, true, "\024webfilings-eu-mirror\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {24, true, "\012wf-demo-eu\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {25, true, "\013wf-demo-hrd\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {24, true, "\012wf-pentest\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {26, true, "\014wf-trial-hrd\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {25, true, "\013xbrlsuccess\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {25, true, "\013w-spotlight\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {29, true, "\017wf-training-hrd\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {30, true, "\020wf-bigsky-master\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {27, true, "\015wf-staging-hr\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {32, true, "\022wf-training-master\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
+ {28, true, "\016wf-dogfood-hrd\007appspot\003com", true, kGooglePins, DOMAIN_APPSPOT_COM },
{23, true, "\005chart\004apis\006google\003com", false, kGooglePins, DOMAIN_GOOGLE_COM },
{11, true, "\005ytimg\003com", false, kGooglePins, DOMAIN_YTIMG_COM },
{23, true, "\021googleusercontent\003com", false, kGooglePins, DOMAIN_GOOGLEUSERCONTENT_COM },
@@ -437,6 +453,7 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{8, true, "\003goo\002gl", false, kGooglePins, DOMAIN_GOO_GL },
{6, true, "\001g\002co", false, kGooglePins, DOMAIN_G_CO },
{22, true, "\020googletagmanager\003com", false, kGooglePins, DOMAIN_GOOGLETAGMANAGER_COM },
+ {23, true, "\021googletagservices\003com", false, kGooglePins, DOMAIN_GOOGLETAGSERVICES_COM },
{11, true, "\006google\002ac", false, kGooglePins, DOMAIN_GOOGLE_AC },
{11, true, "\006google\002ad", false, kGooglePins, DOMAIN_GOOGLE_AD },
{11, true, "\006google\002ae", false, kGooglePins, DOMAIN_GOOGLE_AE },
@@ -647,7 +664,6 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{11, true, "\006google\002tm", false, kGooglePins, DOMAIN_GOOGLE_TM },
{11, true, "\006google\002tn", false, kGooglePins, DOMAIN_GOOGLE_TN },
{11, true, "\006google\002to", false, kGooglePins, DOMAIN_GOOGLE_TO },
- {11, true, "\006google\002tp", false, kGooglePins, DOMAIN_GOOGLE_TP },
{11, true, "\006google\002tt", false, kGooglePins, DOMAIN_GOOGLE_TT },
{11, true, "\006google\002us", false, kGooglePins, DOMAIN_GOOGLE_US },
{11, true, "\006google\002uz", false, kGooglePins, DOMAIN_GOOGLE_UZ },
@@ -760,7 +776,7 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{17, false, "\003www\010intercom\002io", true, kNoPins, DOMAIN_NOT_PINNED },
{17, true, "\010fatzebra\003com\002au", true, kNoPins, DOMAIN_NOT_PINNED },
{18, true, "\007csawctf\004poly\003edu", true, kNoPins, DOMAIN_NOT_PINNED },
- {18, false, "\014makeyourlaws\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {18, true, "\014makeyourlaws\003org", true, kNoPins, DOMAIN_NOT_PINNED },
{22, false, "\003www\014makeyourlaws\003org", true, kNoPins, DOMAIN_NOT_PINNED },
{16, true, "\003iop\006intuit\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{14, false, "\010surfeasy\003com", true, kNoPins, DOMAIN_NOT_PINNED },
@@ -776,6 +792,12 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{17, true, "\003faq\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{22, true, "\010platform\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{19, true, "\005email\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\003app\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\003api\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {23, true, "\011keymaster\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {23, true, "\011discovery\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {18, true, "\014mobilethreat\003net", true, kNoPins, DOMAIN_NOT_PINNED },
+ {25, true, "\023mobilethreatnetwork\003net", true, kNoPins, DOMAIN_NOT_PINNED },
{15, true, "\011itriskltd\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{15, true, "\012stocktrade\002de", true, kNoPins, DOMAIN_NOT_PINNED },
{22, true, "\011openshift\006redhat\003com", true, kNoPins, DOMAIN_NOT_PINNED },
@@ -884,6 +906,91 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{14, true, "\003api\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{9, true, "\003eff\003org", true, kNoPins, DOMAIN_NOT_PINNED },
{9, true, "\004mail\002de", true, kNoPins, DOMAIN_NOT_PINNED },
+ {20, false, "\010passport\006yandex\002ru", true, kNoPins, DOMAIN_NOT_PINNED },
+ {21, false, "\010passport\006yandex\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {20, false, "\010passport\006yandex\002ua", true, kNoPins, DOMAIN_NOT_PINNED },
+ {20, false, "\010passport\006yandex\002by", true, kNoPins, DOMAIN_NOT_PINNED },
+ {20, false, "\010passport\006yandex\002kz", true, kNoPins, DOMAIN_NOT_PINNED },
+ {24, false, "\010passport\006yandex\003com\002tr", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, true, "\006mnsure\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {14, false, "\010getcloak\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {18, false, "\003www\010getcloak\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {23, true, "\020matteomarescotti\004name", true, kNoPins, DOMAIN_NOT_PINNED },
+ {19, true, "\003www\011heliosnet\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {13, false, "\007opsmate\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\003www\007opsmate\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {13, true, "\007f-droid\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {18, false, "\003www\010evernote\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {18, false, "\003app\010yinxiang\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {15, false, "\011neilwynne\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {20, false, "\016calyxinstitute\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {24, false, "\003www\016calyxinstitute\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {15, true, "\011blacklane\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {16, true, "\012boxcryptor\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {10, false, "\004aclu\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {14, false, "\003www\004aclu\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {13, true, "\007prodpad\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {13, true, "\007mailbox\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, false, "\006roddis\003net", true, kNoPins, DOMAIN_NOT_PINNED },
+ {16, false, "\003www\006roddis\003net", true, kNoPins, DOMAIN_NOT_PINNED },
+ {10, true, "\005fiken\002no", true, kNoPins, DOMAIN_NOT_PINNED },
+ {14, true, "\010fairbill\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {11, true, "\005nexth\003net", true, kNoPins, DOMAIN_NOT_PINNED },
+ {10, true, "\005nexth\002us", true, kNoPins, DOMAIN_NOT_PINNED },
+ {10, true, "\005nexth\002de", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, true, "\006souyar\003net", true, kNoPins, DOMAIN_NOT_PINNED },
+ {11, true, "\006souyar\002de", true, kNoPins, DOMAIN_NOT_PINNED },
+ {11, true, "\006souyar\002us", true, kNoPins, DOMAIN_NOT_PINNED },
+ {19, false, "\003www\007banking\002co\002at", true, kNoPins, DOMAIN_NOT_PINNED },
+ {19, false, "\003mbp\007banking\002co\002at", true, kNoPins, DOMAIN_NOT_PINNED },
+ {13, false, "\007feedbin\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {9, true, "\004heha\002co", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\013passwordbox\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, false, "\006python\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\004pypi\006python\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {16, true, "\003www\006python\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\004docs\006python\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\013encircleapp\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {19, true, "\010onedrive\004live\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {14, true, "\010onedrive\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {20, true, "\016keepersecurity\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {15, true, "\011keeperapp\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {11, true, "\006donmez\002ws", true, kNoPins, DOMAIN_NOT_PINNED },
+ {23, false, "\010activiti\010alfresco\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {15, true, "\011cloudcert\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {14, true, "\010seifried\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {11, false, "\005wepay\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {15, false, "\003www\005wepay\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {18, false, "\006static\005wepay\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, false, "\005stage\005wepay\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {15, false, "\011vmoagents\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {13, true, "\007adsfund\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {9, false, "\004pult\002co", true, kNoPins, DOMAIN_NOT_PINNED },
+ {18, true, "\014dillonkorman\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, true, "\006edmodo\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {23, false, "\003www\013eternalgoth\002co\002uk", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\003app\007manilla\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {16, true, "\012harvestapp\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, true, "\007anycoin\002me", true, kNoPins, DOMAIN_NOT_PINNED },
+ {14, true, "\010noexpect\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, false, "\006airbnb\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {16, true, "\003www\006airbnb\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {10, false, "\004usaa\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {14, false, "\003www\004usaa\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, false, "\006mobile\004usaa\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, true, "\007subrosa\002io", true, kNoPins, DOMAIN_NOT_PINNED },
+ {15, false, "\011detectify\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {11, true, "\005crbug\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {20, true, "\016manageprojects\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {21, false, "\017tinfoilsecurity\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {25, false, "\003www\017tinfoilsecurity\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {11, false, "\006imouto\002my", true, kNoPins, DOMAIN_NOT_PINNED },
+ {13, true, "\010vocaloid\002my", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\006sakaki\005anime\002my", true, kNoPins, DOMAIN_NOT_PINNED },
+ {18, true, "\007reviews\005anime\002my", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\004miku\007hatsune\002my", true, kNoPins, DOMAIN_NOT_PINNED },
+ {19, true, "\012webcollect\003org\002uk", true, kNoPins, DOMAIN_NOT_PINNED },
+ {24, false, "\003www\016capitainetrain\003com", true, kNoPins, DOMAIN_NOT_PINNED },
};
static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS);
@@ -894,6 +1001,8 @@ static const struct HSTSPreload kPreloadedSNISTS[] = {
{20, false, "\003www\012googlemail\003com", true, kGooglePins, DOMAIN_GOOGLEMAIL_COM },
{22, true, "\020google-analytics\003com", false, kGooglePins, DOMAIN_GOOGLE_ANALYTICS_COM },
{18, true, "\014googlegroups\003com", false, kGooglePins, DOMAIN_GOOGLEGROUPS_COM },
+ {13, true, "\007mykolab\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\013semenkovich\003com", true, kNoPins, DOMAIN_NOT_PINNED },
};
static const size_t kNumPreloadedSNISTS = ARRAYSIZE_UNSAFE(kPreloadedSNISTS);
diff --git a/chromium/net/http/transport_security_state_static.json b/chromium/net/http/transport_security_state_static.json
index 500e1782110..35c14248a68 100644
--- a/chromium/net/http/transport_security_state_static.json
+++ b/chromium/net/http/transport_security_state_static.json
@@ -168,7 +168,7 @@
{ "name": "docs.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "sites.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "spreadsheets.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
- { "name": "appengine.google.com", "mode": "force-https", "pins": "google" },
+ { "name": "appengine.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "encrypted.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "accounts.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "profiles.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
@@ -184,6 +184,7 @@
{ "name": "goto.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "cloud.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "glass.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "admin.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
// play.google.com doesn't have include_subdomains because of crbug.com/327834.
{ "name": "play.google.com", "mode": "force-https", "pins": "google" },
@@ -203,6 +204,22 @@
{ "name": "dl.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "translate.googleapis.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "webfilings.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "webfilings-mirror-hrd.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "webfilings-eu.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "webfilings-eu-mirror.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "wf-demo-eu.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "wf-demo-hrd.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "wf-pentest.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "wf-trial-hrd.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "xbrlsuccess.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "w-spotlight.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "wf-training-hrd.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "wf-bigsky-master.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "wf-staging-hr.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "wf-training-master.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "wf-dogfood-hrd.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+
// chart.apis.google.com is *not* HSTS because the certificate doesn't match
// and there are lots of links out there that still use the name. The correct
// hostname for this is chart.googleapis.com.
@@ -226,6 +243,7 @@
{ "name": "goo.gl", "include_subdomains": true, "pins": "google" },
{ "name": "g.co", "include_subdomains": true, "pins": "google" },
{ "name": "googletagmanager.com", "include_subdomains": true, "pins": "google" },
+ { "name": "googletagservices.com", "include_subdomains": true, "pins": "google" },
{ "name": "google.ac", "include_subdomains": true, "pins": "google" },
{ "name": "google.ad", "include_subdomains": true, "pins": "google" },
{ "name": "google.ae", "include_subdomains": true, "pins": "google" },
@@ -436,7 +454,6 @@
{ "name": "google.tm", "include_subdomains": true, "pins": "google" },
{ "name": "google.tn", "include_subdomains": true, "pins": "google" },
{ "name": "google.to", "include_subdomains": true, "pins": "google" },
- { "name": "google.tp", "include_subdomains": true, "pins": "google" },
{ "name": "google.tt", "include_subdomains": true, "pins": "google" },
{ "name": "google.us", "include_subdomains": true, "pins": "google" },
{ "name": "google.uz", "include_subdomains": true, "pins": "google" },
@@ -553,7 +570,7 @@
{ "name": "www.intercom.io", "mode": "force-https" },
{ "name": "fatzebra.com.au", "include_subdomains": true, "mode": "force-https" },
{ "name": "csawctf.poly.edu", "include_subdomains": true, "mode": "force-https" },
- { "name": "makeyourlaws.org", "mode": "force-https" },
+ { "name": "makeyourlaws.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "www.makeyourlaws.org", "mode": "force-https" },
{ "name": "iop.intuit.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "surfeasy.com", "mode": "force-https" },
@@ -569,6 +586,12 @@
{ "name": "faq.lookout.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "platform.lookout.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "email.lookout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "app.lookout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "api.lookout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keymaster.lookout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "discovery.lookout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobilethreat.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobilethreatnetwork.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "itriskltd.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "stocktrade.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "openshift.redhat.com", "include_subdomains": true, "mode": "force-https" },
@@ -677,6 +700,91 @@
{ "name": "api.xero.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "eff.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "mail.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "passport.yandex.ru", "mode": "force-https" },
+ { "name": "passport.yandex.com", "mode": "force-https" },
+ { "name": "passport.yandex.ua", "mode": "force-https" },
+ { "name": "passport.yandex.by", "mode": "force-https" },
+ { "name": "passport.yandex.kz", "mode": "force-https" },
+ { "name": "passport.yandex.com.tr", "mode": "force-https" },
+ { "name": "mnsure.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getcloak.com", "mode": "force-https" },
+ { "name": "www.getcloak.com", "mode": "force-https" },
+ { "name": "matteomarescotti.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "www.heliosnet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "opsmate.com", "mode": "force-https" },
+ { "name": "www.opsmate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "f-droid.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "www.evernote.com", "mode": "force-https" },
+ { "name": "app.yinxiang.com", "mode": "force-https" },
+ { "name": "neilwynne.com", "mode": "force-https" },
+ { "name": "calyxinstitute.org", "mode": "force-https" },
+ { "name": "www.calyxinstitute.org", "mode": "force-https" },
+ { "name": "blacklane.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "boxcryptor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aclu.org", "mode": "force-https" },
+ { "name": "www.aclu.org", "mode": "force-https" },
+ { "name": "prodpad.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mailbox.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "roddis.net", "mode": "force-https" },
+ { "name": "www.roddis.net", "mode": "force-https" },
+ { "name": "fiken.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fairbill.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nexth.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nexth.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nexth.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "souyar.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "souyar.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "souyar.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "www.banking.co.at", "mode": "force-https" },
+ { "name": "mbp.banking.co.at", "mode": "force-https" },
+ { "name": "feedbin.com", "mode": "force-https" },
+ { "name": "heha.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "passwordbox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "python.org", "mode": "force-https" },
+ { "name": "pypi.python.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "www.python.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "docs.python.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "encircleapp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onedrive.live.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onedrive.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keepersecurity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keeperapp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "donmez.ws", "include_subdomains": true, "mode": "force-https" },
+ { "name": "activiti.alfresco.com", "mode": "force-https" },
+ { "name": "cloudcert.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seifried.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wepay.com", "mode": "force-https" },
+ { "name": "www.wepay.com", "mode": "force-https" },
+ { "name": "static.wepay.com", "mode": "force-https" },
+ { "name": "stage.wepay.com", "mode": "force-https" },
+ { "name": "vmoagents.com", "mode": "force-https" },
+ { "name": "adsfund.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pult.co", "mode": "force-https" },
+ { "name": "dillonkorman.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "edmodo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "www.eternalgoth.co.uk", "mode": "force-https" },
+ { "name": "app.manilla.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "harvestapp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anycoin.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "noexpect.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "airbnb.com", "mode": "force-https" },
+ { "name": "www.airbnb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usaa.com", "mode": "force-https" },
+ { "name": "www.usaa.com", "mode": "force-https" },
+ { "name": "mobile.usaa.com", "mode": "force-https" },
+ { "name": "subrosa.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "detectify.com", "mode": "force-https" },
+ { "name": "crbug.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "manageprojects.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tinfoilsecurity.com", "mode": "force-https" },
+ { "name": "www.tinfoilsecurity.com", "mode": "force-https" },
+ { "name": "imouto.my", "mode": "force-https" },
+ { "name": "vocaloid.my", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sakaki.anime.my", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reviews.anime.my", "include_subdomains": true, "mode": "force-https" },
+ { "name": "miku.hatsune.my", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webcollect.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "www.capitainetrain.com", "mode": "force-https" },
// Entries that are only valid if the client supports SNI.
{ "name": "gmail.com", "mode": "force-https", "pins": "google", "snionly": true },
@@ -684,6 +792,8 @@
{ "name": "www.gmail.com", "mode": "force-https", "pins": "google", "snionly": true },
{ "name": "www.googlemail.com", "mode": "force-https", "pins": "google", "snionly": true },
{ "name": "google-analytics.com", "include_subdomains": true, "pins": "google", "snionly": true },
- { "name": "googlegroups.com", "include_subdomains": true, "pins": "google", "snionly": true }
+ { "name": "googlegroups.com", "include_subdomains": true, "pins": "google", "snionly": true },
+ { "name": "mykolab.com", "include_subdomains": true, "mode": "force-https", "snionly": true },
+ { "name": "semenkovich.com", "include_subdomains": true, "mode": "force-https", "snionly": true }
]
}
diff --git a/chromium/net/http/transport_security_state_unittest.cc b/chromium/net/http/transport_security_state_unittest.cc
index c3d15da29f9..476ae94bd68 100644
--- a/chromium/net/http/transport_security_state_unittest.cc
+++ b/chromium/net/http/transport_security_state_unittest.cc
@@ -46,10 +46,6 @@ class TransportSecurityStateTest : public testing::Test {
}
protected:
- std::string CanonicalizeHost(const std::string& host) {
- return TransportSecurityState::CanonicalizeHost(host);
- }
-
bool GetStaticDomainState(TransportSecurityState* state,
const std::string& host,
bool sni_enabled,
@@ -70,10 +66,10 @@ TEST_F(TransportSecurityStateTest, SimpleMatches) {
const base::Time current_time(base::Time::Now());
const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
- EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
+ EXPECT_FALSE(state.GetDynamicDomainState("yahoo.com", &domain_state));
bool include_subdomains = false;
state.AddHSTS("yahoo.com", expiry, include_subdomains);
- EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
+ EXPECT_TRUE(state.GetDynamicDomainState("yahoo.com", &domain_state));
}
TEST_F(TransportSecurityStateTest, MatchesCase1) {
@@ -82,10 +78,10 @@ TEST_F(TransportSecurityStateTest, MatchesCase1) {
const base::Time current_time(base::Time::Now());
const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
- EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
+ EXPECT_FALSE(state.GetDynamicDomainState("yahoo.com", &domain_state));
bool include_subdomains = false;
state.AddHSTS("YAhoo.coM", expiry, include_subdomains);
- EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
+ EXPECT_TRUE(state.GetDynamicDomainState("yahoo.com", &domain_state));
}
TEST_F(TransportSecurityStateTest, MatchesCase2) {
@@ -94,10 +90,10 @@ TEST_F(TransportSecurityStateTest, MatchesCase2) {
const base::Time current_time(base::Time::Now());
const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
- EXPECT_FALSE(state.GetDomainState("YAhoo.coM", true, &domain_state));
+ EXPECT_FALSE(state.GetDynamicDomainState("YAhoo.coM", &domain_state));
bool include_subdomains = false;
state.AddHSTS("yahoo.com", expiry, include_subdomains);
- EXPECT_TRUE(state.GetDomainState("YAhoo.coM", true, &domain_state));
+ EXPECT_TRUE(state.GetDynamicDomainState("YAhoo.coM", &domain_state));
}
TEST_F(TransportSecurityStateTest, SubdomainMatches) {
@@ -106,15 +102,15 @@ TEST_F(TransportSecurityStateTest, SubdomainMatches) {
const base::Time current_time(base::Time::Now());
const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
- EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
+ EXPECT_FALSE(state.GetDynamicDomainState("yahoo.com", &domain_state));
bool include_subdomains = true;
state.AddHSTS("yahoo.com", expiry, include_subdomains);
- EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
- EXPECT_TRUE(state.GetDomainState("foo.yahoo.com", true, &domain_state));
- EXPECT_TRUE(state.GetDomainState("foo.bar.yahoo.com", true, &domain_state));
- EXPECT_TRUE(state.GetDomainState("foo.bar.baz.yahoo.com", true,
- &domain_state));
- EXPECT_FALSE(state.GetDomainState("com", true, &domain_state));
+ EXPECT_TRUE(state.GetDynamicDomainState("yahoo.com", &domain_state));
+ EXPECT_TRUE(state.GetDynamicDomainState("foo.yahoo.com", &domain_state));
+ EXPECT_TRUE(state.GetDynamicDomainState("foo.bar.yahoo.com", &domain_state));
+ EXPECT_TRUE(
+ state.GetDynamicDomainState("foo.bar.baz.yahoo.com", &domain_state));
+ EXPECT_FALSE(state.GetDynamicDomainState("com", &domain_state));
}
TEST_F(TransportSecurityStateTest, InvalidDomains) {
@@ -123,11 +119,12 @@ TEST_F(TransportSecurityStateTest, InvalidDomains) {
const base::Time current_time(base::Time::Now());
const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
- EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
+ EXPECT_FALSE(state.GetDynamicDomainState("yahoo.com", &domain_state));
bool include_subdomains = true;
state.AddHSTS("yahoo.com", expiry, include_subdomains);
- EXPECT_TRUE(state.GetDomainState("www-.foo.yahoo.com", true, &domain_state));
- EXPECT_TRUE(state.GetDomainState("2\x01.foo.yahoo.com", true, &domain_state));
+ EXPECT_TRUE(state.GetDynamicDomainState("www-.foo.yahoo.com", &domain_state));
+ EXPECT_TRUE(
+ state.GetDynamicDomainState("2\x01.foo.yahoo.com", &domain_state));
}
TEST_F(TransportSecurityStateTest, DeleteAllDynamicDataSince) {
@@ -137,14 +134,18 @@ TEST_F(TransportSecurityStateTest, DeleteAllDynamicDataSince) {
const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
const base::Time older = current_time - base::TimeDelta::FromSeconds(1000);
- EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
+ EXPECT_FALSE(state.GetDynamicDomainState("yahoo.com", &domain_state));
bool include_subdomains = false;
state.AddHSTS("yahoo.com", expiry, include_subdomains);
state.DeleteAllDynamicDataSince(expiry);
- EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
+ EXPECT_TRUE(state.GetDynamicDomainState("yahoo.com", &domain_state));
+ EXPECT_EQ(TransportSecurityState::DomainState::MODE_FORCE_HTTPS,
+ domain_state.sts.upgrade_mode);
state.DeleteAllDynamicDataSince(older);
- EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
+ EXPECT_TRUE(state.GetDynamicDomainState("yahoo.com", &domain_state));
+ EXPECT_EQ(TransportSecurityState::DomainState::MODE_DEFAULT,
+ domain_state.sts.upgrade_mode);
}
TEST_F(TransportSecurityStateTest, DeleteDynamicDataForHost) {
@@ -155,28 +156,28 @@ TEST_F(TransportSecurityStateTest, DeleteDynamicDataForHost) {
bool include_subdomains = false;
state.AddHSTS("yahoo.com", expiry, include_subdomains);
- EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
- EXPECT_FALSE(state.GetDomainState("example.com", true, &domain_state));
+ EXPECT_TRUE(state.GetDynamicDomainState("yahoo.com", &domain_state));
+ EXPECT_FALSE(state.GetDynamicDomainState("example.com", &domain_state));
EXPECT_TRUE(state.DeleteDynamicDataForHost("yahoo.com"));
- EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
+ EXPECT_FALSE(state.GetDynamicDomainState("yahoo.com", &domain_state));
}
TEST_F(TransportSecurityStateTest, IsPreloaded) {
- const std::string paypal = CanonicalizeHost("paypal.com");
- const std::string www_paypal = CanonicalizeHost("www.paypal.com");
- const std::string foo_paypal = CanonicalizeHost("foo.paypal.com");
- const std::string a_www_paypal = CanonicalizeHost("a.www.paypal.com");
- const std::string abc_paypal = CanonicalizeHost("a.b.c.paypal.com");
- const std::string example = CanonicalizeHost("example.com");
- const std::string aypal = CanonicalizeHost("aypal.com");
+ const std::string paypal = "paypal.com";
+ const std::string www_paypal = "www.paypal.com";
+ const std::string foo_paypal = "foo.paypal.com";
+ const std::string a_www_paypal = "a.www.paypal.com";
+ const std::string abc_paypal = "a.b.c.paypal.com";
+ const std::string example = "example.com";
+ const std::string aypal = "aypal.com";
TransportSecurityState state;
TransportSecurityState::DomainState domain_state;
EXPECT_TRUE(GetStaticDomainState(&state, paypal, true, &domain_state));
EXPECT_TRUE(GetStaticDomainState(&state, www_paypal, true, &domain_state));
- EXPECT_FALSE(domain_state.sts_include_subdomains);
- EXPECT_FALSE(domain_state.pkp_include_subdomains);
+ EXPECT_FALSE(domain_state.sts.include_subdomains);
+ EXPECT_FALSE(domain_state.pkp.include_subdomains);
EXPECT_FALSE(GetStaticDomainState(&state, a_www_paypal, true, &domain_state));
EXPECT_FALSE(GetStaticDomainState(&state, abc_paypal, true, &domain_state));
EXPECT_FALSE(GetStaticDomainState(&state, example, true, &domain_state));
@@ -189,48 +190,49 @@ TEST_F(TransportSecurityStateTest, PreloadedDomainSet) {
// The domain wasn't being set, leading to a blank string in the
// chrome://net-internals/#hsts UI. So test that.
- EXPECT_TRUE(state.GetDomainState("market.android.com", true, &domain_state));
+ EXPECT_TRUE(
+ state.GetStaticDomainState("market.android.com", true, &domain_state));
EXPECT_EQ(domain_state.domain, "market.android.com");
- EXPECT_TRUE(state.GetDomainState("sub.market.android.com", true,
- &domain_state));
+ EXPECT_TRUE(state.GetStaticDomainState(
+ "sub.market.android.com", true, &domain_state));
EXPECT_EQ(domain_state.domain, "market.android.com");
}
-static bool ShouldRedirect(const char* hostname) {
+static bool StaticShouldRedirect(const char* hostname) {
TransportSecurityState state;
TransportSecurityState::DomainState domain_state;
- return state.GetDomainState(hostname, true /* SNI ok */, &domain_state) &&
+ return state.GetStaticDomainState(
+ hostname, true /* SNI ok */, &domain_state) &&
domain_state.ShouldUpgradeToSSL();
}
-static bool HasState(const char* hostname) {
+static bool HasStaticState(const char* hostname) {
TransportSecurityState state;
TransportSecurityState::DomainState domain_state;
- return state.GetDomainState(hostname, true /* SNI ok */, &domain_state);
+ return state.GetStaticDomainState(hostname, true /* SNI ok */, &domain_state);
}
-static bool HasPublicKeyPins(const char* hostname, bool sni_enabled) {
+static bool HasStaticPublicKeyPins(const char* hostname, bool sni_enabled) {
TransportSecurityState state;
TransportSecurityState::DomainState domain_state;
- if (!state.GetDomainState(hostname, sni_enabled, &domain_state))
+ if (!state.GetStaticDomainState(hostname, sni_enabled, &domain_state))
return false;
return domain_state.HasPublicKeyPins();
}
-static bool HasPublicKeyPins(const char* hostname) {
- return HasPublicKeyPins(hostname, true);
+static bool HasStaticPublicKeyPins(const char* hostname) {
+ return HasStaticPublicKeyPins(hostname, true);
}
-static bool OnlyPinning(const char *hostname) {
+static bool OnlyPinningInStaticState(const char* hostname) {
TransportSecurityState state;
TransportSecurityState::DomainState domain_state;
- if (!state.GetDomainState(hostname, true /* SNI ok */, &domain_state))
+ if (!state.GetStaticDomainState(hostname, true /* SNI ok */, &domain_state))
return false;
- return (domain_state.static_spki_hashes.size() > 0 ||
- domain_state.bad_static_spki_hashes.size() > 0 ||
- domain_state.dynamic_spki_hashes.size() > 0) &&
+ return (domain_state.pkp.spki_hashes.size() > 0 ||
+ domain_state.pkp.bad_spki_hashes.size() > 0) &&
!domain_state.ShouldUpgradeToSSL();
}
@@ -239,240 +241,245 @@ TEST_F(TransportSecurityStateTest, Preloaded) {
TransportSecurityState::DomainState domain_state;
// We do more extensive checks for the first domain.
- EXPECT_TRUE(state.GetDomainState("www.paypal.com", true, &domain_state));
- EXPECT_EQ(domain_state.upgrade_mode,
+ EXPECT_TRUE(
+ state.GetStaticDomainState("www.paypal.com", true, &domain_state));
+ EXPECT_EQ(domain_state.sts.upgrade_mode,
TransportSecurityState::DomainState::MODE_FORCE_HTTPS);
- EXPECT_FALSE(domain_state.sts_include_subdomains);
- EXPECT_FALSE(domain_state.pkp_include_subdomains);
+ EXPECT_FALSE(domain_state.sts.include_subdomains);
+ EXPECT_FALSE(domain_state.pkp.include_subdomains);
- EXPECT_TRUE(HasState("paypal.com"));
- EXPECT_FALSE(HasState("www2.paypal.com"));
- EXPECT_FALSE(HasState("www2.paypal.com"));
+ EXPECT_TRUE(HasStaticState("paypal.com"));
+ EXPECT_FALSE(HasStaticState("www2.paypal.com"));
+ EXPECT_FALSE(HasStaticState("www2.paypal.com"));
// Google hosts:
- EXPECT_TRUE(ShouldRedirect("chrome.google.com"));
- EXPECT_TRUE(ShouldRedirect("checkout.google.com"));
- EXPECT_TRUE(ShouldRedirect("wallet.google.com"));
- EXPECT_TRUE(ShouldRedirect("docs.google.com"));
- EXPECT_TRUE(ShouldRedirect("sites.google.com"));
- EXPECT_TRUE(ShouldRedirect("drive.google.com"));
- EXPECT_TRUE(ShouldRedirect("spreadsheets.google.com"));
- EXPECT_TRUE(ShouldRedirect("appengine.google.com"));
- EXPECT_TRUE(ShouldRedirect("market.android.com"));
- EXPECT_TRUE(ShouldRedirect("encrypted.google.com"));
- EXPECT_TRUE(ShouldRedirect("accounts.google.com"));
- EXPECT_TRUE(ShouldRedirect("profiles.google.com"));
- EXPECT_TRUE(ShouldRedirect("mail.google.com"));
- EXPECT_TRUE(ShouldRedirect("chatenabled.mail.google.com"));
- EXPECT_TRUE(ShouldRedirect("talkgadget.google.com"));
- EXPECT_TRUE(ShouldRedirect("hostedtalkgadget.google.com"));
- EXPECT_TRUE(ShouldRedirect("talk.google.com"));
- EXPECT_TRUE(ShouldRedirect("plus.google.com"));
- EXPECT_TRUE(ShouldRedirect("groups.google.com"));
- EXPECT_TRUE(ShouldRedirect("apis.google.com"));
- EXPECT_FALSE(ShouldRedirect("chart.apis.google.com"));
- EXPECT_TRUE(ShouldRedirect("ssl.google-analytics.com"));
- EXPECT_TRUE(ShouldRedirect("gmail.com"));
- EXPECT_TRUE(ShouldRedirect("www.gmail.com"));
- EXPECT_TRUE(ShouldRedirect("googlemail.com"));
- EXPECT_TRUE(ShouldRedirect("www.googlemail.com"));
- EXPECT_TRUE(ShouldRedirect("googleplex.com"));
- EXPECT_TRUE(ShouldRedirect("www.googleplex.com"));
- EXPECT_FALSE(HasState("m.gmail.com"));
- EXPECT_FALSE(HasState("m.googlemail.com"));
-
- EXPECT_TRUE(OnlyPinning("www.google.com"));
- EXPECT_TRUE(OnlyPinning("foo.google.com"));
- EXPECT_TRUE(OnlyPinning("google.com"));
- EXPECT_TRUE(OnlyPinning("www.youtube.com"));
- EXPECT_TRUE(OnlyPinning("youtube.com"));
- EXPECT_TRUE(OnlyPinning("i.ytimg.com"));
- EXPECT_TRUE(OnlyPinning("ytimg.com"));
- EXPECT_TRUE(OnlyPinning("googleusercontent.com"));
- EXPECT_TRUE(OnlyPinning("www.googleusercontent.com"));
- EXPECT_TRUE(OnlyPinning("www.google-analytics.com"));
- EXPECT_TRUE(OnlyPinning("googleapis.com"));
- EXPECT_TRUE(OnlyPinning("googleadservices.com"));
- EXPECT_TRUE(OnlyPinning("googlecode.com"));
- EXPECT_TRUE(OnlyPinning("appspot.com"));
- EXPECT_TRUE(OnlyPinning("googlesyndication.com"));
- EXPECT_TRUE(OnlyPinning("doubleclick.net"));
- EXPECT_TRUE(OnlyPinning("googlegroups.com"));
+ EXPECT_TRUE(StaticShouldRedirect("chrome.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("checkout.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("wallet.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("docs.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("sites.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("drive.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("spreadsheets.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("appengine.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("market.android.com"));
+ EXPECT_TRUE(StaticShouldRedirect("encrypted.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("accounts.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("profiles.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("mail.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("chatenabled.mail.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("talkgadget.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("hostedtalkgadget.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("talk.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("plus.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("groups.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("apis.google.com"));
+ EXPECT_FALSE(StaticShouldRedirect("chart.apis.google.com"));
+ EXPECT_TRUE(StaticShouldRedirect("ssl.google-analytics.com"));
+ EXPECT_TRUE(StaticShouldRedirect("gmail.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.gmail.com"));
+ EXPECT_TRUE(StaticShouldRedirect("googlemail.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.googlemail.com"));
+ EXPECT_TRUE(StaticShouldRedirect("googleplex.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.googleplex.com"));
+ EXPECT_FALSE(HasStaticState("m.gmail.com"));
+ EXPECT_FALSE(HasStaticState("m.googlemail.com"));
+
+ EXPECT_TRUE(OnlyPinningInStaticState("www.google.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("foo.google.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("google.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("www.youtube.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("youtube.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("i.ytimg.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("ytimg.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("googleusercontent.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("www.googleusercontent.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("www.google-analytics.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("googleapis.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("googleadservices.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("googlecode.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("appspot.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("googlesyndication.com"));
+ EXPECT_TRUE(OnlyPinningInStaticState("doubleclick.net"));
+ EXPECT_TRUE(OnlyPinningInStaticState("googlegroups.com"));
// Tests for domains that don't work without SNI.
- EXPECT_FALSE(state.GetDomainState("gmail.com", false, &domain_state));
- EXPECT_FALSE(state.GetDomainState("www.gmail.com", false, &domain_state));
- EXPECT_FALSE(state.GetDomainState("m.gmail.com", false, &domain_state));
- EXPECT_FALSE(state.GetDomainState("googlemail.com", false, &domain_state));
- EXPECT_FALSE(state.GetDomainState("www.googlemail.com", false,
- &domain_state));
- EXPECT_FALSE(state.GetDomainState("m.googlemail.com", false, &domain_state));
+ EXPECT_FALSE(state.GetStaticDomainState("gmail.com", false, &domain_state));
+ EXPECT_FALSE(
+ state.GetStaticDomainState("www.gmail.com", false, &domain_state));
+ EXPECT_FALSE(state.GetStaticDomainState("m.gmail.com", false, &domain_state));
+ EXPECT_FALSE(
+ state.GetStaticDomainState("googlemail.com", false, &domain_state));
+ EXPECT_FALSE(
+ state.GetStaticDomainState("www.googlemail.com", false, &domain_state));
+ EXPECT_FALSE(
+ state.GetStaticDomainState("m.googlemail.com", false, &domain_state));
// Other hosts:
- EXPECT_TRUE(ShouldRedirect("aladdinschools.appspot.com"));
-
- EXPECT_TRUE(ShouldRedirect("ottospora.nl"));
- EXPECT_TRUE(ShouldRedirect("www.ottospora.nl"));
+ EXPECT_TRUE(StaticShouldRedirect("aladdinschools.appspot.com"));
- EXPECT_TRUE(ShouldRedirect("www.paycheckrecords.com"));
+ EXPECT_TRUE(StaticShouldRedirect("ottospora.nl"));
+ EXPECT_TRUE(StaticShouldRedirect("www.ottospora.nl"));
- EXPECT_TRUE(ShouldRedirect("lastpass.com"));
- EXPECT_TRUE(ShouldRedirect("www.lastpass.com"));
- EXPECT_FALSE(HasState("blog.lastpass.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.paycheckrecords.com"));
- EXPECT_TRUE(ShouldRedirect("keyerror.com"));
- EXPECT_TRUE(ShouldRedirect("www.keyerror.com"));
+ EXPECT_TRUE(StaticShouldRedirect("lastpass.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.lastpass.com"));
+ EXPECT_FALSE(HasStaticState("blog.lastpass.com"));
- EXPECT_TRUE(ShouldRedirect("entropia.de"));
- EXPECT_TRUE(ShouldRedirect("www.entropia.de"));
- EXPECT_FALSE(HasState("foo.entropia.de"));
+ EXPECT_TRUE(StaticShouldRedirect("keyerror.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.keyerror.com"));
- EXPECT_TRUE(ShouldRedirect("www.elanex.biz"));
- EXPECT_FALSE(HasState("elanex.biz"));
- EXPECT_FALSE(HasState("foo.elanex.biz"));
+ EXPECT_TRUE(StaticShouldRedirect("entropia.de"));
+ EXPECT_TRUE(StaticShouldRedirect("www.entropia.de"));
+ EXPECT_FALSE(HasStaticState("foo.entropia.de"));
- EXPECT_TRUE(ShouldRedirect("sunshinepress.org"));
- EXPECT_TRUE(ShouldRedirect("www.sunshinepress.org"));
- EXPECT_TRUE(ShouldRedirect("a.b.sunshinepress.org"));
+ EXPECT_TRUE(StaticShouldRedirect("www.elanex.biz"));
+ EXPECT_FALSE(HasStaticState("elanex.biz"));
+ EXPECT_FALSE(HasStaticState("foo.elanex.biz"));
- EXPECT_TRUE(ShouldRedirect("www.noisebridge.net"));
- EXPECT_FALSE(HasState("noisebridge.net"));
- EXPECT_FALSE(HasState("foo.noisebridge.net"));
+ EXPECT_TRUE(StaticShouldRedirect("sunshinepress.org"));
+ EXPECT_TRUE(StaticShouldRedirect("www.sunshinepress.org"));
+ EXPECT_TRUE(StaticShouldRedirect("a.b.sunshinepress.org"));
- EXPECT_TRUE(ShouldRedirect("neg9.org"));
- EXPECT_FALSE(HasState("www.neg9.org"));
+ EXPECT_TRUE(StaticShouldRedirect("www.noisebridge.net"));
+ EXPECT_FALSE(HasStaticState("noisebridge.net"));
+ EXPECT_FALSE(HasStaticState("foo.noisebridge.net"));
- EXPECT_TRUE(ShouldRedirect("riseup.net"));
- EXPECT_TRUE(ShouldRedirect("foo.riseup.net"));
+ EXPECT_TRUE(StaticShouldRedirect("neg9.org"));
+ EXPECT_FALSE(HasStaticState("www.neg9.org"));
- EXPECT_TRUE(ShouldRedirect("factor.cc"));
- EXPECT_FALSE(HasState("www.factor.cc"));
+ EXPECT_TRUE(StaticShouldRedirect("riseup.net"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.riseup.net"));
- EXPECT_TRUE(ShouldRedirect("members.mayfirst.org"));
- EXPECT_TRUE(ShouldRedirect("support.mayfirst.org"));
- EXPECT_TRUE(ShouldRedirect("id.mayfirst.org"));
- EXPECT_TRUE(ShouldRedirect("lists.mayfirst.org"));
- EXPECT_FALSE(HasState("www.mayfirst.org"));
+ EXPECT_TRUE(StaticShouldRedirect("factor.cc"));
+ EXPECT_FALSE(HasStaticState("www.factor.cc"));
- EXPECT_TRUE(ShouldRedirect("romab.com"));
- EXPECT_TRUE(ShouldRedirect("www.romab.com"));
- EXPECT_TRUE(ShouldRedirect("foo.romab.com"));
+ EXPECT_TRUE(StaticShouldRedirect("members.mayfirst.org"));
+ EXPECT_TRUE(StaticShouldRedirect("support.mayfirst.org"));
+ EXPECT_TRUE(StaticShouldRedirect("id.mayfirst.org"));
+ EXPECT_TRUE(StaticShouldRedirect("lists.mayfirst.org"));
+ EXPECT_FALSE(HasStaticState("www.mayfirst.org"));
- EXPECT_TRUE(ShouldRedirect("logentries.com"));
- EXPECT_TRUE(ShouldRedirect("www.logentries.com"));
- EXPECT_FALSE(HasState("foo.logentries.com"));
+ EXPECT_TRUE(StaticShouldRedirect("romab.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.romab.com"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.romab.com"));
- EXPECT_TRUE(ShouldRedirect("stripe.com"));
- EXPECT_TRUE(ShouldRedirect("foo.stripe.com"));
+ EXPECT_TRUE(StaticShouldRedirect("logentries.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.logentries.com"));
+ EXPECT_FALSE(HasStaticState("foo.logentries.com"));
- EXPECT_TRUE(ShouldRedirect("cloudsecurityalliance.org"));
- EXPECT_TRUE(ShouldRedirect("foo.cloudsecurityalliance.org"));
+ EXPECT_TRUE(StaticShouldRedirect("stripe.com"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.stripe.com"));
- EXPECT_TRUE(ShouldRedirect("login.sapo.pt"));
- EXPECT_TRUE(ShouldRedirect("foo.login.sapo.pt"));
+ EXPECT_TRUE(StaticShouldRedirect("cloudsecurityalliance.org"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.cloudsecurityalliance.org"));
- EXPECT_TRUE(ShouldRedirect("mattmccutchen.net"));
- EXPECT_TRUE(ShouldRedirect("foo.mattmccutchen.net"));
+ EXPECT_TRUE(StaticShouldRedirect("login.sapo.pt"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.login.sapo.pt"));
- EXPECT_TRUE(ShouldRedirect("betnet.fr"));
- EXPECT_TRUE(ShouldRedirect("foo.betnet.fr"));
+ EXPECT_TRUE(StaticShouldRedirect("mattmccutchen.net"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.mattmccutchen.net"));
- EXPECT_TRUE(ShouldRedirect("uprotect.it"));
- EXPECT_TRUE(ShouldRedirect("foo.uprotect.it"));
+ EXPECT_TRUE(StaticShouldRedirect("betnet.fr"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.betnet.fr"));
- EXPECT_TRUE(ShouldRedirect("squareup.com"));
- EXPECT_FALSE(HasState("foo.squareup.com"));
+ EXPECT_TRUE(StaticShouldRedirect("uprotect.it"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.uprotect.it"));
- EXPECT_TRUE(ShouldRedirect("cert.se"));
- EXPECT_TRUE(ShouldRedirect("foo.cert.se"));
+ EXPECT_TRUE(StaticShouldRedirect("squareup.com"));
+ EXPECT_FALSE(HasStaticState("foo.squareup.com"));
- EXPECT_TRUE(ShouldRedirect("crypto.is"));
- EXPECT_TRUE(ShouldRedirect("foo.crypto.is"));
+ EXPECT_TRUE(StaticShouldRedirect("cert.se"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.cert.se"));
- EXPECT_TRUE(ShouldRedirect("simon.butcher.name"));
- EXPECT_TRUE(ShouldRedirect("foo.simon.butcher.name"));
+ EXPECT_TRUE(StaticShouldRedirect("crypto.is"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.crypto.is"));
- EXPECT_TRUE(ShouldRedirect("linx.net"));
- EXPECT_TRUE(ShouldRedirect("foo.linx.net"));
+ EXPECT_TRUE(StaticShouldRedirect("simon.butcher.name"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.simon.butcher.name"));
- EXPECT_TRUE(ShouldRedirect("dropcam.com"));
- EXPECT_TRUE(ShouldRedirect("www.dropcam.com"));
- EXPECT_FALSE(HasState("foo.dropcam.com"));
+ EXPECT_TRUE(StaticShouldRedirect("linx.net"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.linx.net"));
- EXPECT_TRUE(state.GetDomainState("torproject.org", false, &domain_state));
- EXPECT_FALSE(domain_state.static_spki_hashes.empty());
- EXPECT_TRUE(state.GetDomainState("www.torproject.org", false,
- &domain_state));
- EXPECT_FALSE(domain_state.static_spki_hashes.empty());
- EXPECT_TRUE(state.GetDomainState("check.torproject.org", false,
- &domain_state));
- EXPECT_FALSE(domain_state.static_spki_hashes.empty());
- EXPECT_TRUE(state.GetDomainState("blog.torproject.org", false,
- &domain_state));
- EXPECT_FALSE(domain_state.static_spki_hashes.empty());
- EXPECT_TRUE(ShouldRedirect("ebanking.indovinabank.com.vn"));
- EXPECT_TRUE(ShouldRedirect("foo.ebanking.indovinabank.com.vn"));
+ EXPECT_TRUE(StaticShouldRedirect("dropcam.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.dropcam.com"));
+ EXPECT_FALSE(HasStaticState("foo.dropcam.com"));
- EXPECT_TRUE(ShouldRedirect("epoxate.com"));
- EXPECT_FALSE(HasState("foo.epoxate.com"));
+ EXPECT_TRUE(
+ state.GetStaticDomainState("torproject.org", false, &domain_state));
+ EXPECT_FALSE(domain_state.pkp.spki_hashes.empty());
+ EXPECT_TRUE(
+ state.GetStaticDomainState("www.torproject.org", false, &domain_state));
+ EXPECT_FALSE(domain_state.pkp.spki_hashes.empty());
+ EXPECT_TRUE(
+ state.GetStaticDomainState("check.torproject.org", false, &domain_state));
+ EXPECT_FALSE(domain_state.pkp.spki_hashes.empty());
+ EXPECT_TRUE(
+ state.GetStaticDomainState("blog.torproject.org", false, &domain_state));
+ EXPECT_FALSE(domain_state.pkp.spki_hashes.empty());
+ EXPECT_TRUE(StaticShouldRedirect("ebanking.indovinabank.com.vn"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.ebanking.indovinabank.com.vn"));
- EXPECT_TRUE(HasPublicKeyPins("torproject.org"));
- EXPECT_TRUE(HasPublicKeyPins("www.torproject.org"));
- EXPECT_TRUE(HasPublicKeyPins("check.torproject.org"));
- EXPECT_TRUE(HasPublicKeyPins("blog.torproject.org"));
- EXPECT_FALSE(HasState("foo.torproject.org"));
+ EXPECT_TRUE(StaticShouldRedirect("epoxate.com"));
+ EXPECT_FALSE(HasStaticState("foo.epoxate.com"));
- EXPECT_TRUE(ShouldRedirect("www.moneybookers.com"));
- EXPECT_FALSE(HasState("moneybookers.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("torproject.org"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("www.torproject.org"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("check.torproject.org"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("blog.torproject.org"));
+ EXPECT_FALSE(HasStaticState("foo.torproject.org"));
- EXPECT_TRUE(ShouldRedirect("ledgerscope.net"));
- EXPECT_TRUE(ShouldRedirect("www.ledgerscope.net"));
- EXPECT_FALSE(HasState("status.ledgerscope.net"));
+ EXPECT_TRUE(StaticShouldRedirect("www.moneybookers.com"));
+ EXPECT_FALSE(HasStaticState("moneybookers.com"));
- EXPECT_TRUE(ShouldRedirect("foo.app.recurly.com"));
- EXPECT_TRUE(ShouldRedirect("foo.api.recurly.com"));
+ EXPECT_TRUE(StaticShouldRedirect("ledgerscope.net"));
+ EXPECT_TRUE(StaticShouldRedirect("www.ledgerscope.net"));
+ EXPECT_FALSE(HasStaticState("status.ledgerscope.net"));
- EXPECT_TRUE(ShouldRedirect("greplin.com"));
- EXPECT_TRUE(ShouldRedirect("www.greplin.com"));
- EXPECT_FALSE(HasState("foo.greplin.com"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.app.recurly.com"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.api.recurly.com"));
- EXPECT_TRUE(ShouldRedirect("luneta.nearbuysystems.com"));
- EXPECT_TRUE(ShouldRedirect("foo.luneta.nearbuysystems.com"));
+ EXPECT_TRUE(StaticShouldRedirect("greplin.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.greplin.com"));
+ EXPECT_FALSE(HasStaticState("foo.greplin.com"));
- EXPECT_TRUE(ShouldRedirect("ubertt.org"));
- EXPECT_TRUE(ShouldRedirect("foo.ubertt.org"));
+ EXPECT_TRUE(StaticShouldRedirect("luneta.nearbuysystems.com"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.luneta.nearbuysystems.com"));
- EXPECT_TRUE(ShouldRedirect("pixi.me"));
- EXPECT_TRUE(ShouldRedirect("www.pixi.me"));
+ EXPECT_TRUE(StaticShouldRedirect("ubertt.org"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.ubertt.org"));
- EXPECT_TRUE(ShouldRedirect("grepular.com"));
- EXPECT_TRUE(ShouldRedirect("www.grepular.com"));
+ EXPECT_TRUE(StaticShouldRedirect("pixi.me"));
+ EXPECT_TRUE(StaticShouldRedirect("www.pixi.me"));
- EXPECT_TRUE(ShouldRedirect("mydigipass.com"));
- EXPECT_FALSE(ShouldRedirect("foo.mydigipass.com"));
- EXPECT_TRUE(ShouldRedirect("www.mydigipass.com"));
- EXPECT_FALSE(ShouldRedirect("foo.www.mydigipass.com"));
- EXPECT_TRUE(ShouldRedirect("developer.mydigipass.com"));
- EXPECT_FALSE(ShouldRedirect("foo.developer.mydigipass.com"));
- EXPECT_TRUE(ShouldRedirect("www.developer.mydigipass.com"));
- EXPECT_FALSE(ShouldRedirect("foo.www.developer.mydigipass.com"));
- EXPECT_TRUE(ShouldRedirect("sandbox.mydigipass.com"));
- EXPECT_FALSE(ShouldRedirect("foo.sandbox.mydigipass.com"));
- EXPECT_TRUE(ShouldRedirect("www.sandbox.mydigipass.com"));
- EXPECT_FALSE(ShouldRedirect("foo.www.sandbox.mydigipass.com"));
+ EXPECT_TRUE(StaticShouldRedirect("grepular.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.grepular.com"));
+
+ EXPECT_TRUE(StaticShouldRedirect("mydigipass.com"));
+ EXPECT_FALSE(StaticShouldRedirect("foo.mydigipass.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.mydigipass.com"));
+ EXPECT_FALSE(StaticShouldRedirect("foo.www.mydigipass.com"));
+ EXPECT_TRUE(StaticShouldRedirect("developer.mydigipass.com"));
+ EXPECT_FALSE(StaticShouldRedirect("foo.developer.mydigipass.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.developer.mydigipass.com"));
+ EXPECT_FALSE(StaticShouldRedirect("foo.www.developer.mydigipass.com"));
+ EXPECT_TRUE(StaticShouldRedirect("sandbox.mydigipass.com"));
+ EXPECT_FALSE(StaticShouldRedirect("foo.sandbox.mydigipass.com"));
+ EXPECT_TRUE(StaticShouldRedirect("www.sandbox.mydigipass.com"));
+ EXPECT_FALSE(StaticShouldRedirect("foo.www.sandbox.mydigipass.com"));
- EXPECT_TRUE(ShouldRedirect("crypto.cat"));
- EXPECT_FALSE(ShouldRedirect("foo.crypto.cat"));
+ EXPECT_TRUE(StaticShouldRedirect("crypto.cat"));
+ EXPECT_FALSE(StaticShouldRedirect("foo.crypto.cat"));
- EXPECT_TRUE(ShouldRedirect("bigshinylock.minazo.net"));
- EXPECT_TRUE(ShouldRedirect("foo.bigshinylock.minazo.net"));
+ EXPECT_TRUE(StaticShouldRedirect("bigshinylock.minazo.net"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.bigshinylock.minazo.net"));
- EXPECT_TRUE(ShouldRedirect("crate.io"));
- EXPECT_TRUE(ShouldRedirect("foo.crate.io"));
+ EXPECT_TRUE(StaticShouldRedirect("crate.io"));
+ EXPECT_TRUE(StaticShouldRedirect("foo.crate.io"));
- EXPECT_TRUE(HasPublicKeyPins("www.twitter.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("www.twitter.com"));
}
TEST_F(TransportSecurityStateTest, LongNames) {
@@ -482,59 +489,62 @@ TEST_F(TransportSecurityStateTest, LongNames) {
"WaveletIdDomainAndBlipBlipid";
TransportSecurityState::DomainState domain_state;
// Just checks that we don't hit a NOTREACHED.
- EXPECT_FALSE(state.GetDomainState(kLongName, true, &domain_state));
+ EXPECT_FALSE(state.GetStaticDomainState(kLongName, true, &domain_state));
+ EXPECT_FALSE(state.GetDynamicDomainState(kLongName, &domain_state));
}
TEST_F(TransportSecurityStateTest, BuiltinCertPins) {
TransportSecurityState state;
TransportSecurityState::DomainState domain_state;
- EXPECT_TRUE(state.GetDomainState("chrome.google.com", true, &domain_state));
- EXPECT_TRUE(HasPublicKeyPins("chrome.google.com"));
+ EXPECT_TRUE(
+ state.GetStaticDomainState("chrome.google.com", true, &domain_state));
+ EXPECT_TRUE(HasStaticPublicKeyPins("chrome.google.com"));
HashValueVector hashes;
+ std::string failure_log;
// Checks that a built-in list does exist.
- EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes));
- EXPECT_FALSE(HasPublicKeyPins("www.paypal.com"));
-
- EXPECT_TRUE(HasPublicKeyPins("docs.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("1.docs.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("sites.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("drive.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("spreadsheets.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("wallet.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("checkout.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("appengine.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("market.android.com"));
- EXPECT_TRUE(HasPublicKeyPins("encrypted.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("accounts.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("profiles.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("mail.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("chatenabled.mail.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("talkgadget.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("hostedtalkgadget.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("talk.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("plus.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("groups.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("apis.google.com"));
-
- EXPECT_TRUE(HasPublicKeyPins("ssl.gstatic.com"));
- EXPECT_TRUE(HasPublicKeyPins("gstatic.com"));
- EXPECT_TRUE(HasPublicKeyPins("www.gstatic.com"));
- EXPECT_TRUE(HasPublicKeyPins("ssl.google-analytics.com"));
- EXPECT_TRUE(HasPublicKeyPins("www.googleplex.com"));
+ EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes, &failure_log));
+ EXPECT_FALSE(HasStaticPublicKeyPins("www.paypal.com"));
+
+ EXPECT_TRUE(HasStaticPublicKeyPins("docs.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("1.docs.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("sites.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("drive.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("spreadsheets.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("wallet.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("checkout.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("appengine.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("market.android.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("encrypted.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("accounts.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("profiles.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("mail.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("chatenabled.mail.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("talkgadget.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("hostedtalkgadget.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("talk.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("plus.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("groups.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("apis.google.com"));
+
+ EXPECT_TRUE(HasStaticPublicKeyPins("ssl.gstatic.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("gstatic.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("www.gstatic.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("ssl.google-analytics.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("www.googleplex.com"));
// Disabled in order to help track down pinning failures --agl
- EXPECT_TRUE(HasPublicKeyPins("twitter.com"));
- EXPECT_FALSE(HasPublicKeyPins("foo.twitter.com"));
- EXPECT_TRUE(HasPublicKeyPins("www.twitter.com"));
- EXPECT_TRUE(HasPublicKeyPins("api.twitter.com"));
- EXPECT_TRUE(HasPublicKeyPins("oauth.twitter.com"));
- EXPECT_TRUE(HasPublicKeyPins("mobile.twitter.com"));
- EXPECT_TRUE(HasPublicKeyPins("dev.twitter.com"));
- EXPECT_TRUE(HasPublicKeyPins("business.twitter.com"));
- EXPECT_TRUE(HasPublicKeyPins("platform.twitter.com"));
- EXPECT_TRUE(HasPublicKeyPins("si0.twimg.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("twitter.com"));
+ EXPECT_FALSE(HasStaticPublicKeyPins("foo.twitter.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("www.twitter.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("api.twitter.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("oauth.twitter.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("mobile.twitter.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("dev.twitter.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("business.twitter.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("platform.twitter.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("si0.twimg.com"));
}
static bool AddHash(const std::string& type_and_base64,
@@ -576,54 +586,56 @@ TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) {
TransportSecurityState state;
TransportSecurityState::DomainState domain_state;
- EXPECT_TRUE(state.GetDomainState("blog.torproject.org", true, &domain_state));
+ EXPECT_TRUE(
+ state.GetStaticDomainState("blog.torproject.org", true, &domain_state));
EXPECT_TRUE(domain_state.HasPublicKeyPins());
- EXPECT_TRUE(domain_state.CheckPublicKeyPins(good_hashes));
- EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes));
+ std::string failure_log;
+ EXPECT_TRUE(domain_state.CheckPublicKeyPins(good_hashes, &failure_log));
+ EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes, &failure_log));
}
TEST_F(TransportSecurityStateTest, OptionalHSTSCertPins) {
TransportSecurityState state;
TransportSecurityState::DomainState domain_state;
- EXPECT_FALSE(ShouldRedirect("www.google-analytics.com"));
-
- EXPECT_FALSE(HasPublicKeyPins("www.google-analytics.com", false));
- EXPECT_TRUE(HasPublicKeyPins("www.google-analytics.com"));
- EXPECT_TRUE(HasPublicKeyPins("google.com"));
- EXPECT_TRUE(HasPublicKeyPins("www.google.com"));
- EXPECT_TRUE(HasPublicKeyPins("mail-attachment.googleusercontent.com"));
- EXPECT_TRUE(HasPublicKeyPins("www.youtube.com"));
- EXPECT_TRUE(HasPublicKeyPins("i.ytimg.com"));
- EXPECT_TRUE(HasPublicKeyPins("googleapis.com"));
- EXPECT_TRUE(HasPublicKeyPins("ajax.googleapis.com"));
- EXPECT_TRUE(HasPublicKeyPins("googleadservices.com"));
- EXPECT_TRUE(HasPublicKeyPins("pagead2.googleadservices.com"));
- EXPECT_TRUE(HasPublicKeyPins("googlecode.com"));
- EXPECT_TRUE(HasPublicKeyPins("kibbles.googlecode.com"));
- EXPECT_TRUE(HasPublicKeyPins("appspot.com"));
- EXPECT_TRUE(HasPublicKeyPins("googlesyndication.com"));
- EXPECT_TRUE(HasPublicKeyPins("doubleclick.net"));
- EXPECT_TRUE(HasPublicKeyPins("ad.doubleclick.net"));
- EXPECT_FALSE(HasPublicKeyPins("learn.doubleclick.net"));
- EXPECT_TRUE(HasPublicKeyPins("a.googlegroups.com"));
- EXPECT_FALSE(HasPublicKeyPins("a.googlegroups.com", false));
+ EXPECT_FALSE(StaticShouldRedirect("www.google-analytics.com"));
+
+ EXPECT_FALSE(HasStaticPublicKeyPins("www.google-analytics.com", false));
+ EXPECT_TRUE(HasStaticPublicKeyPins("www.google-analytics.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("www.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("mail-attachment.googleusercontent.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("www.youtube.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("i.ytimg.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("googleapis.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("ajax.googleapis.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("googleadservices.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("pagead2.googleadservices.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("googlecode.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("kibbles.googlecode.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("appspot.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("googlesyndication.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("doubleclick.net"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("ad.doubleclick.net"));
+ EXPECT_FALSE(HasStaticPublicKeyPins("learn.doubleclick.net"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("a.googlegroups.com"));
+ EXPECT_FALSE(HasStaticPublicKeyPins("a.googlegroups.com", false));
}
TEST_F(TransportSecurityStateTest, OverrideBuiltins) {
- EXPECT_TRUE(HasPublicKeyPins("google.com"));
- EXPECT_FALSE(ShouldRedirect("google.com"));
- EXPECT_FALSE(ShouldRedirect("www.google.com"));
+ EXPECT_TRUE(HasStaticPublicKeyPins("google.com"));
+ EXPECT_FALSE(StaticShouldRedirect("google.com"));
+ EXPECT_FALSE(StaticShouldRedirect("www.google.com"));
TransportSecurityState state;
TransportSecurityState::DomainState domain_state;
const base::Time current_time(base::Time::Now());
const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
- domain_state.upgrade_expiry = expiry;
+ domain_state.sts.expiry = expiry;
EnableHost(&state, "www.google.com", domain_state);
- EXPECT_TRUE(state.GetDomainState("www.google.com", true, &domain_state));
+ EXPECT_TRUE(state.GetDynamicDomainState("www.google.com", &domain_state));
}
TEST_F(TransportSecurityStateTest, GooglePinnedProperties) {
diff --git a/chromium/net/http/url_security_manager_win.cc b/chromium/net/http/url_security_manager_win.cc
index cb3c66ef0f0..4e2d938963e 100644
--- a/chromium/net/http/url_security_manager_win.cc
+++ b/chromium/net/http/url_security_manager_win.cc
@@ -53,7 +53,7 @@ bool URLSecurityManagerWin::CanUseDefaultCredentials(
if (!const_cast<URLSecurityManagerWin*>(this)->EnsureSystemSecurityManager())
return false;
- std::wstring url_w = ASCIIToWide(auth_origin.spec());
+ std::wstring url_w = base::ASCIIToWide(auth_origin.spec());
DWORD policy = 0;
HRESULT hr;
hr = security_manager_->ProcessUrlAction(url_w.c_str(),