summaryrefslogtreecommitdiff
path: root/chromium/content/browser/loader
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-01-25 11:39:07 +0100
committerOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2016-01-25 15:20:42 +0000
commit6c91641271e536ffaa88a1dff5127e42ee99a91e (patch)
tree703d9dd49602377ddc90cbf886aad37913f2496b /chromium/content/browser/loader
parentb145b7fafd36f0c260d6a768c81fc14e32578099 (diff)
downloadqtwebengine-chromium-6c91641271e536ffaa88a1dff5127e42ee99a91e.tar.gz
BASELINE: Update Chromium to 49.0.2623.23
Also adds missing printing sources. Change-Id: I3726b8f0c7d6751c9fc846096c571fadca7108cd Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Diffstat (limited to 'chromium/content/browser/loader')
-rw-r--r--chromium/content/browser/loader/async_resource_handler.cc12
-rw-r--r--chromium/content/browser/loader/async_resource_handler.h5
-rw-r--r--chromium/content/browser/loader/async_resource_handler_browsertest.cc27
-rw-r--r--chromium/content/browser/loader/async_revalidation_driver.cc274
-rw-r--r--chromium/content/browser/loader/async_revalidation_driver.h104
-rw-r--r--chromium/content/browser/loader/async_revalidation_driver_unittest.cc397
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager.cc191
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager.h107
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager_browsertest.cc220
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager_unittest.cc554
-rw-r--r--chromium/content/browser/loader/certificate_resource_handler.cc111
-rw-r--r--chromium/content/browser/loader/certificate_resource_handler.h72
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler.cc72
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler.h9
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc278
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.cc4
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.h2
-rw-r--r--chromium/content/browser/loader/global_routing_id.h7
-rw-r--r--chromium/content/browser/loader/layered_resource_handler.cc6
-rw-r--r--chromium/content/browser/loader/mime_type_resource_handler.cc27
-rw-r--r--chromium/content/browser/loader/mime_type_resource_handler.h1
-rw-r--r--chromium/content/browser/loader/mime_type_resource_handler_unittest.cc26
-rw-r--r--chromium/content/browser/loader/navigation_resource_throttle.cc141
-rw-r--r--chromium/content/browser/loader/navigation_resource_throttle.h3
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.cc12
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.h3
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_factory.h1
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc23
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.h2
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.cc25
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.h3
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_unittest.cc20
-rw-r--r--chromium/content/browser/loader/power_save_block_resource_throttle.cc7
-rw-r--r--chromium/content/browser/loader/power_save_block_resource_throttle.h7
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.cc12
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.h2
-rw-r--r--chromium/content/browser/loader/resource_buffer.h2
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc305
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc321
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h33
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc159
-rw-r--r--chromium/content/browser/loader/resource_loader.cc43
-rw-r--r--chromium/content/browser/loader/resource_loader.h1
-rw-r--r--chromium/content/browser/loader/resource_loader_unittest.cc60
-rw-r--r--chromium/content/browser/loader/resource_message_delegate.h2
-rw-r--r--chromium/content/browser/loader/resource_message_filter.cc6
-rw-r--r--chromium/content/browser/loader/resource_message_filter.h14
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc79
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h18
-rw-r--r--chromium/content/browser/loader/resource_scheduler.cc90
-rw-r--r--chromium/content/browser/loader/resource_scheduler.h7
-rw-r--r--chromium/content/browser/loader/resource_scheduler_filter.cc8
-rw-r--r--chromium/content/browser/loader/resource_scheduler_unittest.cc135
-rw-r--r--chromium/content/browser/loader/stream_resource_handler.h1
-rw-r--r--chromium/content/browser/loader/sync_resource_handler.h4
-rw-r--r--chromium/content/browser/loader/temporary_file_stream.cc4
-rw-r--r--chromium/content/browser/loader/temporary_file_stream_unittest.cc6
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler.cc6
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler.h2
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.cc32
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder_unittest.cc13
61 files changed, 3434 insertions, 684 deletions
diff --git a/chromium/content/browser/loader/async_resource_handler.cc b/chromium/content/browser/loader/async_resource_handler.cc
index 2eace36852e..df08aa79537 100644
--- a/chromium/content/browser/loader/async_resource_handler.cc
+++ b/chromium/content/browser/loader/async_resource_handler.cc
@@ -11,6 +11,7 @@
#include "base/containers/hash_tables.h"
#include "base/debug/alias.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/memory/shared_memory.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
@@ -144,10 +145,10 @@ void AsyncResourceHandler::ReportUploadProgress() {
if (progress.position() == last_upload_position_)
return; // No progress made since last time.
- const uint64 kHalfPercentIncrements = 200;
+ const uint64_t kHalfPercentIncrements = 200;
const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000);
- uint64 amt_since_last = progress.position() - last_upload_position_;
+ uint64_t amt_since_last = progress.position() - last_upload_position_;
TimeDelta time_since_last = TimeTicks::Now() - last_upload_ticks_;
bool is_finished = (progress.size() == progress.position());
@@ -318,6 +319,9 @@ bool AsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
int size;
if (!buffer_->ShareToProcess(filter->PeerHandle(), &handle, &size))
return false;
+
+ // TODO(erikchen): Temporary debugging. http://crbug.com/527588.
+ CHECK_LE(size, kBufferSize);
filter->Send(new ResourceMsg_SetDataBuffer(
GetRequestID(), handle, size, filter->peer_pid()));
sent_first_data_msg_ = true;
@@ -329,6 +333,10 @@ bool AsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
int encoded_data_length = current_transfer_size - reported_transfer_size_;
reported_transfer_size_ = current_transfer_size;
+ // TODO(erikchen): Temporary debugging. http://crbug.com/527588.
+ CHECK_LE(data_offset, kBufferSize);
+
+ filter->Send(new ResourceMsg_DataReceivedDebug(GetRequestID(), data_offset));
filter->Send(new ResourceMsg_DataReceived(
GetRequestID(), data_offset, bytes_read, encoded_data_length));
++pending_data_count_;
diff --git a/chromium/content/browser/loader/async_resource_handler.h b/chromium/content/browser/loader/async_resource_handler.h
index 9d460963d52..d7f70c2b504 100644
--- a/chromium/content/browser/loader/async_resource_handler.h
+++ b/chromium/content/browser/loader/async_resource_handler.h
@@ -5,8 +5,11 @@
#ifndef CONTENT_BROWSER_LOADER_ASYNC_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_ASYNC_RESOURCE_HANDLER_H_
+#include <stdint.h>
+
#include <string>
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/timer/timer.h"
#include "content/browser/loader/resource_handler.h"
@@ -78,7 +81,7 @@ class AsyncResourceHandler : public ResourceHandler,
bool sent_received_response_msg_;
bool sent_first_data_msg_;
- uint64 last_upload_position_;
+ uint64_t last_upload_position_;
bool waiting_for_upload_progress_ack_;
base::TimeTicks last_upload_ticks_;
base::RepeatingTimer progress_timer_;
diff --git a/chromium/content/browser/loader/async_resource_handler_browsertest.cc b/chromium/content/browser/loader/async_resource_handler_browsertest.cc
index cb48a231115..456c31a544f 100644
--- a/chromium/content/browser/loader/async_resource_handler_browsertest.cc
+++ b/chromium/content/browser/loader/async_resource_handler_browsertest.cc
@@ -4,11 +4,14 @@
#include "content/browser/loader/async_resource_handler.h"
+#include <stddef.h>
#include <string>
+#include <utility>
#include "base/format_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -28,8 +31,10 @@ const char kRedirectPostPath[] = "/redirect";
// ThreadSanitizer is too slow to perform the full upload, so tests
// using that build get an easier test which might not show two distinct
-// progress events. See crbug.com/526985.
-#if defined(THREAD_SANITIZER)
+// progress events. See crbug.com/526985. In addition, OSX buildbots have
+// experienced slowdowns on this test (crbug.com/548819), give them the easier
+// test too.
+#if defined(THREAD_SANITIZER) || defined(OS_MACOSX)
const size_t kPayloadSize = 1062882; // 2*3^12
#else
const size_t kPayloadSize = 28697814; // 2*3^15
@@ -44,14 +49,14 @@ scoped_ptr<net::test_server::HttpResponse> HandlePostAndRedirectURLs(
base::CompareCase::SENSITIVE)) {
http_response->set_code(net::HTTP_TEMPORARY_REDIRECT);
http_response->AddCustomHeader("Location", kPostPath);
- EXPECT_EQ(request.content.length(), kPayloadSize);;
- return http_response.Pass();
- } else if(base::StartsWith(request.relative_url, kPostPath,
- base::CompareCase::SENSITIVE)) {
+ EXPECT_EQ(request.content.length(), kPayloadSize);
+ return std::move(http_response);
+ } else if (base::StartsWith(request.relative_url, kPostPath,
+ base::CompareCase::SENSITIVE)) {
http_response->set_content("hello");
http_response->set_content_type("text/plain");
EXPECT_EQ(request.content.length(), kPayloadSize);
- return http_response.Pass();
+ return std::move(http_response);
} else {
return scoped_ptr<net::test_server::HttpResponse>();
}
@@ -63,8 +68,8 @@ class AsyncResourceHandlerBrowserTest : public ContentBrowserTest {
};
IN_PROC_BROWSER_TEST_F(AsyncResourceHandlerBrowserTest, UploadProgress) {
- net::test_server::EmbeddedTestServer* test_server = embedded_test_server();
- ASSERT_TRUE(test_server->InitializeAndWaitUntilReady());
+ net::EmbeddedTestServer* test_server = embedded_test_server();
+ ASSERT_TRUE(test_server->Start());
test_server->RegisterRequestHandler(
base::Bind(&HandlePostAndRedirectURLs, kPostPath));
@@ -83,8 +88,8 @@ IN_PROC_BROWSER_TEST_F(AsyncResourceHandlerBrowserTest, UploadProgress) {
IN_PROC_BROWSER_TEST_F(AsyncResourceHandlerBrowserTest,
UploadProgressRedirect) {
- net::test_server::EmbeddedTestServer* test_server = embedded_test_server();
- ASSERT_TRUE(test_server->InitializeAndWaitUntilReady());
+ net::EmbeddedTestServer* test_server = embedded_test_server();
+ ASSERT_TRUE(test_server->Start());
test_server->RegisterRequestHandler(
base::Bind(&HandlePostAndRedirectURLs, kRedirectPostPath));
diff --git a/chromium/content/browser/loader/async_revalidation_driver.cc b/chromium/content/browser/loader/async_revalidation_driver.cc
new file mode 100644
index 00000000000..3c5d45bc13b
--- /dev/null
+++ b/chromium/content/browser/loader/async_revalidation_driver.cc
@@ -0,0 +1,274 @@
+// Copyright 2015 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 "content/browser/loader/async_revalidation_driver.h"
+
+#include <utility>
+
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/sparse_histogram.h"
+#include "base/single_thread_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request_status.h"
+
+namespace content {
+
+namespace {
+// This matches the maximum allocation size of AsyncResourceHandler.
+const int kReadBufSize = 32 * 1024;
+
+// The time to wait for a response. Since this includes the time taken to
+// connect, this has been set to match the connect timeout
+// kTransportConnectJobTimeoutInSeconds.
+const int kResponseTimeoutInSeconds = 240; // 4 minutes.
+
+// This value should not be too large, as this request may be tying up a socket
+// that could be used for something better. However, if it is too small, the
+// cache entry will be truncated for no good reason.
+// TODO(ricea): Find a more scientific way to set this timeout.
+const int kReadTimeoutInSeconds = 30;
+} // namespace
+
+AsyncRevalidationDriver::AsyncRevalidationDriver(
+ scoped_ptr<net::URLRequest> request,
+ scoped_ptr<ResourceThrottle> throttle,
+ const base::Closure& completion_callback)
+ : request_(std::move(request)),
+ throttle_(std::move(throttle)),
+ completion_callback_(completion_callback),
+ weak_ptr_factory_(this) {
+ request_->set_delegate(this);
+ throttle_->set_controller(this);
+}
+
+AsyncRevalidationDriver::~AsyncRevalidationDriver() {}
+
+void AsyncRevalidationDriver::StartRequest() {
+ // Give the handler a chance to delay the URLRequest from being started.
+ bool defer_start = false;
+ throttle_->WillStartRequest(&defer_start);
+
+ if (defer_start) {
+ RecordDefer();
+ } else {
+ StartRequestInternal();
+ }
+}
+
+void AsyncRevalidationDriver::OnReceivedRedirect(
+ net::URLRequest* request,
+ const net::RedirectInfo& redirect_info,
+ bool* defer) {
+ DCHECK_EQ(request_.get(), request);
+
+ // The async revalidation should not follow redirects, because caching is
+ // a property of an individual HTTP resource.
+ DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec();
+ CancelRequestInternal(net::ERR_ABORTED, RESULT_GOT_REDIRECT);
+}
+
+void AsyncRevalidationDriver::OnAuthRequired(
+ net::URLRequest* request,
+ net::AuthChallengeInfo* auth_info) {
+ DCHECK_EQ(request_.get(), request);
+ // This error code doesn't have exactly the right semantics, but it should
+ // be sufficient to narrow down the problem in net logs.
+ CancelRequestInternal(net::ERR_ACCESS_DENIED, RESULT_AUTH_FAILED);
+}
+
+void AsyncRevalidationDriver::OnBeforeNetworkStart(net::URLRequest* request,
+ bool* defer) {
+ DCHECK_EQ(request_.get(), request);
+
+ // Verify that the ResourceScheduler does not defer here.
+ throttle_->WillStartUsingNetwork(defer);
+ DCHECK(!*defer);
+
+ // Start the response timer. This use of base::Unretained() is guaranteed safe
+ // by the semantics of base::OneShotTimer.
+ timer_.Start(FROM_HERE,
+ base::TimeDelta::FromSeconds(kResponseTimeoutInSeconds),
+ base::Bind(&AsyncRevalidationDriver::OnTimeout,
+ base::Unretained(this), RESULT_RESPONSE_TIMEOUT));
+}
+
+void AsyncRevalidationDriver::OnResponseStarted(net::URLRequest* request) {
+ DCHECK_EQ(request_.get(), request);
+
+ DVLOG(1) << "OnResponseStarted: " << request_->url().spec();
+
+ // We have the response. No need to wait any longer.
+ timer_.Stop();
+
+ if (!request_->status().is_success()) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AsyncRevalidation.ResponseError",
+ -request_->status().ToNetError());
+ ResponseCompleted(RESULT_NET_ERROR);
+ // |this| may be deleted after this point.
+ return;
+ }
+
+ const net::HttpResponseInfo& response_info = request_->response_info();
+ if (!response_info.response_time.is_null() && response_info.was_cached) {
+ // The cached entry was revalidated. No need to read it in.
+ ResponseCompleted(RESULT_REVALIDATED);
+ // |this| may be deleted after this point.
+ return;
+ }
+
+ bool defer = false;
+ throttle_->WillProcessResponse(&defer);
+ DCHECK(!defer);
+
+ // Set up the timer for reading the body. This use of base::Unretained() is
+ // guaranteed safe by the semantics of base::OneShotTimer.
+ timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kReadTimeoutInSeconds),
+ base::Bind(&AsyncRevalidationDriver::OnTimeout,
+ base::Unretained(this), RESULT_BODY_TIMEOUT));
+ StartReading(false); // Read the first chunk.
+}
+
+void AsyncRevalidationDriver::OnReadCompleted(net::URLRequest* request,
+ int bytes_read) {
+ // request_ could be NULL if a timeout happened while OnReadCompleted() was
+ // queued to run asynchronously.
+ if (!request_)
+ return;
+ DCHECK_EQ(request_.get(), request);
+ DCHECK(!is_deferred_);
+ DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\""
+ << " bytes_read = " << bytes_read;
+
+ // bytes_read == 0 is EOF.
+ if (bytes_read == 0) {
+ ResponseCompleted(RESULT_LOADED);
+ return;
+ }
+ // bytes_read == -1 is an error.
+ if (bytes_read == -1 || !request_->status().is_success()) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AsyncRevalidation.ReadError",
+ -request_->status().ToNetError());
+ ResponseCompleted(RESULT_READ_ERROR);
+ // |this| may be deleted after this point.
+ return;
+ }
+
+ DCHECK_GT(bytes_read, 0);
+ StartReading(true); // Read the next chunk.
+}
+
+void AsyncRevalidationDriver::Resume() {
+ DCHECK(is_deferred_);
+ DCHECK(request_);
+ is_deferred_ = false;
+ request_->LogUnblocked();
+ StartRequestInternal();
+}
+
+void AsyncRevalidationDriver::Cancel() {
+ NOTREACHED();
+}
+
+void AsyncRevalidationDriver::CancelAndIgnore() {
+ NOTREACHED();
+}
+
+void AsyncRevalidationDriver::CancelWithError(int error_code) {
+ NOTREACHED();
+}
+
+void AsyncRevalidationDriver::StartRequestInternal() {
+ DCHECK(request_);
+ DCHECK(!request_->is_pending());
+
+ request_->Start();
+}
+
+void AsyncRevalidationDriver::CancelRequestInternal(
+ int error,
+ AsyncRevalidationResult result) {
+ DVLOG(1) << "CancelRequestInternal: " << request_->url().spec();
+
+ // Set the error code since this will be reported to the NetworkDelegate and
+ // recorded in the NetLog.
+ request_->CancelWithError(error);
+
+ // The ResourceScheduler needs to be able to examine the request when the
+ // ResourceThrottle is destroyed, so delete it first.
+ throttle_.reset();
+
+ // Destroy the request so that it doesn't try to send an asynchronous
+ // notification of completion.
+ request_.reset();
+
+ // Cancel timer to prevent OnTimeout() being called.
+ timer_.Stop();
+
+ ResponseCompleted(result);
+ // |this| may deleted after this point.
+}
+
+void AsyncRevalidationDriver::StartReading(bool is_continuation) {
+ int bytes_read = 0;
+ ReadMore(&bytes_read);
+
+ // If IO is pending, wait for the URLRequest to call OnReadCompleted.
+ if (request_->status().is_io_pending())
+ return;
+
+ if (!is_continuation || bytes_read <= 0) {
+ OnReadCompleted(request_.get(), bytes_read);
+ } else {
+ // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
+ // thread in case the URLRequest can provide data synchronously.
+ scoped_refptr<base::SingleThreadTaskRunner> single_thread_task_runner =
+ base::ThreadTaskRunnerHandle::Get();
+ single_thread_task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(&AsyncRevalidationDriver::OnReadCompleted,
+ weak_ptr_factory_.GetWeakPtr(), request_.get(), bytes_read));
+ }
+}
+
+void AsyncRevalidationDriver::ReadMore(int* bytes_read) {
+ DCHECK(!is_deferred_);
+
+ if (!read_buffer_)
+ read_buffer_ = new net::IOBuffer(kReadBufSize);
+
+ timer_.Reset();
+ request_->Read(read_buffer_.get(), kReadBufSize, bytes_read);
+
+ // No need to check the return value here as we'll detect errors by
+ // inspecting the URLRequest's status.
+}
+
+void AsyncRevalidationDriver::ResponseCompleted(
+ AsyncRevalidationResult result) {
+ DVLOG(1) << "ResponseCompleted: "
+ << (request_ ? request_->url().spec() : "(request deleted)")
+ << "result = " << result;
+ UMA_HISTOGRAM_ENUMERATION("Net.AsyncRevalidation.Result", result, RESULT_MAX);
+ DCHECK(!completion_callback_.is_null());
+ base::ResetAndReturn(&completion_callback_).Run();
+ // |this| may be deleted after this point.
+}
+
+void AsyncRevalidationDriver::OnTimeout(AsyncRevalidationResult result) {
+ CancelRequestInternal(net::ERR_TIMED_OUT, result);
+}
+
+void AsyncRevalidationDriver::RecordDefer() {
+ request_->LogBlockedBy(throttle_->GetNameForLogging());
+ DCHECK(!is_deferred_);
+ is_deferred_ = true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/async_revalidation_driver.h b/chromium/content/browser/loader/async_revalidation_driver.h
new file mode 100644
index 00000000000..b96e06ebd5c
--- /dev/null
+++ b/chromium/content/browser/loader/async_revalidation_driver.h
@@ -0,0 +1,104 @@
+// Copyright 2015 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 CONTENT_BROWSER_LOADER_ASYNC_REVALIDATION_DRIVER_H_
+#define CONTENT_BROWSER_LOADER_ASYNC_REVALIDATION_DRIVER_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/resource_controller.h"
+#include "content/public/browser/resource_throttle.h"
+#include "net/base/io_buffer.h"
+#include "net/url_request/url_request.h"
+
+namespace net {
+class HttpCache;
+}
+
+namespace content {
+
+// This class is responsible for driving the URLRequest for an async
+// revalidation. It is passed an instance of ResourceThrottle created by
+// content::ResourceScheduler to perform throttling on the request.
+class CONTENT_EXPORT AsyncRevalidationDriver : public net::URLRequest::Delegate,
+ public ResourceController {
+ public:
+ // |completion_callback| is guaranteed to be called on completion,
+ // regardless of success or failure.
+ AsyncRevalidationDriver(scoped_ptr<net::URLRequest> request,
+ scoped_ptr<ResourceThrottle> throttle,
+ const base::Closure& completion_callback);
+ ~AsyncRevalidationDriver() override;
+
+ void StartRequest();
+
+ private:
+ // This enum is logged as histogram "Net.AsyncRevalidation.Result". Only add
+ // new entries at the end and update histograms.xml to match.
+ enum AsyncRevalidationResult {
+ RESULT_LOADED,
+ RESULT_REVALIDATED,
+ RESULT_NET_ERROR,
+ RESULT_READ_ERROR,
+ RESULT_GOT_REDIRECT,
+ RESULT_AUTH_FAILED,
+ RESULT_RESPONSE_TIMEOUT,
+ RESULT_BODY_TIMEOUT,
+ RESULT_MAX
+ };
+
+ // net::URLRequest::Delegate implementation:
+ void OnReceivedRedirect(net::URLRequest* request,
+ const net::RedirectInfo& redirect_info,
+ bool* defer) override;
+ void OnAuthRequired(net::URLRequest* request,
+ net::AuthChallengeInfo* info) override;
+ void OnBeforeNetworkStart(net::URLRequest* request, bool* defer) override;
+ void OnResponseStarted(net::URLRequest* request) override;
+ void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
+
+ // ResourceController implementation:
+ void Resume() override;
+
+ // For simplicity, this class assumes that ResourceScheduler never cancels
+ // requests, and so these three methods are never called.
+ void Cancel() override;
+ void CancelAndIgnore() override;
+ void CancelWithError(int error_code) override;
+
+ // Internal methods.
+ void StartRequestInternal();
+ void CancelRequestInternal(int error, AsyncRevalidationResult result);
+ void StartReading(bool is_continuation);
+ void ReadMore(int* bytes_read);
+ // Logs the result histogram, then calls and clears |completion_callback_|.
+ void ResponseCompleted(AsyncRevalidationResult result);
+ void OnTimeout(AsyncRevalidationResult result);
+ void RecordDefer();
+
+ bool is_deferred_ = false;
+
+ scoped_refptr<net::IOBuffer> read_buffer_;
+ base::OneShotTimer timer_;
+
+ scoped_ptr<net::URLRequest> request_;
+ scoped_ptr<ResourceThrottle> throttle_;
+
+ base::Closure completion_callback_;
+
+ base::WeakPtrFactory<AsyncRevalidationDriver> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncRevalidationDriver);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_ASYNC_REVALIDATION_DRIVER_H_
diff --git a/chromium/content/browser/loader/async_revalidation_driver_unittest.cc b/chromium/content/browser/loader/async_revalidation_driver_unittest.cc
new file mode 100644
index 00000000000..1f5a7e4b1f0
--- /dev/null
+++ b/chromium/content/browser/loader/async_revalidation_driver_unittest.cc
@@ -0,0 +1,397 @@
+// Copyright 2015 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 "content/browser/loader/async_revalidation_driver.h"
+
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "content/public/browser/client_certificate_delegate.h"
+#include "content/public/common/content_client.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/test_content_browser_client.h"
+#include "ipc/ipc_message.h"
+#include "net/base/net_errors.h"
+#include "net/base/network_delegate_impl.h"
+#include "net/base/request_priority.h"
+#include "net/ssl/ssl_cert_request_info.h"
+#include "net/url_request/url_request_job_factory.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "net/url_request/url_request_status.h"
+#include "net/url_request/url_request_test_job.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+// Dummy implementation of ResourceThrottle, an instance of which is needed to
+// initialize AsyncRevalidationDriver.
+class ResourceThrottleStub : public ResourceThrottle {
+ public:
+ ResourceThrottleStub() {}
+
+ // If true, defers the request in WillStartRequest.
+ void set_defer_request_on_will_start_request(
+ bool defer_request_on_will_start_request) {
+ defer_request_on_will_start_request_ = defer_request_on_will_start_request;
+ }
+
+ // ResourceThrottler implementation:
+ void WillStartRequest(bool* defer) override {
+ *defer = defer_request_on_will_start_request_;
+ }
+
+ const char* GetNameForLogging() const override {
+ return "ResourceThrottleStub";
+ }
+
+ private:
+ bool defer_request_on_will_start_request_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceThrottleStub);
+};
+
+// There are multiple layers of boilerplate needed to use a URLRequestTestJob
+// subclass. Subclasses of AsyncRevalidationDriverTest can use
+// BindCreateProtocolHandlerCallback() to bypass most of that boilerplate.
+using CreateProtocolHandlerCallback =
+ base::Callback<scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>()>;
+
+template <typename T>
+CreateProtocolHandlerCallback BindCreateProtocolHandlerCallback() {
+ static_assert(std::is_base_of<net::URLRequestJob, T>::value,
+ "Template argument to BindCreateProtocolHandlerCallback() must "
+ "be a subclass of URLRequestJob.");
+
+ class TemplatedProtocolHandler
+ : public net::URLRequestJobFactory::ProtocolHandler {
+ public:
+ static scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> Create() {
+ return make_scoped_ptr(new TemplatedProtocolHandler());
+ }
+
+ // URLRequestJobFactory::ProtocolHandler implementation:
+ net::URLRequestJob* MaybeCreateJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ return new T(request, network_delegate);
+ }
+ };
+
+ return base::Bind(&TemplatedProtocolHandler::Create);
+}
+
+// An implementation of NetworkDelegate that captures the status of the last
+// URLRequest to be destroyed.
+class StatusCapturingNetworkDelegate : public net::NetworkDelegateImpl {
+ public:
+ const net::URLRequestStatus& last_status() { return last_status_; }
+
+ private:
+ // net::NetworkDelegate implementation.
+ void OnURLRequestDestroyed(net::URLRequest* request) override {
+ last_status_ = request->status();
+ }
+
+ net::URLRequestStatus last_status_;
+};
+
+class AsyncRevalidationDriverTest : public testing::Test {
+ protected:
+ // Constructor for test fixtures that subclass this one.
+ AsyncRevalidationDriverTest(
+ const CreateProtocolHandlerCallback& create_protocol_handler_callback)
+ : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ create_protocol_handler_callback_(create_protocol_handler_callback),
+ raw_ptr_resource_throttle_(nullptr),
+ raw_ptr_request_(nullptr) {
+ test_url_request_context_.set_job_factory(&job_factory_);
+ test_url_request_context_.set_network_delegate(&network_delegate_);
+ }
+
+ // Constructor for tests that use this fixture directly.
+ AsyncRevalidationDriverTest()
+ : AsyncRevalidationDriverTest(
+ base::Bind(net::URLRequestTestJob::CreateProtocolHandler)) {}
+
+ bool async_revalidation_complete_called() const {
+ return async_revalidation_complete_called_;
+ }
+
+ const net::URLRequestStatus& last_status() {
+ return network_delegate_.last_status();
+ }
+
+ void SetUpAsyncRevalidationDriverWithRequestToUrl(const GURL& url) {
+ scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
+ url, net::DEFAULT_PRIORITY, nullptr /* delegate */));
+ raw_ptr_request_ = request.get();
+ raw_ptr_resource_throttle_ = new ResourceThrottleStub();
+ // This use of base::Unretained() is safe because |driver_|, and the closure
+ // passed to it, will be destroyed before this object is.
+ driver_.reset(new AsyncRevalidationDriver(
+ std::move(request), make_scoped_ptr(raw_ptr_resource_throttle_),
+ base::Bind(&AsyncRevalidationDriverTest::OnAsyncRevalidationComplete,
+ base::Unretained(this))));
+ }
+
+ void SetUpAsyncRevalidationDriverWithDefaultRequest() {
+ SetUpAsyncRevalidationDriverWithRequestToUrl(
+ net::URLRequestTestJob::test_url_1());
+ }
+
+ void SetUp() override {
+ job_factory_.SetProtocolHandler("test",
+ create_protocol_handler_callback_.Run());
+ SetUpAsyncRevalidationDriverWithDefaultRequest();
+ }
+
+ void OnAsyncRevalidationComplete() {
+ EXPECT_FALSE(async_revalidation_complete_called_);
+ async_revalidation_complete_called_ = true;
+ driver_.reset();
+ }
+
+ TestBrowserThreadBundle thread_bundle_;
+ net::URLRequestJobFactoryImpl job_factory_;
+ net::TestURLRequestContext test_url_request_context_;
+ StatusCapturingNetworkDelegate network_delegate_;
+ CreateProtocolHandlerCallback create_protocol_handler_callback_;
+
+ // The AsyncRevalidationDriver owns the URLRequest and the ResourceThrottle.
+ ResourceThrottleStub* raw_ptr_resource_throttle_;
+ net::URLRequest* raw_ptr_request_;
+ scoped_ptr<AsyncRevalidationDriver> driver_;
+ bool async_revalidation_complete_called_ = false;
+};
+
+TEST_F(AsyncRevalidationDriverTest, NormalRequestCompletes) {
+ driver_->StartRequest();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+// Verifies that request that should be deferred at start is deferred.
+TEST_F(AsyncRevalidationDriverTest, DeferOnStart) {
+ raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);
+
+ driver_->StartRequest();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(raw_ptr_request_->is_pending());
+ EXPECT_FALSE(async_revalidation_complete_called());
+}
+
+// Verifies that resuming a deferred request works. Assumes that DeferOnStart
+// passes.
+TEST_F(AsyncRevalidationDriverTest, ResumeDeferredRequestWorks) {
+ raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);
+
+ driver_->StartRequest();
+ base::RunLoop().RunUntilIdle();
+
+ ResourceController* driver_as_resource_controller = driver_.get();
+ driver_as_resource_controller->Resume();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+// Verifies that redirects are not followed.
+TEST_F(AsyncRevalidationDriverTest, RedirectsAreNotFollowed) {
+ SetUpAsyncRevalidationDriverWithRequestToUrl(
+ net::URLRequestTestJob::test_url_redirect_to_url_2());
+
+ driver_->StartRequest();
+ while (net::URLRequestTestJob::ProcessOnePendingMessage())
+ base::RunLoop().RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(last_status().is_success());
+ EXPECT_EQ(net::ERR_ABORTED, last_status().error());
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+// A mock URLRequestJob which simulates an SSL client auth request.
+class MockClientCertURLRequestJob : public net::URLRequestTestJob {
+ public:
+ MockClientCertURLRequestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
+ : net::URLRequestTestJob(request, network_delegate, true),
+ weak_factory_(this) {}
+
+ // net::URLRequestTestJob implementation:
+ void Start() override {
+ scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
+ new net::SSLCertRequestInfo);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
+ weak_factory_.GetWeakPtr(), cert_request_info));
+ }
+
+ void ContinueWithCertificate(
+ net::X509Certificate* cert,
+ net::SSLPrivateKey* client_private_key) override {
+ ADD_FAILURE() << "Certificate supplied.";
+ }
+
+ void Kill() override {
+ weak_factory_.InvalidateWeakPtrs();
+ URLRequestJob::Kill();
+ }
+
+ private:
+ base::WeakPtrFactory<MockClientCertURLRequestJob> weak_factory_;
+};
+
+class AsyncRevalidationDriverClientCertTest
+ : public AsyncRevalidationDriverTest {
+ protected:
+ AsyncRevalidationDriverClientCertTest()
+ : AsyncRevalidationDriverTest(
+ BindCreateProtocolHandlerCallback<MockClientCertURLRequestJob>()) {}
+};
+
+// Test browser client that causes the test to fail if SelectClientCertificate()
+// is called. Automatically sets itself as the browser client when constructed
+// and restores the old browser client in the destructor.
+class ScopedDontSelectCertificateBrowserClient
+ : public TestContentBrowserClient {
+ public:
+ ScopedDontSelectCertificateBrowserClient() {
+ old_client_ = SetBrowserClientForTesting(this);
+ }
+
+ ~ScopedDontSelectCertificateBrowserClient() override {
+ SetBrowserClientForTesting(old_client_);
+ }
+
+ void SelectClientCertificate(
+ WebContents* web_contents,
+ net::SSLCertRequestInfo* cert_request_info,
+ scoped_ptr<ClientCertificateDelegate> delegate) override {
+ ADD_FAILURE() << "SelectClientCertificate was called.";
+ }
+
+ private:
+ ContentBrowserClient* old_client_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedDontSelectCertificateBrowserClient);
+};
+
+// Verifies that async revalidation requests do not attempt to provide client
+// certificates.
+TEST_F(AsyncRevalidationDriverClientCertTest, RequestRejected) {
+ // Ensure that SelectClientCertificate is not called during this test.
+ ScopedDontSelectCertificateBrowserClient test_client;
+
+ // Start the request and wait for it to pause.
+ driver_->StartRequest();
+
+ // Because TestBrowserThreadBundle only uses one real thread, this is
+ // sufficient to ensure that tasks posted to the "UI thread" have run.
+ base::RunLoop().RunUntilIdle();
+
+ // Check that the request aborted.
+ EXPECT_FALSE(last_status().is_success());
+ EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, last_status().error());
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+// A mock URLRequestJob which simulates an SSL certificate error.
+class MockSSLErrorURLRequestJob : public net::URLRequestTestJob {
+ public:
+ MockSSLErrorURLRequestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
+ : net::URLRequestTestJob(request, network_delegate, true),
+ weak_factory_(this) {}
+
+ // net::URLRequestTestJob implementation:
+ void Start() override {
+ // This SSLInfo isn't really valid, but it is good enough for testing.
+ net::SSLInfo ssl_info;
+ ssl_info.SetCertError(net::ERR_CERT_DATE_INVALID);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&MockSSLErrorURLRequestJob::NotifySSLCertificateError,
+ weak_factory_.GetWeakPtr(), ssl_info, false));
+ }
+
+ void ContinueDespiteLastError() override {
+ ADD_FAILURE() << "ContinueDespiteLastError called.";
+ }
+
+ private:
+ base::WeakPtrFactory<MockSSLErrorURLRequestJob> weak_factory_;
+};
+
+class AsyncRevalidationDriverSSLErrorTest : public AsyncRevalidationDriverTest {
+ protected:
+ AsyncRevalidationDriverSSLErrorTest()
+ : AsyncRevalidationDriverTest(
+ BindCreateProtocolHandlerCallback<MockSSLErrorURLRequestJob>()) {}
+};
+
+// Verifies that async revalidation requests do not attempt to recover from SSL
+// certificate errors.
+TEST_F(AsyncRevalidationDriverSSLErrorTest, RequestWithSSLErrorRejected) {
+ // Start the request and wait for it to pause.
+ driver_->StartRequest();
+ base::RunLoop().RunUntilIdle();
+
+ // Check that the request has been aborted.
+ EXPECT_FALSE(last_status().is_success());
+ EXPECT_EQ(net::ERR_ABORTED, last_status().error());
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+// A URLRequestTestJob that sets |request_time| and |was_cached| on their
+// response_info, and causes the test to fail if Read() is called.
+class FromCacheURLRequestJob : public net::URLRequestTestJob {
+ public:
+ FromCacheURLRequestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
+ : net::URLRequestTestJob(request, network_delegate, true) {}
+
+ void GetResponseInfo(net::HttpResponseInfo* info) override {
+ URLRequestTestJob::GetResponseInfo(info);
+ info->request_time = base::Time::Now();
+ info->was_cached = true;
+ }
+
+ int ReadRawData(net::IOBuffer* buf, int buf_size) override {
+ ADD_FAILURE() << "ReadRawData() was called.";
+ return URLRequestTestJob::ReadRawData(buf, buf_size);
+ }
+
+ private:
+ ~FromCacheURLRequestJob() override {}
+
+ DISALLOW_COPY_AND_ASSIGN(FromCacheURLRequestJob);
+};
+
+class AsyncRevalidationDriverFromCacheTest
+ : public AsyncRevalidationDriverTest {
+ protected:
+ AsyncRevalidationDriverFromCacheTest()
+ : AsyncRevalidationDriverTest(
+ BindCreateProtocolHandlerCallback<FromCacheURLRequestJob>()) {}
+};
+
+TEST_F(AsyncRevalidationDriverFromCacheTest,
+ CacheNotReadOnSuccessfulRevalidation) {
+ driver_->StartRequest();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(async_revalidation_complete_called());
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/loader/async_revalidation_manager.cc b/chromium/content/browser/loader/async_revalidation_manager.cc
new file mode 100644
index 00000000000..aaaeb68ab83
--- /dev/null
+++ b/chromium/content/browser/loader/async_revalidation_manager.cc
@@ -0,0 +1,191 @@
+// Copyright 2015 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 "content/browser/loader/async_revalidation_manager.h"
+
+#include <tuple>
+#include <utility>
+
+#include "base/logging.h"
+#include "content/browser/loader/async_revalidation_driver.h"
+#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/loader/resource_scheduler.h"
+#include "content/common/resource_messages.h"
+#include "content/public/browser/resource_throttle.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_transaction_factory.h"
+#include "net/http/http_util.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "url/gurl.h"
+
+namespace content {
+
+AsyncRevalidationManager::AsyncRevalidationKey::AsyncRevalidationKey(
+ const ResourceContext* resource_context,
+ const net::HttpCache* http_cache,
+ const GURL& url)
+ : resource_context(resource_context),
+ http_cache(http_cache),
+ url_key(net::HttpUtil::SpecForRequest(url)) {}
+
+AsyncRevalidationManager::AsyncRevalidationKey::AsyncRevalidationKey(
+ const ResourceContext* resource_context)
+ : resource_context(resource_context), http_cache(nullptr), url_key() {}
+
+AsyncRevalidationManager::AsyncRevalidationKey::~AsyncRevalidationKey() {}
+
+bool AsyncRevalidationManager::AsyncRevalidationKey::LessThan::operator()(
+ const AsyncRevalidationKey& lhs,
+ const AsyncRevalidationKey& rhs) const {
+ return std::tie(lhs.resource_context, lhs.http_cache, lhs.url_key) <
+ std::tie(rhs.resource_context, rhs.http_cache, rhs.url_key);
+}
+
+AsyncRevalidationManager::AsyncRevalidationManager() {}
+
+AsyncRevalidationManager::~AsyncRevalidationManager() {
+ DCHECK(in_progress_.empty());
+}
+
+void AsyncRevalidationManager::BeginAsyncRevalidation(
+ const net::URLRequest& for_request,
+ ResourceScheduler* scheduler) {
+ DCHECK_EQ(for_request.url_chain().size(), 1u);
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(&for_request);
+ DCHECK(info);
+ if (!info->filter()) {
+ // The child has gone away and we can no longer get ResourceContext and
+ // URLRequestContext to perform async revalidation.
+ // This can happen in the following cases, ordered from bad to not-so-bad
+ //
+ // 1. PlzNavigate (but enabling PlzNavigate automatically disables
+ // stale-while-revalidate; see crbug.com/561609)
+ // 2. <link rel=prefetch> may read a stale cache entry without a
+ // revalidation being performed if the original renderer goes away. This
+ // is a lost optimisation opportunity.
+ //
+ // Not an issue:
+ // 1. Implicit downloads. This method is called before
+ // MimeTypeResourceHandler calls set_is_download, so the renderer process
+ // must still exist for the request not to have been canceled.
+ // 2. Explicit downloads (ie. started via "Save As"). These never use
+ // stale-while-revalidate.
+ // 3. Non-PlzNavigate navigations between renderers. The old renderer
+ // still exists when this method is called.
+ // 4. <a ping>, navigation.sendBeacon() and Content-Security-Policy reports
+ // are POST requests, so they never use stale-while-revalidate.
+ //
+ // TODO(ricea): Resolve these lifetime issues. crbug.com/561591
+ return;
+ }
+
+ ResourceContext* resource_context = nullptr;
+ net::URLRequestContext* request_context = nullptr;
+
+ // The embedder of //content needs to ensure that the URLRequestContext object
+ // remains valid until after the ResourceContext object is destroyed.
+ info->filter()->GetContexts(info->GetResourceType(), info->GetOriginPID(),
+ &resource_context, &request_context);
+
+ AsyncRevalidationKey async_revalidation_key(
+ resource_context, request_context->http_transaction_factory()->GetCache(),
+ for_request.url());
+ std::pair<AsyncRevalidationMap::iterator, bool> insert_result =
+ in_progress_.insert(AsyncRevalidationMap::value_type(
+ async_revalidation_key, scoped_ptr<AsyncRevalidationDriver>()));
+ if (!insert_result.second) {
+ // A matching async revalidation is already in progress for this cache; we
+ // don't need another one.
+ return;
+ }
+
+ net::HttpRequestHeaders headers;
+ headers.AddHeadersFromString(info->original_headers());
+
+ // Construct the request.
+ scoped_ptr<net::URLRequest> new_request = request_context->CreateRequest(
+ for_request.url(), net::MINIMUM_PRIORITY, nullptr);
+
+ new_request->set_method(for_request.method());
+ new_request->set_first_party_for_cookies(
+ for_request.first_party_for_cookies());
+ new_request->set_initiator(for_request.initiator());
+ new_request->set_first_party_url_policy(for_request.first_party_url_policy());
+
+ new_request->SetReferrer(for_request.referrer());
+ new_request->set_referrer_policy(for_request.referrer_policy());
+
+ new_request->SetExtraRequestHeaders(headers);
+
+ // Remove LOAD_SUPPORT_ASYNC_REVALIDATION and LOAD_MAIN_FRAME flags.
+ // Also remove things which shouldn't have been there to begin with,
+ // and unrecognised flags.
+ int load_flags =
+ for_request.load_flags() &
+ (net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_BYPASS_PROXY |
+ net::LOAD_VERIFY_EV_CERT | net::LOAD_DO_NOT_SEND_COOKIES |
+ net::LOAD_DO_NOT_SEND_AUTH_DATA | net::LOAD_MAYBE_USER_GESTURE |
+ net::LOAD_DO_NOT_USE_EMBEDDED_IDENTITY);
+ new_request->SetLoadFlags(load_flags);
+
+ // These values would be -1 if the request was created by PlzNavigate. This
+ // would cause the async revalidation to start immediately.
+ // stale-while-revalidate is disabled when PlzNavigate is enabled
+ // to prevent this and other issues. See crbug.com/561610.
+ int child_id = info->GetChildID();
+ int route_id = info->GetRouteID();
+
+ scoped_ptr<ResourceThrottle> throttle =
+ scheduler->ScheduleRequest(child_id, route_id, false, new_request.get());
+
+ // AsyncRevalidationDriver does not outlive its entry in |in_progress_|,
+ // so the iterator and |this| may be passed to base::Bind directly.
+ insert_result.first->second.reset(new AsyncRevalidationDriver(
+ std::move(new_request), std::move(throttle),
+ base::Bind(&AsyncRevalidationManager::OnAsyncRevalidationComplete,
+ base::Unretained(this), insert_result.first)));
+ insert_result.first->second->StartRequest();
+}
+
+void AsyncRevalidationManager::CancelAsyncRevalidationsForResourceContext(
+ ResourceContext* resource_context) {
+ // |resource_context| is the first part of the key, so elements to be
+ // cancelled are contiguous in the map.
+ AsyncRevalidationKey partial_key(resource_context);
+ for (auto it = in_progress_.lower_bound(partial_key);
+ it != in_progress_.end() &&
+ it->first.resource_context == resource_context;) {
+ it = in_progress_.erase(it);
+ }
+}
+
+bool AsyncRevalidationManager::QualifiesForAsyncRevalidation(
+ const ResourceHostMsg_Request& request) {
+ if (request.load_flags &
+ (net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
+ net::LOAD_VALIDATE_CACHE | net::LOAD_PREFERRING_CACHE |
+ net::LOAD_ONLY_FROM_CACHE | net::LOAD_IGNORE_LIMITS |
+ net::LOAD_PREFETCH)) {
+ return false;
+ }
+ if (request.method != "GET")
+ return false;
+ // A GET request should not have a body.
+ if (request.request_body.get())
+ return false;
+ if (!request.url.SchemeIsHTTPOrHTTPS())
+ return false;
+
+ return true;
+}
+
+void AsyncRevalidationManager::OnAsyncRevalidationComplete(
+ AsyncRevalidationMap::iterator it) {
+ in_progress_.erase(it);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/async_revalidation_manager.h b/chromium/content/browser/loader/async_revalidation_manager.h
new file mode 100644
index 00000000000..1070ea9c8bc
--- /dev/null
+++ b/chromium/content/browser/loader/async_revalidation_manager.h
@@ -0,0 +1,107 @@
+// Copyright 2015 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 CONTENT_BROWSER_LOADER_ASYNC_REVALIDATION_MANAGER_H_
+#define CONTENT_BROWSER_LOADER_ASYNC_REVALIDATION_MANAGER_H_
+
+#include <map>
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+
+class GURL;
+struct ResourceHostMsg_Request;
+
+namespace net {
+class URLRequest;
+class HttpCache;
+}
+
+namespace content {
+
+class AsyncRevalidationDriver;
+class ResourceContext;
+class ResourceScheduler;
+
+// One instance of this class manages all active AsyncRevalidationDriver objects
+// for all profiles. It is created by and owned by
+// ResourceDispatcherHostImpl. It also implements the creation of a new
+// net::URLRequest and AsyncRevalidationDriver from an existing net::URLRequest
+// that has had the stale-while-revalidate algorithm applied to it.
+class AsyncRevalidationManager {
+ public:
+ AsyncRevalidationManager();
+ ~AsyncRevalidationManager();
+
+ // Starts an async revalidation by copying |for_request|. |scheduler| must
+ // remain valid until this object is destroyed.
+ void BeginAsyncRevalidation(const net::URLRequest& for_request,
+ ResourceScheduler* scheduler);
+
+ // Cancel all pending async revalidations that use ResourceContext.
+ void CancelAsyncRevalidationsForResourceContext(
+ ResourceContext* resource_context);
+
+ static bool QualifiesForAsyncRevalidation(
+ const ResourceHostMsg_Request& request);
+
+ private:
+ // The key of the map of pending async revalidations. This key has a distinct
+ // value for every in-progress async revalidation. It is used to avoid
+ // duplicate async revalidations, and also to cancel affected async
+ // revalidations when a ResourceContext is removed.
+ //
+ // Request headers are intentionally not included in the key for simplicity,
+ // as they usually don't affect caching.
+ //
+ // TODO(ricea): Behave correctly in cases where the request headers do make a
+ // difference. crbug.com/567721
+ struct AsyncRevalidationKey {
+ AsyncRevalidationKey(const ResourceContext* resource_context,
+ const net::HttpCache* http_cache,
+ const GURL& url);
+
+ // Create a prefix key that is used to match all of the
+ // AsyncRevalidationDrivers using |resource_context| in the map.
+ explicit AsyncRevalidationKey(const ResourceContext* resource_context);
+
+ // The key for a map needs to be copyable.
+ AsyncRevalidationKey(const AsyncRevalidationKey& rhs) = default;
+ ~AsyncRevalidationKey();
+
+ // No operator= is generated because the struct members are immutable.
+
+ // |resource_context| and |http_cache| are never dereferenced; they are only
+ // compared to other values.
+ const ResourceContext* const resource_context;
+
+ // There are multiple independent HttpCache objects per ResourceContext.
+ const net::HttpCache* const http_cache;
+
+ // Derived from the url via net::HttpUtil::SpecForRequest().
+ const std::string url_key;
+
+ struct LessThan {
+ bool operator()(const AsyncRevalidationKey& lhs,
+ const AsyncRevalidationKey& rhs) const;
+ };
+ };
+
+ using AsyncRevalidationMap = std::map<AsyncRevalidationKey,
+ scoped_ptr<AsyncRevalidationDriver>,
+ AsyncRevalidationKey::LessThan>;
+
+ void OnAsyncRevalidationComplete(AsyncRevalidationMap::iterator it);
+
+ // Map of AsyncRevalidationDriver instances that are currently in-flight:
+ // either waiting to be scheduled or active on the network.
+ AsyncRevalidationMap in_progress_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncRevalidationManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_ASYNC_REVALIDATION_MANAGER_H_
diff --git a/chromium/content/browser/loader/async_revalidation_manager_browsertest.cc b/chromium/content/browser/loader/async_revalidation_manager_browsertest.cc
new file mode 100644
index 00000000000..f7999431b42
--- /dev/null
+++ b/chromium/content/browser/loader/async_revalidation_manager_browsertest.cc
@@ -0,0 +1,220 @@
+// Copyright 2015 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 <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+using net::test_server::HttpResponse;
+using net::test_server::HttpRequest;
+using net::test_server::BasicHttpResponse;
+
+const char kCountedHtmlPath[] = "/counted.html";
+const char kCookieHtmlPath[] = "/cookie.html";
+
+class AsyncRevalidationManagerBrowserTest : public ContentBrowserTest {
+ protected:
+ AsyncRevalidationManagerBrowserTest() {}
+ ~AsyncRevalidationManagerBrowserTest() override {}
+
+ void SetUp() override {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+ ContentBrowserTest::SetUp();
+ }
+
+ void SetUpOnMainThread() override {
+ embedded_test_server()->StartAcceptingConnections();
+ }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch("enable-stale-while-revalidate");
+ }
+
+ base::RunLoop* run_loop() { return &run_loop_; }
+ int requests_counted() const { return requests_counted_; }
+
+ // This method lacks diagnostics for the failure case because TitleWatcher
+ // will just wait until the test times out if |expected_title| does not
+ // appear.
+ bool TitleBecomes(const GURL& url, const std::string& expected_title) {
+ base::string16 expected_title16(base::ASCIIToUTF16(expected_title));
+ TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
+ NavigateToURL(shell(), url);
+ return title_watcher.WaitAndGetTitle() == expected_title16;
+ }
+
+ void RegisterCountingRequestHandler() {
+ embedded_test_server()->RegisterRequestHandler(base::Bind(
+ &AsyncRevalidationManagerBrowserTest::CountingRequestHandler, this));
+ }
+
+ void RegisterCookieRequestHandler() {
+ embedded_test_server()->RegisterRequestHandler(base::Bind(
+ &AsyncRevalidationManagerBrowserTest::CookieRequestHandler, this));
+ }
+
+ private:
+ // A request handler which increases the number in the title tag on every
+ // request.
+ scoped_ptr<HttpResponse> CountingRequestHandler(const HttpRequest& request) {
+ if (request.relative_url != kCountedHtmlPath)
+ return nullptr;
+
+ int version = ++requests_counted_;
+
+ scoped_ptr<BasicHttpResponse> http_response(StaleWhileRevalidateHeaders());
+ http_response->set_content(
+ base::StringPrintf("<title>Version %d</title>", version));
+
+ // The second time this handler is run is the async revalidation. Tests can
+ // use this for synchronisation.
+ if (version == 2)
+ run_loop_.Quit();
+ return std::move(http_response);
+ }
+
+ // A request handler which increases a cookie value on every request.
+ scoped_ptr<HttpResponse> CookieRequestHandler(const HttpRequest& request) {
+ static const char kHtml[] =
+ "<script>\n"
+ "var intervalId;\n"
+ "function checkCookie() {\n"
+ " if (document.cookie.search(/version=2/) != -1) {\n"
+ " clearInterval(intervalId);\n"
+ " document.title = \"PASS\";\n"
+ " }\n"
+ "}\n"
+ "intervalId = setInterval(checkCookie, 10);\n"
+ "</script>\n"
+ "<title>Loaded</title>\n";
+
+ if (request.relative_url != kCookieHtmlPath)
+ return nullptr;
+
+ int version = ++requests_counted_;
+
+ scoped_ptr<BasicHttpResponse> http_response(StaleWhileRevalidateHeaders());
+ http_response->AddCustomHeader("Set-Cookie",
+ base::StringPrintf("version=%d", version));
+ http_response->set_content(kHtml);
+
+ return std::move(http_response);
+ }
+
+ // Generate the standard response headers common to all request handlers.
+ scoped_ptr<BasicHttpResponse> StaleWhileRevalidateHeaders() {
+ scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
+ http_response->set_code(net::HTTP_OK);
+ http_response->set_content_type("text/html; charset=utf-8");
+ http_response->AddCustomHeader("Cache-Control",
+ "max-age=0, stale-while-revalidate=86400");
+ // A validator is needed for revalidations, and hence
+ // stale-while-revalidate, to work.
+ std::string etag = base::StringPrintf(
+ "\"AsyncRevalidationManagerBrowserTest%d\"", requests_counted_);
+ http_response->AddCustomHeader("ETag", etag);
+ return http_response;
+ }
+
+ base::RunLoop run_loop_;
+ int requests_counted_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncRevalidationManagerBrowserTest);
+};
+
+// Verify that the "Cache-Control: stale-while-revalidate" directive correctly
+// triggers an async revalidation.
+IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest,
+ StaleWhileRevalidateIsApplied) {
+ RegisterCountingRequestHandler();
+ GURL url(embedded_test_server()->GetURL(kCountedHtmlPath));
+
+ EXPECT_TRUE(TitleBecomes(url, "Version 1"));
+
+ // The first request happens synchronously.
+ EXPECT_EQ(1, requests_counted());
+
+ // Force the renderer to be destroyed so that the Blink cache doesn't
+ // interfere with the result.
+ NavigateToURL(shell(), GURL("about:blank"));
+
+ // Load the page again. We should get the stale version from the cache.
+ EXPECT_TRUE(TitleBecomes(url, "Version 1"));
+
+ // Wait for the async revalidation to complete.
+ run_loop()->Run();
+ EXPECT_EQ(2, requests_counted());
+}
+
+// The fresh cache entry must become visible once the async revalidation request
+// has been sent.
+IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest, CacheIsUpdated) {
+ using base::ASCIIToUTF16;
+ RegisterCountingRequestHandler();
+ GURL url(embedded_test_server()->GetURL(kCountedHtmlPath));
+
+ EXPECT_TRUE(TitleBecomes(url, "Version 1"));
+
+ // Reset the renderer cache.
+ NavigateToURL(shell(), GURL("about:blank"));
+
+ // Load the page again. We should get the stale version from the cache.
+ EXPECT_TRUE(TitleBecomes(url, "Version 1"));
+
+ // Wait for the async revalidation request to be processed by the
+ // EmbeddedTestServer.
+ run_loop()->Run();
+
+ // Reset the renderer cache.
+ NavigateToURL(shell(), GURL("about:blank"));
+
+ // Since the async revalidation request has been sent, the cache can no
+ // longer return the stale contents.
+ EXPECT_TRUE(TitleBecomes(url, "Version 2"));
+}
+
+// When the asynchronous revalidation arrives, any cookies it contains must be
+// applied immediately.
+IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest,
+ CookieSetAsynchronously) {
+ RegisterCookieRequestHandler();
+ GURL url(embedded_test_server()->GetURL(kCookieHtmlPath));
+
+ // Set cookie to version=1
+ NavigateToURL(shell(), url);
+
+ // Reset render cache.
+ NavigateToURL(shell(), GURL("about:blank"));
+
+ // The page will load from the cache, then when the async revalidation
+ // completes the cookie will update.
+ EXPECT_TRUE(TitleBecomes(url, "PASS"));
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/loader/async_revalidation_manager_unittest.cc b/chromium/content/browser/loader/async_revalidation_manager_unittest.cc
new file mode 100644
index 00000000000..d0ec206130d
--- /dev/null
+++ b/chromium/content/browser/loader/async_revalidation_manager_unittest.cc
@@ -0,0 +1,554 @@
+// Copyright 2015 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 "content/browser/loader/async_revalidation_manager.h"
+
+#include <deque>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/shared_memory_handle.h"
+#include "base/pickle.h"
+#include "base/run_loop.h"
+#include "base/strings/string_util.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/loader/resource_message_filter.h"
+#include "content/common/child_process_host_impl.h"
+#include "content/common/resource_messages.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/common/appcache_info.h"
+#include "content/public/common/process_type.h"
+#include "content/public/common/resource_type.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "ipc/ipc_param_traits.h"
+#include "net/base/load_flags.h"
+#include "net/base/network_delegate.h"
+#include "net/http/http_util.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_job.h"
+#include "net/url_request/url_request_job_factory.h"
+#include "net/url_request/url_request_test_job.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/page_transition_types.h"
+#include "url/gurl.h"
+#include "url/url_constants.h"
+
+namespace content {
+
+namespace {
+
+// This class is a variation on URLRequestTestJob that
+// returns ERR_IO_PENDING before every read, not just the first one.
+class URLRequestTestDelayedCompletionJob : public net::URLRequestTestJob {
+ public:
+ URLRequestTestDelayedCompletionJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const std::string& response_headers,
+ const std::string& response_data)
+ : net::URLRequestTestJob(request,
+ network_delegate,
+ response_headers,
+ response_data,
+ false) {}
+
+ private:
+ bool NextReadAsync() override { return true; }
+};
+
+// A URLRequestJob implementation which sets the |async_revalidation_required|
+// flag on the HttpResponseInfo object to true if the request has the
+// LOAD_SUPPORT_ASYNC_REVALIDATION flag.
+class AsyncRevalidationRequiredURLRequestTestJob
+ : public net::URLRequestTestJob {
+ public:
+ AsyncRevalidationRequiredURLRequestTestJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
+ : URLRequestTestJob(request,
+ network_delegate,
+ net::URLRequestTestJob::test_headers(),
+ std::string(),
+ false) {}
+
+ void GetResponseInfo(net::HttpResponseInfo* info) override {
+ URLRequestTestJob::GetResponseInfo(info);
+ if (request()->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION)
+ info->async_revalidation_required = true;
+ }
+};
+
+// A URLRequestJob implementation which serves a redirect and sets the
+// |async_revalidation_required| flag on the HttpResponseInfo object to true if
+// the request has the LOAD_SUPPORT_ASYNC_REVALIDATION flag.
+class RedirectAndRevalidateURLRequestTestJob : public net::URLRequestTestJob {
+ public:
+ RedirectAndRevalidateURLRequestTestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
+ : URLRequestTestJob(request,
+ network_delegate,
+ CreateRedirectHeaders(),
+ std::string(),
+ false) {}
+
+ void GetResponseInfo(net::HttpResponseInfo* info) override {
+ URLRequestTestJob::GetResponseInfo(info);
+ if (request()->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION)
+ info->async_revalidation_required = true;
+ }
+
+ private:
+ static std::string CreateRedirectHeaders() {
+ static const char kRedirectHeaders[] =
+ "HTTP/1.1 302 MOVED\n"
+ "Location: http://example.com/async-revalidate/from-redirect\n"
+ "\n";
+ return std::string(kRedirectHeaders, arraysize(kRedirectHeaders) - 1);
+ }
+};
+
+class TestURLRequestJobFactory : public net::URLRequestJobFactory {
+ public:
+ TestURLRequestJobFactory() = default;
+
+ // Sets the contents of the response. |headers| should have "\n" as line
+ // breaks and end in "\n\n".
+ void SetResponse(const std::string& headers, const std::string& data) {
+ response_headers_ = headers;
+ response_data_ = data;
+ }
+
+ net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
+ const std::string& scheme,
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ std::string path = request->url().path();
+ if (base::StartsWith(path, "/async-revalidate",
+ base::CompareCase::SENSITIVE)) {
+ return new AsyncRevalidationRequiredURLRequestTestJob(request,
+ network_delegate);
+ }
+ if (base::StartsWith(path, "/redirect", base::CompareCase::SENSITIVE)) {
+ return new RedirectAndRevalidateURLRequestTestJob(request,
+ network_delegate);
+ }
+ return new URLRequestTestDelayedCompletionJob(
+ request, network_delegate, response_headers_, response_data_);
+ }
+
+ net::URLRequestJob* MaybeInterceptRedirect(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const GURL& location) const override {
+ return nullptr;
+ }
+
+ net::URLRequestJob* MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ return nullptr;
+ }
+
+ bool IsHandledProtocol(const std::string& scheme) const override {
+ // If non-standard schemes need to be tested in future it will be
+ // necessary to call ChildProcessSecurityPolicyImpl::
+ // RegisterWebSafeScheme() for them.
+ return scheme == url::kHttpScheme || scheme == url::kHttpsScheme;
+ }
+
+ bool IsHandledURL(const GURL& url) const override {
+ return IsHandledProtocol(url.scheme());
+ }
+
+ bool IsSafeRedirectTarget(const GURL& location) const override {
+ return false;
+ }
+
+ private:
+ std::string response_headers_;
+ std::string response_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestURLRequestJobFactory);
+};
+
+// On Windows, ResourceMsg_SetDataBuffer supplies a HANDLE which is not
+// automatically released.
+//
+// See ResourceDispatcher::ReleaseResourcesInDataMessage.
+//
+// TODO(ricea): Maybe share this implementation with
+// resource_dispatcher_host_unittest.cc.
+void ReleaseHandlesInMessage(const IPC::Message& message) {
+ if (message.type() == ResourceMsg_SetDataBuffer::ID) {
+ base::PickleIterator iter(message);
+ int request_id;
+ CHECK(iter.ReadInt(&request_id));
+ base::SharedMemoryHandle shm_handle;
+ if (IPC::ParamTraits<base::SharedMemoryHandle>::Read(&message, &iter,
+ &shm_handle)) {
+ if (base::SharedMemory::IsHandleValid(shm_handle))
+ base::SharedMemory::CloseHandle(shm_handle);
+ }
+ }
+}
+
+// This filter just deletes any messages that are sent through it.
+class BlackholeFilter : public ResourceMessageFilter {
+ public:
+ explicit BlackholeFilter(ResourceContext* resource_context)
+ : ResourceMessageFilter(
+ ChildProcessHostImpl::GenerateChildProcessUniqueId(),
+ PROCESS_TYPE_RENDERER,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ base::Bind(&BlackholeFilter::GetContexts, base::Unretained(this))),
+ resource_context_(resource_context) {
+ ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id());
+ }
+
+ bool Send(IPC::Message* msg) override {
+ scoped_ptr<IPC::Message> take_ownership(msg);
+ ReleaseHandlesInMessage(*msg);
+ return true;
+ }
+
+ private:
+ ~BlackholeFilter() override {
+ ChildProcessSecurityPolicyImpl::GetInstance()->Remove(child_id());
+ }
+
+ void GetContexts(ResourceType resource_type,
+ int origin_pid,
+ ResourceContext** resource_context,
+ net::URLRequestContext** request_context) {
+ *resource_context = resource_context_;
+ *request_context = resource_context_->GetRequestContext();
+ }
+
+ ResourceContext* resource_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlackholeFilter);
+};
+
+ResourceHostMsg_Request CreateResourceRequest(const char* method,
+ ResourceType type,
+ const GURL& url) {
+ ResourceHostMsg_Request request;
+ request.method = std::string(method);
+ request.url = url;
+ request.first_party_for_cookies = url; // Bypass third-party cookie blocking.
+ request.referrer_policy = blink::WebReferrerPolicyDefault;
+ request.load_flags = 0;
+ request.origin_pid = 0;
+ request.resource_type = type;
+ request.request_context = 0;
+ request.appcache_host_id = kAppCacheNoHostId;
+ request.download_to_file = false;
+ request.should_reset_appcache = false;
+ request.is_main_frame = true;
+ request.parent_is_main_frame = false;
+ request.parent_render_frame_id = -1;
+ request.transition_type = ui::PAGE_TRANSITION_LINK;
+ request.allow_download = true;
+ return request;
+}
+
+class AsyncRevalidationManagerTest : public ::testing::Test {
+ protected:
+ AsyncRevalidationManagerTest(
+ scoped_ptr<net::TestNetworkDelegate> network_delegate)
+ : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ network_delegate_(std::move(network_delegate)) {
+ browser_context_.reset(new TestBrowserContext());
+ BrowserContext::EnsureResourceContextInitialized(browser_context_.get());
+ base::RunLoop().RunUntilIdle();
+ ResourceContext* resource_context = browser_context_->GetResourceContext();
+ filter_ = new BlackholeFilter(resource_context);
+ net::URLRequestContext* request_context =
+ resource_context->GetRequestContext();
+ job_factory_.reset(new TestURLRequestJobFactory);
+ request_context->set_job_factory(job_factory_.get());
+ request_context->set_network_delegate(network_delegate_.get());
+ host_.EnableStaleWhileRevalidateForTesting();
+ }
+
+ AsyncRevalidationManagerTest()
+ : AsyncRevalidationManagerTest(
+ make_scoped_ptr(new net::TestNetworkDelegate)) {}
+
+ void TearDown() override {
+ host_.CancelRequestsForProcess(filter_->child_id());
+ host_.Shutdown();
+ host_.CancelRequestsForContext(browser_context_->GetResourceContext());
+ browser_context_.reset();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void SetResponse(const std::string& headers, const std::string& data) {
+ job_factory_->SetResponse(headers, data);
+ }
+
+ // Creates a request using the current test object as the filter and
+ // SubResource as the resource type.
+ void MakeTestRequest(int render_view_id, int request_id, const GURL& url) {
+ ResourceHostMsg_Request request =
+ CreateResourceRequest("GET", RESOURCE_TYPE_SUB_RESOURCE, url);
+ ResourceHostMsg_RequestResource msg(render_view_id, request_id, request);
+ host_.OnMessageReceived(msg, filter_.get());
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void EnsureSchemeIsAllowed(const std::string& scheme) {
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ if (!policy->IsWebSafeScheme(scheme))
+ policy->RegisterWebSafeScheme(scheme);
+ }
+
+ content::TestBrowserThreadBundle thread_bundle_;
+ scoped_ptr<TestBrowserContext> browser_context_;
+ scoped_ptr<TestURLRequestJobFactory> job_factory_;
+ scoped_refptr<BlackholeFilter> filter_;
+ scoped_ptr<net::TestNetworkDelegate> network_delegate_;
+ ResourceDispatcherHostImpl host_;
+};
+
+TEST_F(AsyncRevalidationManagerTest, SupportsAsyncRevalidation) {
+ SetResponse(net::URLRequestTestJob::test_headers(), "delay complete");
+ MakeTestRequest(0, 1, GURL("http://example.com/baz"));
+
+ net::URLRequest* url_request(
+ host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
+ ASSERT_TRUE(url_request);
+
+ EXPECT_TRUE(url_request->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION);
+}
+
+TEST_F(AsyncRevalidationManagerTest, AsyncRevalidationNotSupportedForPOST) {
+ SetResponse(net::URLRequestTestJob::test_headers(), "delay complete");
+ // Create POST request.
+ ResourceHostMsg_Request request = CreateResourceRequest(
+ "POST", RESOURCE_TYPE_SUB_RESOURCE, GURL("http://example.com/baz.php"));
+ ResourceHostMsg_RequestResource msg(0, 1, request);
+ host_.OnMessageReceived(msg, filter_.get());
+ base::RunLoop().RunUntilIdle();
+
+ net::URLRequest* url_request(
+ host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
+ ASSERT_TRUE(url_request);
+
+ EXPECT_FALSE(url_request->load_flags() &
+ net::LOAD_SUPPORT_ASYNC_REVALIDATION);
+}
+
+TEST_F(AsyncRevalidationManagerTest,
+ AsyncRevalidationNotSupportedAfterRedirect) {
+ static const char kRedirectHeaders[] =
+ "HTTP/1.1 302 MOVED\n"
+ "Location: http://example.com/var\n"
+ "\n";
+ SetResponse(kRedirectHeaders, "");
+
+ MakeTestRequest(0, 1, GURL("http://example.com/baz"));
+
+ net::URLRequest* url_request(
+ host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
+ ASSERT_TRUE(url_request);
+
+ EXPECT_FALSE(url_request->load_flags() &
+ net::LOAD_SUPPORT_ASYNC_REVALIDATION);
+}
+
+// A NetworkDelegate that records the URLRequests as they are created.
+class URLRequestRecordingNetworkDelegate : public net::TestNetworkDelegate {
+ public:
+ URLRequestRecordingNetworkDelegate() : requests_() {}
+
+ net::URLRequest* NextRequest() {
+ EXPECT_FALSE(requests_.empty());
+ if (requests_.empty())
+ return nullptr;
+ net::URLRequest* request = requests_.front();
+ EXPECT_TRUE(request);
+ requests_.pop_front();
+ return request;
+ }
+
+ bool NextRequestWasDestroyed() {
+ net::URLRequest* request = requests_.front();
+ requests_.pop_front();
+ return request == nullptr;
+ }
+
+ bool IsEmpty() const { return requests_.empty(); }
+
+ int OnBeforeURLRequest(net::URLRequest* request,
+ const net::CompletionCallback& callback,
+ GURL* new_url) override {
+ requests_.push_back(request);
+ return TestNetworkDelegate::OnBeforeURLRequest(request, callback, new_url);
+ }
+
+ void OnURLRequestDestroyed(net::URLRequest* request) override {
+ for (auto& recorded_request : requests_) {
+ if (recorded_request == request)
+ recorded_request = nullptr;
+ }
+ net::TestNetworkDelegate::OnURLRequestDestroyed(request);
+ }
+
+ private:
+ std::deque<net::URLRequest*> requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLRequestRecordingNetworkDelegate);
+};
+
+class AsyncRevalidationManagerRecordingTest
+ : public AsyncRevalidationManagerTest {
+ public:
+ AsyncRevalidationManagerRecordingTest()
+ : AsyncRevalidationManagerTest(
+ make_scoped_ptr(new URLRequestRecordingNetworkDelegate)) {}
+
+ void TearDown() override {
+ EXPECT_TRUE(IsEmpty());
+ AsyncRevalidationManagerTest::TearDown();
+ }
+
+ URLRequestRecordingNetworkDelegate* recording_network_delegate() const {
+ return static_cast<URLRequestRecordingNetworkDelegate*>(
+ network_delegate_.get());
+ }
+
+ bool NextRequestWasDestroyed() {
+ return recording_network_delegate()->NextRequestWasDestroyed();
+ }
+
+ net::URLRequest* NextRequest() {
+ return recording_network_delegate()->NextRequest();
+ }
+
+ bool IsEmpty() const { return recording_network_delegate()->IsEmpty(); }
+};
+
+// Verify that an async revalidation is actually created when needed.
+TEST_F(AsyncRevalidationManagerRecordingTest, Issued) {
+ // Create the original request.
+ MakeTestRequest(0, 1, GURL("http://example.com/async-revalidate"));
+
+ net::URLRequest* initial_request = NextRequest();
+ ASSERT_TRUE(initial_request);
+ EXPECT_TRUE(initial_request->load_flags() &
+ net::LOAD_SUPPORT_ASYNC_REVALIDATION);
+
+ net::URLRequest* async_request = NextRequest();
+ ASSERT_TRUE(async_request);
+}
+
+// Verify the the URL of the async revalidation matches the original request.
+TEST_F(AsyncRevalidationManagerRecordingTest, URLMatches) {
+ // Create the original request.
+ MakeTestRequest(0, 1, GURL("http://example.com/async-revalidate/u"));
+
+ // Discard the original request.
+ NextRequest();
+
+ net::URLRequest* async_request = NextRequest();
+ ASSERT_TRUE(async_request);
+ EXPECT_EQ(GURL("http://example.com/async-revalidate/u"),
+ async_request->url());
+}
+
+TEST_F(AsyncRevalidationManagerRecordingTest,
+ AsyncRevalidationsDoNotSupportAsyncRevalidation) {
+ // Create the original request.
+ MakeTestRequest(0, 1, GURL("http://example.com/async-revalidate"));
+
+ // Discard the original request.
+ NextRequest();
+
+ // Get the async revalidation request.
+ net::URLRequest* async_request = NextRequest();
+ ASSERT_TRUE(async_request);
+ EXPECT_FALSE(async_request->load_flags() &
+ net::LOAD_SUPPORT_ASYNC_REVALIDATION);
+}
+
+TEST_F(AsyncRevalidationManagerRecordingTest, AsyncRevalidationsNotDuplicated) {
+ // Create the original request.
+ MakeTestRequest(0, 1, GURL("http://example.com/async-revalidate"));
+
+ // Discard the original request.
+ NextRequest();
+
+ // Get the async revalidation request.
+ net::URLRequest* async_request = NextRequest();
+ EXPECT_TRUE(async_request);
+
+ // Start a second request to the same URL.
+ MakeTestRequest(0, 2, GURL("http://example.com/async-revalidate"));
+
+ // Discard the second request.
+ NextRequest();
+
+ // There should not be another async revalidation request.
+ EXPECT_TRUE(IsEmpty());
+}
+
+// Async revalidation to different URLs should not be treated as duplicates.
+TEST_F(AsyncRevalidationManagerRecordingTest,
+ AsyncRevalidationsToSeparateURLsAreSeparate) {
+ // Create two requests to two URLs.
+ MakeTestRequest(0, 1, GURL("http://example.com/async-revalidate"));
+ MakeTestRequest(0, 2, GURL("http://example.com/async-revalidate2"));
+
+ net::URLRequest* initial_request = NextRequest();
+ ASSERT_TRUE(initial_request);
+ net::URLRequest* initial_async_revalidation = NextRequest();
+ ASSERT_TRUE(initial_async_revalidation);
+ net::URLRequest* second_request = NextRequest();
+ ASSERT_TRUE(second_request);
+ net::URLRequest* second_async_revalidation = NextRequest();
+ ASSERT_TRUE(second_async_revalidation);
+
+ EXPECT_EQ("http://example.com/async-revalidate",
+ initial_request->url().spec());
+ EXPECT_EQ("http://example.com/async-revalidate",
+ initial_async_revalidation->url().spec());
+ EXPECT_EQ("http://example.com/async-revalidate2",
+ second_request->url().spec());
+ EXPECT_EQ("http://example.com/async-revalidate2",
+ second_async_revalidation->url().spec());
+}
+
+// Nothing after the first redirect leg has stale-while-revalidate applied.
+// TODO(ricea): s-w-r should work with redirects. Change this test when it does.
+TEST_F(AsyncRevalidationManagerRecordingTest, NoSWRAfterFirstRedirectLeg) {
+ MakeTestRequest(0, 1, GURL("http://example.com/redirect"));
+
+ net::URLRequest* initial_request = NextRequest();
+ EXPECT_TRUE(initial_request);
+
+ EXPECT_FALSE(initial_request->load_flags() &
+ net::LOAD_SUPPORT_ASYNC_REVALIDATION);
+
+ // An async revalidation happens for the redirect. It has no body, so it has
+ // already completed.
+ EXPECT_TRUE(NextRequestWasDestroyed());
+
+ // But no others.
+ EXPECT_TRUE(IsEmpty());
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/loader/certificate_resource_handler.cc b/chromium/content/browser/loader/certificate_resource_handler.cc
deleted file mode 100644
index fd49181f8da..00000000000
--- a/chromium/content/browser/loader/certificate_resource_handler.cc
+++ /dev/null
@@ -1,111 +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 "content/browser/loader/certificate_resource_handler.h"
-
-#include <limits.h>
-
-#include "components/mime_util/mime_util.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/common/resource_response.h"
-#include "net/base/io_buffer.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_status.h"
-
-namespace content {
-
-CertificateResourceHandler::CertificateResourceHandler(net::URLRequest* request)
- : ResourceHandler(request),
- buffer_(new net::GrowableIOBuffer),
- cert_type_(net::CERTIFICATE_MIME_TYPE_UNKNOWN) {
-}
-
-CertificateResourceHandler::~CertificateResourceHandler() {
-}
-
-bool CertificateResourceHandler::OnRequestRedirected(
- const net::RedirectInfo& redirect_info,
- ResourceResponse* resp,
- bool* defer) {
- return true;
-}
-
-bool CertificateResourceHandler::OnResponseStarted(ResourceResponse* resp,
- bool* defer) {
- cert_type_ =
- mime_util::GetCertificateMimeTypeForMimeType(resp->head.mime_type);
- return cert_type_ != net::CERTIFICATE_MIME_TYPE_UNKNOWN;
-}
-
-bool CertificateResourceHandler::OnWillStart(const GURL& url, bool* defer) {
- return true;
-}
-
-bool CertificateResourceHandler::OnBeforeNetworkStart(const GURL& url,
- bool* defer) {
- return true;
-}
-
-bool CertificateResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) {
- static const int kInitialBufferSizeInBytes = 32768;
- static const int kMaxCertificateSizeInBytes = 1024 * 1024;
-
- // TODO(gauravsh): Should we use 'min_size' here?
- DCHECK(buf);
- DCHECK(buf_size);
-
- if (buffer_->capacity() == 0) {
- buffer_->SetCapacity(kInitialBufferSizeInBytes);
- } else if (buffer_->RemainingCapacity() == 0) {
- int capacity = buffer_->capacity();
- if (capacity >= kMaxCertificateSizeInBytes)
- return false;
- static_assert(kMaxCertificateSizeInBytes < INT_MAX / 2,
- "The size limit ensures the capacity remains in bounds.");
- capacity *= 2;
- if (capacity > kMaxCertificateSizeInBytes)
- capacity = kMaxCertificateSizeInBytes;
- buffer_->SetCapacity(capacity);
- }
-
- *buf = buffer_.get();
- *buf_size = buffer_->RemainingCapacity();
-
- return true;
-}
-
-bool CertificateResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
- DCHECK_LE(0, bytes_read);
- DCHECK_LE(bytes_read, buffer_->RemainingCapacity());
- if (!bytes_read)
- return true;
-
- buffer_->set_offset(buffer_->offset() + bytes_read);
- return true;
-}
-
-void CertificateResourceHandler::OnResponseCompleted(
- const net::URLRequestStatus& urs,
- const std::string& sec_info,
- bool* defer) {
- if (urs.status() != net::URLRequestStatus::SUCCESS)
- return;
-
- // Note that it's up to the browser to verify that the certificate
- // data is well-formed.
- const ResourceRequestInfo* info = GetRequestInfo();
- GetContentClient()->browser()->AddCertificate(
- cert_type_, buffer_->StartOfBuffer(),
- static_cast<size_t>(buffer_->offset()), info->GetChildID(),
- info->GetRenderFrameID());
-}
-
-void CertificateResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- NOTREACHED();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/certificate_resource_handler.h b/chromium/content/browser/loader/certificate_resource_handler.h
deleted file mode 100644
index 743bf9d71dc..00000000000
--- a/chromium/content/browser/loader/certificate_resource_handler.h
+++ /dev/null
@@ -1,72 +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 CONTENT_BROWSER_LOADER_CERTIFICATE_RESOURCE_HANDLER_H_
-#define CONTENT_BROWSER_LOADER_CERTIFICATE_RESOURCE_HANDLER_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/browser/loader/resource_handler.h"
-#include "net/base/mime_util.h"
-
-namespace net {
-class GrowableIOBuffer;
-class URLRequest;
-class URLRequestStatus;
-} // namespace net
-
-namespace content {
-
-// This class handles certificate mime types such as:
-// - "application/x-x509-user-cert"
-// - "application/x-x509-ca-cert"
-// - "application/x-pkcs12"
-//
-class CertificateResourceHandler : public ResourceHandler {
- public:
- explicit CertificateResourceHandler(net::URLRequest* request);
- ~CertificateResourceHandler() override;
-
- // Not needed, as this event handler ought to be the final resource.
- bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
- ResourceResponse* resp,
- bool* defer) override;
-
- // Check if this indeed an X509 cert.
- bool OnResponseStarted(ResourceResponse* resp, bool* defer) override;
-
- // Pass-through implementation.
- bool OnWillStart(const GURL& url, bool* defer) override;
-
- // Pass-through implementation.
- bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
-
- // Create a new buffer to store received data.
- bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) override;
-
- // A read was completed, maybe allocate a new buffer for further data.
- bool OnReadCompleted(int bytes_read, bool* defer) override;
-
- // Done downloading the certificate.
- void OnResponseCompleted(const net::URLRequestStatus& urs,
- const std::string& sec_info,
- bool* defer) override;
-
- // N/A to cert downloading.
- void OnDataDownloaded(int bytes_downloaded) override;
-
- private:
- scoped_refptr<net::GrowableIOBuffer> buffer_;
- net::CertificateMimeType cert_type_;
-
- DISALLOW_COPY_AND_ASSIGN(CertificateResourceHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_CERTIFICATE_RESOURCE_HANDLER_H_
diff --git a/chromium/content/browser/loader/cross_site_resource_handler.cc b/chromium/content/browser/loader/cross_site_resource_handler.cc
index 7ffb659744a..fad4024ee28 100644
--- a/chromium/content/browser/loader/cross_site_resource_handler.cc
+++ b/chromium/content/browser/loader/cross_site_resource_handler.cc
@@ -5,6 +5,7 @@
#include "content/browser/loader/cross_site_resource_handler.h"
#include <string>
+#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
@@ -76,9 +77,9 @@ void OnCrossSiteResponseHelper(const CrossSiteResponseParams& params) {
CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
}
rfh->OnCrossSiteResponse(
- params.global_request_id, cross_site_transferring_request.Pass(),
- params.transfer_url_chain, params.referrer,
- params.page_transition, params.should_replace_current_entry);
+ params.global_request_id, std::move(cross_site_transferring_request),
+ params.transfer_url_chain, params.referrer, params.page_transition,
+ params.should_replace_current_entry);
} else if (leak_requests_for_testing_ && cross_site_transferring_request) {
// Some unit tests expect requests to be leaked in this case, so they can
// pass them along manually.
@@ -87,42 +88,23 @@ void OnCrossSiteResponseHelper(const CrossSiteResponseParams& params) {
}
// Returns whether a transfer is needed by doing a check on the UI thread.
-bool CheckNavigationPolicyOnUI(GURL real_url,
- int process_id,
- int render_frame_id) {
+CrossSiteResourceHandler::NavigationDecision
+CheckNavigationPolicyOnUI(GURL real_url, int process_id, int render_frame_id) {
CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
RenderFrameHostImpl* rfh =
RenderFrameHostImpl::FromID(process_id, render_frame_id);
+
+ // Without a valid RFH against which to check, we must cancel the request,
+ // to prevent the resource at |url| from being delivered to a potentially
+ // unsuitable renderer process.
if (!rfh)
- return false;
-
- // A transfer is not needed if the current SiteInstance doesn't yet have a
- // site. This is the case for tests that use NavigateToURL.
- if (!rfh->GetSiteInstance()->HasSite())
- return false;
-
- // For now, GuestViews never transfer on cross-site navigations.
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(rfh));
- if (web_contents->GetBrowserPluginGuest())
- return false;
-
- GURL effective_url = SiteInstanceImpl::GetEffectiveURL(
- rfh->GetSiteInstance()->GetBrowserContext(), real_url);
-
- // TODO(nasko, nick): These following --site-per-process checks are
- // overly simplistic. Update them to match all the cases
- // considered by RenderFrameHostManager::DetermineSiteInstanceForURL.
- if (SiteInstance::IsSameWebSite(rfh->GetSiteInstance()->GetBrowserContext(),
- rfh->GetSiteInstance()->GetSiteURL(),
- real_url)) {
- return false; // The same site, no transition needed.
- }
+ return CrossSiteResourceHandler::NavigationDecision::CANCEL_REQUEST;
- // The sites differ. If either one requires a dedicated process,
- // then a transfer is needed.
- return rfh->GetSiteInstance()->RequiresDedicatedProcess() ||
- SiteIsolationPolicy::DoesSiteRequireDedicatedProcess(effective_url);
+ RenderFrameHostManager* manager = rfh->frame_tree_node()->render_manager();
+ if (manager->IsRendererTransferNeededForNavigation(rfh, real_url))
+ return CrossSiteResourceHandler::NavigationDecision::TRANSFER_REQUIRED;
+ else
+ return CrossSiteResourceHandler::NavigationDecision::USE_EXISTING_RENDERER;
}
} // namespace
@@ -130,13 +112,12 @@ bool CheckNavigationPolicyOnUI(GURL real_url,
CrossSiteResourceHandler::CrossSiteResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
net::URLRequest* request)
- : LayeredResourceHandler(request, next_handler.Pass()),
+ : LayeredResourceHandler(request, std::move(next_handler)),
has_started_response_(false),
in_cross_site_transition_(false),
completed_during_transition_(false),
did_defer_(false),
- weak_ptr_factory_(this) {
-}
+ weak_ptr_factory_(this) {}
CrossSiteResourceHandler::~CrossSiteResourceHandler() {
// Cleanup back-pointer stored on the request info.
@@ -236,11 +217,18 @@ bool CrossSiteResourceHandler::OnNormalResponseStarted(
return next_handler_->OnResponseStarted(response, defer);
}
-void CrossSiteResourceHandler::ResumeOrTransfer(bool is_transfer) {
- if (is_transfer) {
- StartCrossSiteTransition(response_.get());
- } else {
- ResumeResponse();
+void CrossSiteResourceHandler::ResumeOrTransfer(NavigationDecision decision) {
+ switch (decision) {
+ case NavigationDecision::CANCEL_REQUEST:
+ // TODO(nick): What kind of cleanup do we need here?
+ controller()->Cancel();
+ break;
+ case NavigationDecision::USE_EXISTING_RENDERER:
+ ResumeResponse();
+ break;
+ case NavigationDecision::TRANSFER_REQUIRED:
+ StartCrossSiteTransition(response_.get());
+ break;
}
}
diff --git a/chromium/content/browser/loader/cross_site_resource_handler.h b/chromium/content/browser/loader/cross_site_resource_handler.h
index b73a5a1475b..3c38fc758d4 100644
--- a/chromium/content/browser/loader/cross_site_resource_handler.h
+++ b/chromium/content/browser/loader/cross_site_resource_handler.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_LOADER_CROSS_SITE_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_CROSS_SITE_RESOURCE_HANDLER_H_
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/loader/layered_resource_handler.h"
@@ -26,6 +27,12 @@ struct TransitionLayerData;
// and not a download.
class CrossSiteResourceHandler : public LayeredResourceHandler {
public:
+ enum class NavigationDecision {
+ TRANSFER_REQUIRED,
+ USE_EXISTING_RENDERER,
+ CANCEL_REQUEST
+ };
+
CrossSiteResourceHandler(scoped_ptr<ResourceHandler> next_handler,
net::URLRequest* request);
~CrossSiteResourceHandler() override;
@@ -63,7 +70,7 @@ class CrossSiteResourceHandler : public LayeredResourceHandler {
bool OnNormalResponseStarted(ResourceResponse* response,
bool* defer);
- void ResumeOrTransfer(bool is_transfer);
+ void ResumeOrTransfer(NavigationDecision decision);
void ResumeIfDeferred();
// Called when about to defer a request. Sets |did_defer_| and logs the
diff --git a/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc b/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc
new file mode 100644
index 00000000000..a6df689d032
--- /dev/null
+++ b/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc
@@ -0,0 +1,278 @@
+// Copyright 2015 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 "base/callback.h"
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/frame_messages.h"
+#include "content/public/browser/resource_dispatcher_host.h"
+#include "content/public/browser/resource_dispatcher_host_delegate.h"
+#include "content/public/browser/resource_throttle.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
+#include "ipc/ipc_security_test_util.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/url_request/url_request.h"
+
+namespace content {
+
+namespace {
+
+// A ResourceDispatchHostDelegate that uses ResourceThrottles to pause a
+// targeted request temporarily, to run a chunk of test code.
+class TestResourceDispatcherHostDelegate
+ : public ShellResourceDispatcherHostDelegate {
+ public:
+ using RequestDeferredHook = base::Callback<void(const base::Closure& resume)>;
+ TestResourceDispatcherHostDelegate() : throttle_created_(false) {}
+
+ void RequestBeginning(net::URLRequest* request,
+ ResourceContext* resource_context,
+ AppCacheService* appcache_service,
+ ResourceType resource_type,
+ ScopedVector<ResourceThrottle>* throttles) override {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ShellResourceDispatcherHostDelegate::RequestBeginning(
+ request, resource_context, appcache_service, resource_type, throttles);
+
+ // If this is a request for the tracked URL, add a throttle to track it.
+ if (request->url() == tracked_url_) {
+ // Expect only a single request for the tracked url.
+ ASSERT_FALSE(throttle_created_);
+ throttle_created_ = true;
+
+ throttles->push_back(
+ new CallbackRunningResourceThrottle(request, this, run_on_start_));
+ }
+ }
+
+ // Starts tracking a URL. The request for previously tracked URL, if any,
+ // must have been made and deleted before calling this function.
+ void SetTrackedURL(const GURL& tracked_url,
+ const RequestDeferredHook& run_on_start) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // Should not currently be tracking any URL.
+ ASSERT_FALSE(run_loop_);
+
+ // Create a RunLoop that will be stopped once the request for the tracked
+ // URL has been destroyed, to allow tracking the URL while also waiting for
+ // other events.
+ run_loop_.reset(new base::RunLoop());
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&TestResourceDispatcherHostDelegate::SetTrackedURLOnIOThread,
+ base::Unretained(this), tracked_url, run_on_start,
+ run_loop_->QuitClosure()));
+ }
+
+ // Waits until the tracked URL has been requested, and the request for it has
+ // been destroyed.
+ bool WaitForTrackedURLAndGetCompleted() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ run_loop_->Run();
+ run_loop_.reset();
+ return tracked_request_completed_;
+ }
+
+ private:
+ // A ResourceThrottle which defers the request at WillStartRequest time until
+ // a test-supplied callback completes. Notifies |tracker| when the request is
+ // destroyed.
+ class CallbackRunningResourceThrottle : public ResourceThrottle {
+ public:
+ CallbackRunningResourceThrottle(net::URLRequest* request,
+ TestResourceDispatcherHostDelegate* tracker,
+ const RequestDeferredHook& run_on_start)
+ : request_(request),
+ tracker_(tracker),
+ run_on_start_(run_on_start),
+ weak_factory_(this) {}
+
+ void WillStartRequest(bool* defer) override {
+ *defer = true;
+ base::Closure resume_request_on_io_thread = base::Bind(
+ base::IgnoreResult(&BrowserThread::PostTask), BrowserThread::IO,
+ FROM_HERE, base::Bind(&CallbackRunningResourceThrottle::Resume,
+ weak_factory_.GetWeakPtr()));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(run_on_start_, resume_request_on_io_thread));
+ }
+
+ ~CallbackRunningResourceThrottle() override {
+ // If the request is deleted without being cancelled, its status will
+ // indicate it succeeded, so have to check if the request is still pending
+ // as well.
+ tracker_->OnTrackedRequestDestroyed(!request_->is_pending() &&
+ request_->status().is_success());
+ }
+
+ // ResourceThrottle implementation:
+ const char* GetNameForLogging() const override {
+ return "CallbackRunningResourceThrottle";
+ }
+
+ private:
+ void Resume() { controller()->Resume(); }
+ net::URLRequest* request_;
+ TestResourceDispatcherHostDelegate* tracker_;
+ RequestDeferredHook run_on_start_;
+ base::WeakPtrFactory<CallbackRunningResourceThrottle> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CallbackRunningResourceThrottle);
+ };
+
+ void SetTrackedURLOnIOThread(const GURL& tracked_url,
+ const RequestDeferredHook& run_on_start,
+ const base::Closure& run_loop_quit_closure) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ throttle_created_ = false;
+ tracked_url_ = tracked_url;
+ run_on_start_ = run_on_start;
+ run_loop_quit_closure_ = run_loop_quit_closure;
+ }
+
+ void OnTrackedRequestDestroyed(bool completed) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ tracked_request_completed_ = completed;
+ tracked_url_ = GURL();
+ run_on_start_ = RequestDeferredHook();
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ run_loop_quit_closure_);
+ }
+
+ // These live on the IO thread.
+ GURL tracked_url_;
+ bool throttle_created_;
+ base::Closure run_loop_quit_closure_;
+ RequestDeferredHook run_on_start_;
+
+ // This lives on the UI thread.
+ scoped_ptr<base::RunLoop> run_loop_;
+
+ // Set on the IO thread while |run_loop_| is non-nullptr, read on the UI
+ // thread after deleting run_loop_.
+ bool tracked_request_completed_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherHostDelegate);
+};
+
+class CrossSiteResourceHandlerTest : public ContentBrowserTest {
+ public:
+ CrossSiteResourceHandlerTest() : old_delegate_(nullptr) {}
+
+ // ContentBrowserTest implementation:
+ void SetUpOnMainThread() override {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(
+ &CrossSiteResourceHandlerTest::InjectResourceDispatcherHostDelegate,
+ base::Unretained(this)));
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ content::SetupCrossSiteRedirector(embedded_test_server());
+ }
+
+ void TearDownOnMainThread() override {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&CrossSiteResourceHandlerTest::
+ RestoreResourceDispatcherHostDelegate,
+ base::Unretained(this)));
+ }
+
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ IsolateAllSitesForTesting(command_line);
+ }
+
+ void InjectResourceDispatcherHostDelegate() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ old_delegate_ = ResourceDispatcherHostImpl::Get()->delegate();
+ ResourceDispatcherHostImpl::Get()->SetDelegate(&tracking_delegate_);
+ }
+
+ void RestoreResourceDispatcherHostDelegate() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate_);
+ old_delegate_ = nullptr;
+ }
+
+ TestResourceDispatcherHostDelegate& tracking_delegate() {
+ return tracking_delegate_;
+ }
+
+ private:
+ TestResourceDispatcherHostDelegate tracking_delegate_;
+ ResourceDispatcherHostDelegate* old_delegate_;
+};
+
+void SimulateMaliciousFrameDetachOnUIThread(int render_process_id,
+ int frame_routing_id,
+ const base::Closure& done_cb) {
+ RenderFrameHostImpl* rfh =
+ RenderFrameHostImpl::FromID(render_process_id, frame_routing_id);
+ CHECK(rfh);
+
+ // Inject a frame detach message. An attacker-controlled renderer could do
+ // this without also cancelling the pending navigation (as blink would, if you
+ // removed the iframe from the document via js).
+ rfh->OnMessageReceived(FrameHostMsg_Detach(frame_routing_id));
+ done_cb.Run();
+}
+
+} // namespace
+
+// Regression test for https://crbug.com/538784 -- ensures that one can't
+// sidestep CrossSiteResourceHandler by detaching a frame mid-request.
+IN_PROC_BROWSER_TEST_F(CrossSiteResourceHandlerTest,
+ NoDeliveryToDetachedFrame) {
+ GURL attacker_page = embedded_test_server()->GetURL(
+ "evil.com", "/cross_site_iframe_factory.html?evil(evil)");
+ EXPECT_TRUE(NavigateToURL(shell(), attacker_page));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ RenderFrameHost* child_frame = root->child_at(0)->current_frame_host();
+
+ // Attacker initiates a navigation to a cross-site document. Under --site-per-
+ // process, these bytes must not be sent to the attacker process.
+ GURL target_resource =
+ embedded_test_server()->GetURL("a.com", "/title1.html");
+
+ // We add a testing hook to simulate the attacker-controlled process sending
+ // FrameHostMsg_Detach before the http response arrives. At the time this test
+ // was written, the resource request had a lifetime separate from the RFH,
+ tracking_delegate().SetTrackedURL(
+ target_resource, base::Bind(&SimulateMaliciousFrameDetachOnUIThread,
+ child_frame->GetProcess()->GetID(),
+ child_frame->GetRoutingID()));
+ EXPECT_TRUE(ExecuteScript(
+ shell()->web_contents()->GetMainFrame(),
+ base::StringPrintf("document.getElementById('child-0').src='%s'",
+ target_resource.spec().c_str())));
+
+ // Wait for the scenario to play out. If this returns false, it means the
+ // request did not succeed, which is good in this case.
+ EXPECT_FALSE(tracking_delegate().WaitForTrackedURLAndGetCompleted())
+ << "Request should have been cancelled before reaching the renderer.";
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/detachable_resource_handler.cc b/chromium/content/browser/loader/detachable_resource_handler.cc
index df9c357a888..786252f5b6b 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.cc
+++ b/chromium/content/browser/loader/detachable_resource_handler.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/detachable_resource_handler.h"
+#include <utility>
+
#include "base/logging.h"
#include "base/time/time.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -24,7 +26,7 @@ DetachableResourceHandler::DetachableResourceHandler(
base::TimeDelta cancel_delay,
scoped_ptr<ResourceHandler> next_handler)
: ResourceHandler(request),
- next_handler_(next_handler.Pass()),
+ next_handler_(std::move(next_handler)),
cancel_delay_(cancel_delay),
is_deferred_(false),
is_finished_(false) {
diff --git a/chromium/content/browser/loader/detachable_resource_handler.h b/chromium/content/browser/loader/detachable_resource_handler.h
index 4bb1763ec8d..95072269956 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.h
+++ b/chromium/content/browser/loader/detachable_resource_handler.h
@@ -5,8 +5,8 @@
#ifndef CONTENT_BROWSER_LOADER_DETACHABLE_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_DETACHABLE_RESOURCE_HANDLER_H_
-#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
diff --git a/chromium/content/browser/loader/global_routing_id.h b/chromium/content/browser/loader/global_routing_id.h
index a15e93d78da..df5f202c22e 100644
--- a/chromium/content/browser/loader/global_routing_id.h
+++ b/chromium/content/browser/loader/global_routing_id.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_LOADER_GLOBAL_ROUTING_ID_H_
#define CONTENT_BROWSER_LOADER_GLOBAL_ROUTING_ID_H_
+#include <tuple>
+
namespace content {
// Uniquely identifies the route from which a net::URLRequest comes.
@@ -24,9 +26,8 @@ struct GlobalRoutingID {
int route_id;
bool operator<(const GlobalRoutingID& other) const {
- if (child_id == other.child_id)
- return route_id < other.route_id;
- return child_id < other.child_id;
+ return std::tie(child_id, route_id) <
+ std::tie(other.child_id, other.route_id);
}
bool operator==(const GlobalRoutingID& other) const {
return child_id == other.child_id &&
diff --git a/chromium/content/browser/loader/layered_resource_handler.cc b/chromium/content/browser/loader/layered_resource_handler.cc
index 00048ae520a..9ff3d55e6f3 100644
--- a/chromium/content/browser/loader/layered_resource_handler.cc
+++ b/chromium/content/browser/loader/layered_resource_handler.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/layered_resource_handler.h"
+#include <utility>
+
#include "base/logging.h"
namespace content {
@@ -11,9 +13,7 @@ namespace content {
LayeredResourceHandler::LayeredResourceHandler(
net::URLRequest* request,
scoped_ptr<ResourceHandler> next_handler)
- : ResourceHandler(request),
- next_handler_(next_handler.Pass()) {
-}
+ : ResourceHandler(request), next_handler_(std::move(next_handler)) {}
LayeredResourceHandler::~LayeredResourceHandler() {
}
diff --git a/chromium/content/browser/loader/mime_type_resource_handler.cc b/chromium/content/browser/loader/mime_type_resource_handler.cc
index 59c2b531066..3c69c0ad4d2 100644
--- a/chromium/content/browser/loader/mime_type_resource_handler.cc
+++ b/chromium/content/browser/loader/mime_type_resource_handler.cc
@@ -4,6 +4,7 @@
#include "content/browser/loader/mime_type_resource_handler.h"
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -16,7 +17,6 @@
#include "components/mime_util/mime_util.h"
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/download/download_stats.h"
-#include "content/browser/loader/certificate_resource_handler.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader/stream_resource_handler.h"
@@ -86,7 +86,7 @@ MimeTypeResourceHandler::MimeTypeResourceHandler(
ResourceDispatcherHostImpl* host,
PluginService* plugin_service,
net::URLRequest* request)
- : LayeredResourceHandler(request, next_handler.Pass()),
+ : LayeredResourceHandler(request, std::move(next_handler)),
state_(STATE_STARTING),
host_(host),
plugin_service_(plugin_service),
@@ -94,8 +94,7 @@ MimeTypeResourceHandler::MimeTypeResourceHandler(
bytes_read_(0),
must_download_(false),
must_download_is_set_(false),
- weak_ptr_factory_(this) {
-}
+ weak_ptr_factory_(this) {}
MimeTypeResourceHandler::~MimeTypeResourceHandler() {
}
@@ -329,7 +328,7 @@ bool MimeTypeResourceHandler::SelectPluginHandler(bool* defer,
plugin_path, request(), response_.get(), &payload));
if (handler) {
*handled_by_plugin = true;
- return UseAlternateNextHandler(handler.Pass(), payload);
+ return UseAlternateNextHandler(std::move(handler), payload);
}
#endif
return true;
@@ -341,12 +340,14 @@ bool MimeTypeResourceHandler::SelectNextHandler(bool* defer) {
ResourceRequestInfoImpl* info = GetRequestInfo();
const std::string& mime_type = response_->head.mime_type;
- if (mime_util::IsSupportedCertificateMimeType(mime_type)) {
- // Install certificate file.
- info->set_is_download(true);
- scoped_ptr<ResourceHandler> handler(
- new CertificateResourceHandler(request()));
- return UseAlternateNextHandler(handler.Pass(), std::string());
+ // https://crbug.com/568184 - Temporary hack to track servers that aren't
+ // setting Content-Disposition when sending x-x509-user-cert and expecting
+ // the browser to automatically install certificates; this is being
+ // deprecated and will be removed upon full <keygen> removal.
+ if (mime_type == "application/x-x509-user-cert") {
+ UMA_HISTOGRAM_BOOLEAN(
+ "UserCert.ContentDisposition",
+ response_->head.headers->HasHeader("Content-Disposition"));
}
// Allow requests for object/embed tags to be intercepted as streams.
@@ -391,7 +392,7 @@ bool MimeTypeResourceHandler::SelectNextHandler(bool* defer) {
DownloadItem::kInvalidId,
scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo()),
DownloadUrlParameters::OnStartedCallback()));
- return UseAlternateNextHandler(handler.Pass(), std::string());
+ return UseAlternateNextHandler(std::move(handler), std::string());
}
bool MimeTypeResourceHandler::UseAlternateNextHandler(
@@ -443,7 +444,7 @@ bool MimeTypeResourceHandler::UseAlternateNextHandler(
// This is handled entirely within the new ResourceHandler, so just reset the
// original ResourceHandler.
- next_handler_ = new_handler.Pass();
+ next_handler_ = std::move(new_handler);
next_handler_->SetController(this);
return CopyReadBufferToNextHandler();
diff --git a/chromium/content/browser/loader/mime_type_resource_handler.h b/chromium/content/browser/loader/mime_type_resource_handler.h
index b5e56c21b70..9217683584d 100644
--- a/chromium/content/browser/loader/mime_type_resource_handler.h
+++ b/chromium/content/browser/loader/mime_type_resource_handler.h
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
+#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/loader/layered_resource_handler.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc b/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc
index 92fbbcb1fec..1b3ddcdbdf0 100644
--- a/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/mime_type_resource_handler.h"
+#include <stdint.h>
+
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -90,10 +92,10 @@ class TestResourceDispatcherHost : public ResourceDispatcherHostImpl {
net::URLRequest* request,
bool is_content_initiated,
bool must_download,
- uint32 id,
+ uint32_t id,
scoped_ptr<DownloadSaveInfo> save_info,
const DownloadUrlParameters::OnStartedCallback& started_cb) override {
- return scoped_ptr<ResourceHandler>(new TestResourceHandler).Pass();
+ return scoped_ptr<ResourceHandler>(new TestResourceHandler);
}
scoped_ptr<ResourceHandler> MaybeInterceptAsStream(
@@ -104,7 +106,7 @@ class TestResourceDispatcherHost : public ResourceDispatcherHostImpl {
intercepted_as_stream_count_++;
if (stream_has_handler_) {
intercepted_as_stream_ = true;
- return scoped_ptr<ResourceHandler>(new TestResourceHandler).Pass();
+ return scoped_ptr<ResourceHandler>(new TestResourceHandler);
} else {
return scoped_ptr<ResourceHandler>();
}
@@ -248,17 +250,17 @@ bool MimeTypeResourceHandlerTest::TestStreamIsIntercepted(
is_main_frame, // is_main_frame
false, // parent_is_main_frame
allow_download, // allow_download
- true); // is_async
+ true, // is_async
+ false); // is_using_lofi
TestResourceDispatcherHost host(stream_has_handler_);
TestResourceDispatcherHostDelegate host_delegate(must_download);
host.SetDelegate(&host_delegate);
TestFakePluginService plugin_service(plugin_available_, plugin_stale_);
- scoped_ptr<ResourceHandler> mime_sniffing_handler(
- new MimeTypeResourceHandler(
- scoped_ptr<ResourceHandler>(new TestResourceHandler()).Pass(), &host,
- &plugin_service, request.get()));
+ scoped_ptr<ResourceHandler> mime_sniffing_handler(new MimeTypeResourceHandler(
+ scoped_ptr<ResourceHandler>(new TestResourceHandler()), &host,
+ &plugin_service, request.get()));
TestResourceController resource_controller;
mime_sniffing_handler->SetController(&resource_controller);
@@ -317,6 +319,14 @@ TEST_F(MimeTypeResourceHandlerTest, StreamHandling) {
EXPECT_FALSE(
TestStreamIsIntercepted(allow_download, must_download, resource_type));
+ // Plugin resource request with download not allowed. Stream shouldn't be
+ // intercepted.
+ allow_download = false;
+ must_download = false;
+ resource_type = RESOURCE_TYPE_PLUGIN_RESOURCE;
+ EXPECT_FALSE(
+ TestStreamIsIntercepted(allow_download, must_download, resource_type));
+
// Object request with download not allowed. Stream should be intercepted.
allow_download = false;
must_download = false;
diff --git a/chromium/content/browser/loader/navigation_resource_throttle.cc b/chromium/content/browser/loader/navigation_resource_throttle.cc
index 8dd143cc079..44fd0c131ff 100644
--- a/chromium/content/browser/loader/navigation_resource_throttle.cc
+++ b/chromium/content/browser/loader/navigation_resource_throttle.cc
@@ -23,6 +23,14 @@ namespace {
typedef base::Callback<void(NavigationThrottle::ThrottleCheckResult)>
UIChecksPerformedCallback;
+void SendCheckResultToIOThread(UIChecksPerformedCallback callback,
+ NavigationThrottle::ThrottleCheckResult result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ CHECK(result != NavigationThrottle::DEFER);
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(callback, result));
+}
+
void CheckWillStartRequestOnUIThread(UIChecksPerformedCallback callback,
int render_process_id,
int render_frame_host_id,
@@ -32,48 +40,76 @@ void CheckWillStartRequestOnUIThread(UIChecksPerformedCallback callback,
ui::PageTransition transition,
bool is_external_protocol) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- NavigationThrottle::ThrottleCheckResult result = NavigationThrottle::PROCEED;
RenderFrameHostImpl* render_frame_host =
RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
- if (render_frame_host) {
- NavigationHandleImpl* navigation_handle =
- render_frame_host->navigation_handle();
- if (navigation_handle) {
- result = navigation_handle->WillStartRequest(is_post, sanitized_referrer,
- has_user_gesture, transition,
- is_external_protocol);
- }
+ if (!render_frame_host) {
+ SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED);
+ return;
}
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(callback, result));
+
+ NavigationHandleImpl* navigation_handle =
+ render_frame_host->navigation_handle();
+ if (!navigation_handle) {
+ SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED);
+ return;
+ }
+
+ navigation_handle->WillStartRequest(
+ is_post, sanitized_referrer, has_user_gesture, transition,
+ is_external_protocol, base::Bind(&SendCheckResultToIOThread, callback));
}
-void CheckWillRedirectRequestOnUIThread(UIChecksPerformedCallback callback,
- int render_process_id,
- int render_frame_host_id,
- const GURL& new_url,
- bool new_method_is_post,
- const GURL& new_referrer_url,
- bool new_is_external_protocol) {
+void CheckWillRedirectRequestOnUIThread(
+ UIChecksPerformedCallback callback,
+ int render_process_id,
+ int render_frame_host_id,
+ const GURL& new_url,
+ bool new_method_is_post,
+ const GURL& new_referrer_url,
+ bool new_is_external_protocol,
+ scoped_refptr<net::HttpResponseHeaders> headers) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- NavigationThrottle::ThrottleCheckResult result = NavigationThrottle::PROCEED;
RenderFrameHostImpl* render_frame_host =
RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
- if (render_frame_host) {
- NavigationHandleImpl* navigation_handle =
- render_frame_host->navigation_handle();
- if (navigation_handle) {
- RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id);
- GURL new_validated_url = new_url;
- rph->FilterURL(false, &new_validated_url);
- result = navigation_handle->WillRedirectRequest(
- new_validated_url, new_method_is_post, new_referrer_url,
- new_is_external_protocol);
- }
+ if (!render_frame_host) {
+ SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED);
+ return;
}
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(callback, result));
+
+ NavigationHandleImpl* navigation_handle =
+ render_frame_host->navigation_handle();
+ if (!navigation_handle) {
+ SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED);
+ return;
+ }
+
+ GURL new_validated_url(new_url);
+ RenderProcessHost::FromID(render_process_id)
+ ->FilterURL(false, &new_validated_url);
+ navigation_handle->WillRedirectRequest(
+ new_validated_url, new_method_is_post, new_referrer_url,
+ new_is_external_protocol, headers,
+ base::Bind(&SendCheckResultToIOThread, callback));
}
+
+void WillProcessResponseOnUIThread(
+ int render_process_id,
+ int render_frame_host_id,
+ scoped_refptr<net::HttpResponseHeaders> headers) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RenderFrameHostImpl* render_frame_host =
+ RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
+ if (!render_frame_host)
+ return;
+
+ NavigationHandleImpl* navigation_handle =
+ render_frame_host->navigation_handle();
+ if (!navigation_handle)
+ return;
+
+ navigation_handle->ReadyToCommitNavigation(render_frame_host, headers);
+}
+
} // namespace
NavigationResourceThrottle::NavigationResourceThrottle(net::URLRequest* request)
@@ -82,6 +118,7 @@ NavigationResourceThrottle::NavigationResourceThrottle(net::URLRequest* request)
NavigationResourceThrottle::~NavigationResourceThrottle() {}
void NavigationResourceThrottle::WillStartRequest(bool* defer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
if (!info)
return;
@@ -112,6 +149,7 @@ void NavigationResourceThrottle::WillStartRequest(bool* defer) {
void NavigationResourceThrottle::WillRedirectRequest(
const net::RedirectInfo& redirect_info,
bool* defer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
if (!info)
return;
@@ -128,15 +166,50 @@ void NavigationResourceThrottle::WillRedirectRequest(
UIChecksPerformedCallback callback =
base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed,
weak_ptr_factory_.GetWeakPtr());
+
+ // Send the redirect info to the NavigationHandle on the UI thread.
+ // Note: to avoid threading issues, a copy of the HttpResponseHeaders is sent
+ // in lieu of the original.
+ scoped_refptr<net::HttpResponseHeaders> response_headers;
+ if (request_->response_headers()) {
+ response_headers = new net::HttpResponseHeaders(
+ request_->response_headers()->raw_headers());
+ }
+
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&CheckWillRedirectRequestOnUIThread, callback,
render_process_id, render_frame_id, redirect_info.new_url,
redirect_info.new_method == "POST",
- GURL(redirect_info.new_referrer), new_is_external_protocol));
+ GURL(redirect_info.new_referrer), new_is_external_protocol,
+ response_headers));
*defer = true;
}
+void NavigationResourceThrottle::WillProcessResponse(bool* defer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
+ if (!info)
+ return;
+
+ int render_process_id, render_frame_id;
+ if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
+ return;
+
+ // Send a copy of the response headers to the NavigationHandle on the UI
+ // thread.
+ scoped_refptr<net::HttpResponseHeaders> response_headers;
+ if (request_->response_headers()) {
+ response_headers = new net::HttpResponseHeaders(
+ request_->response_headers()->raw_headers());
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&WillProcessResponseOnUIThread, render_process_id,
+ render_frame_id, response_headers));
+}
+
const char* NavigationResourceThrottle::GetNameForLogging() const {
return "NavigationResourceThrottle";
}
@@ -146,6 +219,8 @@ void NavigationResourceThrottle::OnUIChecksPerformed(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (result == NavigationThrottle::CANCEL_AND_IGNORE) {
controller()->CancelAndIgnore();
+ } else if (result == NavigationThrottle::CANCEL) {
+ controller()->Cancel();
} else {
controller()->Resume();
}
diff --git a/chromium/content/browser/loader/navigation_resource_throttle.h b/chromium/content/browser/loader/navigation_resource_throttle.h
index e46b59d0669..6357b20aad4 100644
--- a/chromium/content/browser/loader/navigation_resource_throttle.h
+++ b/chromium/content/browser/loader/navigation_resource_throttle.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_BROWSER_LOADER_NAVIGATION_RESOURCE_THROTTLE_H_
#define CONTENT_BROWSER_LOADER_NAVIGATION_RESOURCE_THROTTLE_H_
-#include "base/basictypes.h"
+#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/resource_throttle.h"
@@ -28,6 +28,7 @@ class NavigationResourceThrottle : public ResourceThrottle {
void WillStartRequest(bool* defer) override;
void WillRedirectRequest(const net::RedirectInfo& redirect_info,
bool* defer) override;
+ void WillProcessResponse(bool* defer) override;
const char* GetNameForLogging() const override;
private:
diff --git a/chromium/content/browser/loader/navigation_url_loader.cc b/chromium/content/browser/loader/navigation_url_loader.cc
index c1513dc4a5d..e2507650a81 100644
--- a/chromium/content/browser/loader/navigation_url_loader.cc
+++ b/chromium/content/browser/loader/navigation_url_loader.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/navigation_url_loader.h"
+#include <utility>
+
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_url_loader_factory.h"
#include "content/browser/loader/navigation_url_loader_impl.h"
@@ -15,13 +17,15 @@ static NavigationURLLoaderFactory* g_factory = nullptr;
scoped_ptr<NavigationURLLoader> NavigationURLLoader::Create(
BrowserContext* browser_context,
scoped_ptr<NavigationRequestInfo> request_info,
+ ServiceWorkerNavigationHandle* service_worker_handle,
NavigationURLLoaderDelegate* delegate) {
if (g_factory) {
- return g_factory->CreateLoader(browser_context, request_info.Pass(),
- delegate);
+ return g_factory->CreateLoader(browser_context, std::move(request_info),
+ service_worker_handle, delegate);
}
- return scoped_ptr<NavigationURLLoader>(new NavigationURLLoaderImpl(
- browser_context, request_info.Pass(), delegate));
+ return scoped_ptr<NavigationURLLoader>(
+ new NavigationURLLoaderImpl(browser_context, std::move(request_info),
+ service_worker_handle, delegate));
}
void NavigationURLLoader::SetFactoryForTesting(
diff --git a/chromium/content/browser/loader/navigation_url_loader.h b/chromium/content/browser/loader/navigation_url_loader.h
index 89553f6e30f..0ba836a8d67 100644
--- a/chromium/content/browser/loader/navigation_url_loader.h
+++ b/chromium/content/browser/loader/navigation_url_loader.h
@@ -5,7 +5,6 @@
#ifndef CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_H_
#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_H_
-#include "base/basictypes.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
@@ -15,6 +14,7 @@ namespace content {
class BrowserContext;
class NavigationURLLoaderDelegate;
class NavigationURLLoaderFactory;
+class ServiceWorkerNavigationHandle;
struct CommonNavigationParams;
struct NavigationRequestInfo;
@@ -35,6 +35,7 @@ class CONTENT_EXPORT NavigationURLLoader {
static scoped_ptr<NavigationURLLoader> Create(
BrowserContext* browser_context,
scoped_ptr<NavigationRequestInfo> request_info,
+ ServiceWorkerNavigationHandle* service_worker_handle,
NavigationURLLoaderDelegate* delegate);
// For testing purposes; sets the factory for use in testing.
diff --git a/chromium/content/browser/loader/navigation_url_loader_factory.h b/chromium/content/browser/loader/navigation_url_loader_factory.h
index 770644e0519..a2fd37136a7 100644
--- a/chromium/content/browser/loader/navigation_url_loader_factory.h
+++ b/chromium/content/browser/loader/navigation_url_loader_factory.h
@@ -18,6 +18,7 @@ class NavigationURLLoaderFactory {
virtual scoped_ptr<NavigationURLLoader> CreateLoader(
BrowserContext* browser_context,
scoped_ptr<NavigationRequestInfo> request_info,
+ ServiceWorkerNavigationHandle* service_worker_handle,
NavigationURLLoaderDelegate* delegate) = 0;
protected:
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
index 7cbd9112d6d..1f95ce3165f 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -4,11 +4,15 @@
#include "content/browser/loader/navigation_url_loader_impl.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/location.h"
+#include "base/trace_event/trace_event.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/browser/loader/navigation_url_loader_impl_core.h"
+#include "content/browser/service_worker/service_worker_navigation_handle.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/stream_handle.h"
@@ -18,17 +22,28 @@ namespace content {
NavigationURLLoaderImpl::NavigationURLLoaderImpl(
BrowserContext* browser_context,
scoped_ptr<NavigationRequestInfo> request_info,
+ ServiceWorkerNavigationHandle* service_worker_handle,
NavigationURLLoaderDelegate* delegate)
- : delegate_(delegate),
- weak_factory_(this) {
+ : delegate_(delegate), weak_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
core_ = new NavigationURLLoaderImplCore(weak_factory_.GetWeakPtr());
+
+ // TODO(carlosk): extend this trace to support non-PlzNavigate navigations.
+ // For the trace below we're using the NavigationURLLoaderImplCore as the
+ // async trace id, |navigation_start| as the timestamp and reporting the
+ // FrameTreeNode id as a parameter.
+ TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
+ "navigation", "Navigation timeToResponseStarted", core_,
+ request_info->common_params.navigation_start.ToInternalValue(),
+ "FrameTreeNode id", request_info->frame_tree_node_id);
+ ServiceWorkerNavigationHandleCore* service_worker_handle_core =
+ service_worker_handle ? service_worker_handle->core() : nullptr;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&NavigationURLLoaderImplCore::Start, base::Unretained(core_),
browser_context->GetResourceContext(),
- base::Passed(&request_info)));
+ service_worker_handle_core, base::Passed(&request_info)));
}
NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
@@ -60,7 +75,7 @@ void NavigationURLLoaderImpl::NotifyResponseStarted(
scoped_ptr<StreamHandle> body) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- delegate_->OnResponseStarted(response, body.Pass());
+ delegate_->OnResponseStarted(response, std::move(body));
}
void NavigationURLLoaderImpl::NotifyRequestFailed(bool in_cache,
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.h b/chromium/content/browser/loader/navigation_url_loader_impl.h
index 6a88fc8650c..5c7fcd0d2b0 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.h
@@ -19,6 +19,7 @@ struct RedirectInfo;
namespace content {
class NavigationURLLoaderImplCore;
+class ServiceWorkerNavigationHandle;
class StreamHandle;
struct ResourceResponse;
@@ -27,6 +28,7 @@ class NavigationURLLoaderImpl : public NavigationURLLoader {
// The caller is responsible for ensuring that |delegate| outlives the loader.
NavigationURLLoaderImpl(BrowserContext* browser_context,
scoped_ptr<NavigationRequestInfo> request_info,
+ ServiceWorkerNavigationHandle* service_worker_handle,
NavigationURLLoaderDelegate* delegate);
~NavigationURLLoaderImpl() override;
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.cc b/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
index 7fe69513040..bd7ef98f8ea 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
@@ -10,6 +10,7 @@
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_resource_handler.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
#include "content/common/navigation_params.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/stream_handle.h"
@@ -37,6 +38,7 @@ NavigationURLLoaderImplCore::~NavigationURLLoaderImplCore() {
void NavigationURLLoaderImplCore::Start(
ResourceContext* resource_context,
+ ServiceWorkerNavigationHandleCore* service_worker_handle_core,
scoped_ptr<NavigationRequestInfo> request_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -45,8 +47,11 @@ void NavigationURLLoaderImplCore::Start(
base::Bind(&NavigationURLLoaderImpl::NotifyRequestStarted, loader_,
base::TimeTicks::Now()));
- ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
- resource_context, *request_info, this);
+ // The ResourceDispatcherHostImpl can be null in unit tests.
+ if (ResourceDispatcherHostImpl::Get()) {
+ ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
+ resource_context, *request_info, this, service_worker_handle_core);
+ }
}
void NavigationURLLoaderImplCore::FollowRedirect() {
@@ -56,11 +61,11 @@ void NavigationURLLoaderImplCore::FollowRedirect() {
resource_handler_->FollowRedirect();
}
-
void NavigationURLLoaderImplCore::NotifyRequestRedirected(
const net::RedirectInfo& redirect_info,
ResourceResponse* response) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT_ASYNC_END0("navigation", "Navigation redirectDelay", this);
// Make a copy of the ResourceResponse before it is passed to another thread.
//
@@ -71,12 +76,22 @@ void NavigationURLLoaderImplCore::NotifyRequestRedirected(
BrowserThread::UI, FROM_HERE,
base::Bind(&NavigationURLLoaderImpl::NotifyRequestRedirected, loader_,
redirect_info, response->DeepCopy()));
+
+ // TODO(carlosk): extend this trace to support non-PlzNavigate navigations.
+ // For the trace below we're using the NavigationURLLoaderImplCore as the
+ // async trace id and reporting the new redirect URL as a parameter.
+ TRACE_EVENT_ASYNC_BEGIN2("navigation", "Navigation redirectDelay", this,
+ "&NavigationURLLoaderImplCore", this, "New URL",
+ redirect_info.new_url.spec());
}
void NavigationURLLoaderImplCore::NotifyResponseStarted(
ResourceResponse* response,
scoped_ptr<StreamHandle> body) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT_ASYNC_END0("navigation", "Navigation redirectDelay", this);
+ TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
+ "&NavigationURLLoaderImplCore", this, "success", true);
// If, by the time the task reaches the UI thread, |loader_| has already been
// destroyed, NotifyResponseStarted will not run. |body| will be destructed
@@ -96,6 +111,10 @@ void NavigationURLLoaderImplCore::NotifyResponseStarted(
void NavigationURLLoaderImplCore::NotifyRequestFailed(bool in_cache,
int net_error) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT_ASYNC_END0("navigation", "Navigation redirectDelay", this);
+ TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
+ "&NavigationURLLoaderImplCore", this, "success",
+ false);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.h b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
index 8a93469c93b..b12629d92f2 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_core.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
@@ -5,7 +5,6 @@
#ifndef CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_CORE_H_
#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_CORE_H_
-#include "base/basictypes.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
@@ -23,6 +22,7 @@ class NavigationResourceHandler;
class ResourceContext;
class ResourceHandler;
class ResourceRequestBody;
+class ServiceWorkerNavigationHandleCore;
class StreamHandle;
struct ResourceResponse;
@@ -40,6 +40,7 @@ class NavigationURLLoaderImplCore {
// Starts the request.
void Start(ResourceContext* resource_context,
+ ServiceWorkerNavigationHandleCore* service_worker_handle_core,
scoped_ptr<NavigationRequestInfo> request_info);
// Follows the current pending redirect.
diff --git a/chromium/content/browser/loader/navigation_url_loader_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
index 0a4e26b6f91..efee272495d 100644
--- a/chromium/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <utility>
+
#include "base/command_line.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -34,6 +36,7 @@
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/origin.h"
namespace content {
@@ -109,7 +112,7 @@ class TestNavigationURLLoaderDelegate : public NavigationURLLoaderDelegate {
void OnResponseStarted(const scoped_refptr<ResourceResponse>& response,
scoped_ptr<StreamHandle> body) override {
response_ = response;
- body_ = body.Pass();
+ body_ = std::move(body);
ASSERT_TRUE(response_started_);
response_started_->Quit();
}
@@ -178,16 +181,17 @@ class NavigationURLLoaderTest : public testing::Test {
scoped_ptr<NavigationURLLoader> MakeTestLoader(
const GURL& url,
NavigationURLLoaderDelegate* delegate) {
- BeginNavigationParams begin_params(
- "GET", std::string(), net::LOAD_NORMAL, false);
+ BeginNavigationParams begin_params("GET", std::string(), net::LOAD_NORMAL,
+ false, false,
+ REQUEST_CONTEXT_TYPE_LOCATION);
CommonNavigationParams common_params;
common_params.url = url;
- scoped_ptr<NavigationRequestInfo> request_info(
- new NavigationRequestInfo(common_params, begin_params, url, true, false,
- -1, scoped_refptr<ResourceRequestBody>()));
+ scoped_ptr<NavigationRequestInfo> request_info(new NavigationRequestInfo(
+ common_params, begin_params, url, url::Origin(url), true, false, -1,
+ scoped_refptr<ResourceRequestBody>()));
- return NavigationURLLoader::Create(browser_context_.get(),
- request_info.Pass(), delegate);
+ return NavigationURLLoader::Create(
+ browser_context_.get(), std::move(request_info), nullptr, delegate);
}
// Helper function for fetching the body of a URL to a string.
diff --git a/chromium/content/browser/loader/power_save_block_resource_throttle.cc b/chromium/content/browser/loader/power_save_block_resource_throttle.cc
index 42e0b0e46d8..76afe12de13 100644
--- a/chromium/content/browser/loader/power_save_block_resource_throttle.cc
+++ b/chromium/content/browser/loader/power_save_block_resource_throttle.cc
@@ -14,8 +14,9 @@ const int kPowerSaveBlockDelaySeconds = 30;
} // namespace
-PowerSaveBlockResourceThrottle::PowerSaveBlockResourceThrottle() {
-}
+PowerSaveBlockResourceThrottle::PowerSaveBlockResourceThrottle(
+ const std::string& host)
+ : host_(host) {}
PowerSaveBlockResourceThrottle::~PowerSaveBlockResourceThrottle() {
}
@@ -41,7 +42,7 @@ const char* PowerSaveBlockResourceThrottle::GetNameForLogging() const {
void PowerSaveBlockResourceThrottle::ActivatePowerSaveBlocker() {
power_save_blocker_ = PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
- PowerSaveBlocker::kReasonOther, "Uploading data");
+ PowerSaveBlocker::kReasonOther, "Uploading data to " + host_);
}
} // namespace content
diff --git a/chromium/content/browser/loader/power_save_block_resource_throttle.h b/chromium/content/browser/loader/power_save_block_resource_throttle.h
index 0d0c0803bfd..4c678421a05 100644
--- a/chromium/content/browser/loader/power_save_block_resource_throttle.h
+++ b/chromium/content/browser/loader/power_save_block_resource_throttle.h
@@ -5,8 +5,10 @@
#ifndef CONTENT_BROWSER_LOADER_POWER_SAVE_BLOCK_RESOURCE_THROTTLE_H_
#define CONTENT_BROWSER_LOADER_POWER_SAVE_BLOCK_RESOURCE_THROTTLE_H_
-#include "base/basictypes.h"
+#include <string>
+
#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
#include "content/public/browser/resource_throttle.h"
@@ -18,7 +20,7 @@ class PowerSaveBlocker;
// This ResourceThrottle blocks power save until large upload request finishes.
class PowerSaveBlockResourceThrottle : public ResourceThrottle {
public:
- PowerSaveBlockResourceThrottle();
+ explicit PowerSaveBlockResourceThrottle(const std::string& host);
~PowerSaveBlockResourceThrottle() override;
// ResourceThrottle overrides:
@@ -29,6 +31,7 @@ class PowerSaveBlockResourceThrottle : public ResourceThrottle {
private:
void ActivatePowerSaveBlocker();
+ const std::string host_;
base::OneShotTimer timer_;
scoped_ptr<PowerSaveBlocker> power_save_blocker_;
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
index 12fd7d38e54..670b3343d30 100644
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
+++ b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
@@ -4,8 +4,11 @@
#include "content/browser/loader/redirect_to_file_resource_handler.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/threading/thread_restrictions.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader/temporary_file_stream.h"
@@ -61,7 +64,7 @@ class RedirectToFileResourceHandler::Writer {
scoped_ptr<net::FileStream> file_stream,
ShareableFileReference* deletable_file)
: handler_(handler),
- file_stream_(file_stream.Pass()),
+ file_stream_(std::move(file_stream)),
is_writing_(false),
deletable_file_(deletable_file) {
DCHECK(!deletable_file_->path().empty());
@@ -129,7 +132,7 @@ class RedirectToFileResourceHandler::Writer {
RedirectToFileResourceHandler::RedirectToFileResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
net::URLRequest* request)
- : LayeredResourceHandler(request, next_handler.Pass()),
+ : LayeredResourceHandler(request, std::move(next_handler)),
buf_(new net::GrowableIOBuffer()),
buf_write_pending_(false),
write_cursor_(0),
@@ -137,8 +140,7 @@ RedirectToFileResourceHandler::RedirectToFileResourceHandler(
next_buffer_size_(kInitialReadBufSize),
did_defer_(false),
completed_during_write_(false),
- weak_factory_(this) {
-}
+ weak_factory_(this) {}
RedirectToFileResourceHandler::~RedirectToFileResourceHandler() {
// Orphan the writer to asynchronously close and release the temporary file.
@@ -249,7 +251,7 @@ void RedirectToFileResourceHandler::DidCreateTemporaryFile(
return;
}
- writer_ = new Writer(this, file_stream.Pass(), deletable_file);
+ writer_ = new Writer(this, std::move(file_stream), deletable_file);
// Resume the request.
DCHECK(did_defer_);
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.h b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
index 1778921e370..cd4d60dc058 100644
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.h
+++ b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
@@ -5,11 +5,11 @@
#ifndef CONTENT_BROWSER_LOADER_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_
-#include "base/basictypes.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/content/browser/loader/resource_buffer.h b/chromium/content/browser/loader/resource_buffer.h
index 0908edbc083..e323bf19a41 100644
--- a/chromium/content/browser/loader/resource_buffer.h
+++ b/chromium/content/browser/loader/resource_buffer.h
@@ -7,7 +7,7 @@
#include <queue>
-#include "base/basictypes.h"
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
index b612d302df5..bad9b869c9f 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -2,15 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/public/browser/resource_dispatcher_host.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/web_contents.h"
@@ -18,6 +26,7 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_content_browser_client.h"
@@ -28,6 +37,8 @@
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "net/test/url_request/url_request_mock_http_job.h"
+#include "net/url_request/url_request.h"
+#include "url/gurl.h"
using base::ASCIIToUTF16;
@@ -57,11 +68,6 @@ class ResourceDispatcherHostBrowserTest : public ContentBrowserTest,
got_downloads_ = !!manager->InProgressCount();
}
- GURL GetMockURL(const std::string& file) {
- return net::URLRequestMockHTTPJob::GetMockUrl(
- base::FilePath().AppendASCII(file));
- }
-
void CheckTitleTest(const GURL& url,
const std::string& expected_title) {
base::string16 expected_title16(ASCIIToUTF16(expected_title));
@@ -98,7 +104,7 @@ class ResourceDispatcherHostBrowserTest : public ContentBrowserTest,
// Test title for content created by javascript window.open().
// See http://crbug.com/5988
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle1) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/dynamic1.html"));
base::string16 title;
@@ -111,7 +117,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle1) {
// Test title for content created by javascript window.open().
// See http://crbug.com/5988
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle2) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/dynamic2.html"));
base::string16 title;
@@ -123,26 +129,29 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle2) {
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
SniffHTMLWithNoContentType) {
- CheckTitleTest(GetMockURL("content-sniffer-test0.html"),
- "Content Sniffer Test 0");
+ CheckTitleTest(
+ net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test0.html"),
+ "Content Sniffer Test 0");
}
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
RespectNoSniffDirective) {
- CheckTitleTest(GetMockURL("nosniff-test.html"),
+ CheckTitleTest(net::URLRequestMockHTTPJob::GetMockUrl("nosniff-test.html"),
"mock.http/nosniff-test.html");
}
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
DoNotSniffHTMLFromTextPlain) {
- CheckTitleTest(GetMockURL("content-sniffer-test1.html"),
- "mock.http/content-sniffer-test1.html");
+ CheckTitleTest(
+ net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test1.html"),
+ "mock.http/content-sniffer-test1.html");
}
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
DoNotSniffHTMLFromImageGIF) {
- CheckTitleTest(GetMockURL("content-sniffer-test2.html"),
- "mock.http/content-sniffer-test2.html");
+ CheckTitleTest(
+ net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test2.html"),
+ "mock.http/content-sniffer-test2.html");
}
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
@@ -150,25 +159,30 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// Make sure no downloads start.
BrowserContext::GetDownloadManager(
shell()->web_contents()->GetBrowserContext())->AddObserver(this);
- CheckTitleTest(GetMockURL("content-sniffer-test3.html"),
- "Content Sniffer Test 3");
+ CheckTitleTest(
+ net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test3.html"),
+ "Content Sniffer Test 3");
EXPECT_EQ(1u, Shell::windows().size());
ASSERT_FALSE(got_downloads());
}
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
ContentDispositionEmpty) {
- CheckTitleTest(GetMockURL("content-disposition-empty.html"), "success");
+ CheckTitleTest(
+ net::URLRequestMockHTTPJob::GetMockUrl("content-disposition-empty.html"),
+ "success");
}
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
ContentDispositionInline) {
- CheckTitleTest(GetMockURL("content-disposition-inline.html"), "success");
+ CheckTitleTest(
+ net::URLRequestMockHTTPJob::GetMockUrl("content-disposition-inline.html"),
+ "success");
}
// Test for bug #1091358.
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, SyncXMLHttpRequest) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
NavigateToURL(
shell(), embedded_test_server()->GetURL("/sync_xmlhttprequest.html"));
@@ -184,7 +198,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, SyncXMLHttpRequest) {
// If this flakes, use http://crbug.com/62776.
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
SyncXMLHttpRequest_Disallowed) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
NavigateToURL(
shell(),
embedded_test_server()->GetURL("/sync_xmlhttprequest_disallowed.html"));
@@ -210,7 +224,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
#endif
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
MAYBE_SyncXMLHttpRequest_DuringUnload) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
BrowserContext::GetDownloadManager(
shell()->web_contents()->GetBrowserContext())->AddObserver(this);
@@ -230,15 +244,16 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// Tests that onunload is run for cross-site requests. (Bug 1114994)
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
DISABLED_CrossSiteOnunloadCookie) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/onunload_cookie.html");
CheckTitleTest(url, "set cookie on unload");
// Navigate to a new cross-site page, to dispatch unload event and set the
// cookie.
- CheckTitleTest(GetMockURL("content-sniffer-test0.html"),
- "Content Sniffer Test 0");
+ CheckTitleTest(
+ net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test0.html"),
+ "Content Sniffer Test 0");
// Check that the cookie was set.
EXPECT_EQ("onunloadCookie=foo", GetCookies(url));
@@ -249,7 +264,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// without network loads (e.g., about:blank, data URLs).
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
DISABLED_CrossSiteImmediateLoadOnunloadCookie) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/onunload_cookie.html");
CheckTitleTest(url, "set cookie on unload");
@@ -275,7 +290,7 @@ scoped_ptr<net::test_server::HttpResponse> NoContentResponseHandler(
scoped_ptr<net::test_server::BasicHttpResponse> http_response(
new net::test_server::BasicHttpResponse);
http_response->set_code(net::HTTP_NO_CONTENT);
- return http_response.Pass();
+ return std::move(http_response);
}
} // namespace
@@ -284,7 +299,7 @@ scoped_ptr<net::test_server::HttpResponse> NoContentResponseHandler(
// If this flakes use http://crbug.com/80596.
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
CrossSiteNoUnloadOn204) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
// Start with a URL that sets a cookie in its unload handler.
GURL url = embedded_test_server()->GetURL("/onunload_cookie.html");
@@ -328,8 +343,9 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// Navigate to a new cross-site page. The browser should not wait around for
// the old renderer's on{before}unload handlers to run.
- CheckTitleTest(GetMockURL("content-sniffer-test0.html"),
- "Content Sniffer Test 0");
+ CheckTitleTest(
+ net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test0.html"),
+ "Content Sniffer Test 0");
}
// Tests that cross-site navigations work when the new page does not go through
@@ -337,8 +353,9 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
CrossSiteNavigationNonBuffered) {
// Start with an HTTP page.
- CheckTitleTest(GetMockURL("content-sniffer-test0.html"),
- "Content Sniffer Test 0");
+ CheckTitleTest(
+ net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test0.html"),
+ "Content Sniffer Test 0");
// Now load a file:// page, which does not use the BufferedEventHandler.
// Make sure that the page loads and displays a title, and doesn't get stuck.
@@ -352,7 +369,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// away from the link doctor page. (Bug 1235537)
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
DISABLED_CrossSiteNavigationErrorPage) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/onunload_cookie.html"));
CheckTitleTest(url, "set cookie on unload");
@@ -397,7 +414,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
CrossSiteNavigationErrorPage2) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/title2.html"));
CheckTitleTest(url, "Title Of Awesomeness");
@@ -428,7 +445,8 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
//
// If the redirect in #2 were not blocked, we'd also see a request
// for http://mock.http:4000/title2.html, and the title would be different.
- CheckTitleTest(GetMockURL("cross-origin-redirect-blocked.html"),
+ CheckTitleTest(net::URLRequestMockHTTPJob::GetMockUrl(
+ "cross-origin-redirect-blocked.html"),
"Title Of More Awesomeness");
}
@@ -459,7 +477,7 @@ scoped_ptr<net::test_server::HttpResponse> HandleRedirectRequest(
http_response->set_code(net::HTTP_FOUND);
http_response->AddCustomHeader(
"Location", request.relative_url.substr(request_path.length()));
- return http_response.Pass();
+ return std::move(http_response);
}
} // namespace
@@ -467,7 +485,7 @@ scoped_ptr<net::test_server::HttpResponse> HandleRedirectRequest(
// Test that we update the cookie policy URLs correctly when transferring
// navigations.
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, CookiePolicy) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
embedded_test_server()->RegisterRequestHandler(
base::Bind(&HandleRedirectRequest, "/redirect?"));
@@ -511,7 +529,7 @@ class PageTransitionResourceDispatcherHostDelegate
// when encountering a meta refresh tag.
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
PageTransitionClientRedirect) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(embedded_test_server()->Start());
PageTransitionResourceDispatcherHostDelegate delegate(
embedded_test_server()->GetURL("/title1.html"));
@@ -526,4 +544,215 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
delegate.page_transition() & ui::PAGE_TRANSITION_CLIENT_REDIRECT);
}
+namespace {
+
+// Checks whether the given urls are requested, and that IsUsingLofi() returns
+// the appropriate value when the Lo-Fi state is set.
+class LoFiModeResourceDispatcherHostDelegate
+ : public ResourceDispatcherHostDelegate {
+ public:
+ LoFiModeResourceDispatcherHostDelegate(const GURL& main_frame_url,
+ const GURL& subresource_url,
+ const GURL& iframe_url)
+ : main_frame_url_(main_frame_url),
+ subresource_url_(subresource_url),
+ iframe_url_(iframe_url),
+ main_frame_url_seen_(false),
+ subresource_url_seen_(false),
+ iframe_url_seen_(false),
+ use_lofi_(false),
+ should_enable_lofi_mode_called_(false) {}
+
+ ~LoFiModeResourceDispatcherHostDelegate() override {}
+
+ // ResourceDispatcherHostDelegate implementation:
+ void RequestBeginning(net::URLRequest* request,
+ ResourceContext* resource_context,
+ AppCacheService* appcache_service,
+ ResourceType resource_type,
+ ScopedVector<ResourceThrottle>* throttles) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
+ if (request->url() != main_frame_url_ && request->url() != subresource_url_
+ && request->url() != iframe_url_)
+ return;
+ if (request->url() == main_frame_url_) {
+ EXPECT_FALSE(main_frame_url_seen_);
+ main_frame_url_seen_ = true;
+ } else if (request->url() == subresource_url_) {
+ EXPECT_TRUE(main_frame_url_seen_);
+ EXPECT_FALSE(subresource_url_seen_);
+ subresource_url_seen_ = true;
+ } else if (request->url() == iframe_url_) {
+ EXPECT_TRUE(main_frame_url_seen_);
+ EXPECT_FALSE(iframe_url_seen_);
+ iframe_url_seen_ = true;
+ }
+ EXPECT_EQ(use_lofi_, info->IsUsingLoFi());
+ }
+
+ void SetDelegate() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ResourceDispatcherHost::Get()->SetDelegate(this);
+ }
+
+ bool ShouldEnableLoFiMode(
+ const net::URLRequest& request,
+ content::ResourceContext* resource_context) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ EXPECT_FALSE(should_enable_lofi_mode_called_);
+ should_enable_lofi_mode_called_ = true;
+ EXPECT_EQ(main_frame_url_, request.url());
+ return use_lofi_;
+ }
+
+ void Reset(bool use_lofi) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ main_frame_url_seen_ = false;
+ subresource_url_seen_ = false;
+ iframe_url_seen_ = false;
+ use_lofi_ = use_lofi;
+ should_enable_lofi_mode_called_ = false;
+ }
+
+ void CheckResourcesRequested(bool should_enable_lofi_mode_called) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ EXPECT_EQ(should_enable_lofi_mode_called, should_enable_lofi_mode_called_);
+ EXPECT_TRUE(main_frame_url_seen_);
+ EXPECT_TRUE(subresource_url_seen_);
+ EXPECT_TRUE(iframe_url_seen_);
+ }
+
+ private:
+ const GURL main_frame_url_;
+ const GURL subresource_url_;
+ const GURL iframe_url_;
+
+ bool main_frame_url_seen_;
+ bool subresource_url_seen_;
+ bool iframe_url_seen_;
+ bool use_lofi_;
+ bool should_enable_lofi_mode_called_;
+
+ DISALLOW_COPY_AND_ASSIGN(LoFiModeResourceDispatcherHostDelegate);
+};
+
+} // namespace
+
+class LoFiResourceDispatcherHostBrowserTest : public ContentBrowserTest {
+ public:
+ ~LoFiResourceDispatcherHostBrowserTest() override {}
+
+ protected:
+ void SetUpOnMainThread() override {
+ ContentBrowserTest::SetUpOnMainThread();
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ delegate_.reset(new LoFiModeResourceDispatcherHostDelegate(
+ embedded_test_server()->GetURL("/page_with_iframe.html"),
+ embedded_test_server()->GetURL("/image.jpg"),
+ embedded_test_server()->GetURL("/title1.html")));
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&LoFiModeResourceDispatcherHostDelegate::SetDelegate,
+ base::Unretained(delegate_.get())));
+ }
+
+ void Reset(bool use_lofi) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&LoFiModeResourceDispatcherHostDelegate::Reset,
+ base::Unretained(delegate_.get()), use_lofi));
+ }
+
+ void CheckResourcesRequested(
+ bool should_enable_lofi_mode_called) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(
+ &LoFiModeResourceDispatcherHostDelegate::CheckResourcesRequested,
+ base::Unretained(delegate_.get()), should_enable_lofi_mode_called));
+ }
+
+ private:
+ scoped_ptr<LoFiModeResourceDispatcherHostDelegate> delegate_;
+};
+
+// Test that navigating with ShouldEnableLoFiMode returning true fetches the
+// resources with LOFI_ON.
+IN_PROC_BROWSER_TEST_F(LoFiResourceDispatcherHostBrowserTest,
+ ShouldEnableLoFiModeOn) {
+ // Navigate with ShouldEnableLoFiMode returning true.
+ Reset(true);
+ NavigateToURLBlockUntilNavigationsComplete(
+ shell(), embedded_test_server()->GetURL("/page_with_iframe.html"), 1);
+ CheckResourcesRequested(true);
+}
+
+// Test that navigating with ShouldEnableLoFiMode returning false fetches the
+// resources with LOFI_OFF.
+IN_PROC_BROWSER_TEST_F(LoFiResourceDispatcherHostBrowserTest,
+ ShouldEnableLoFiModeOff) {
+ // Navigate with ShouldEnableLoFiMode returning false.
+ NavigateToURLBlockUntilNavigationsComplete(
+ shell(), embedded_test_server()->GetURL("/page_with_iframe.html"), 1);
+ CheckResourcesRequested(true);
+}
+
+// Test that reloading calls ShouldEnableLoFiMode again and changes the Lo-Fi
+// state.
+IN_PROC_BROWSER_TEST_F(LoFiResourceDispatcherHostBrowserTest,
+ ShouldEnableLoFiModeReload) {
+ // Navigate with ShouldEnableLoFiMode returning false.
+ NavigateToURLBlockUntilNavigationsComplete(
+ shell(), embedded_test_server()->GetURL("/page_with_iframe.html"), 1);
+ CheckResourcesRequested(true);
+
+ // Reload. ShouldEnableLoFiMode should be called.
+ Reset(true);
+ ReloadBlockUntilNavigationsComplete(shell(), 1);
+ CheckResourcesRequested(true);
+}
+
+// Test that navigating backwards calls ShouldEnableLoFiMode again and changes
+// the Lo-Fi state.
+IN_PROC_BROWSER_TEST_F(LoFiResourceDispatcherHostBrowserTest,
+ ShouldEnableLoFiModeNavigateBackThenForward) {
+ // Navigate with ShouldEnableLoFiMode returning false.
+ NavigateToURLBlockUntilNavigationsComplete(
+ shell(), embedded_test_server()->GetURL("/page_with_iframe.html"), 1);
+ CheckResourcesRequested(true);
+
+ // Go to a different page.
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+
+ // Go back with ShouldEnableLoFiMode returning true.
+ Reset(true);
+ TestNavigationObserver tab_observer(shell()->web_contents(), 1);
+ shell()->GoBackOrForward(-1);
+ tab_observer.Wait();
+ CheckResourcesRequested(true);
+}
+
+// Test that reloading with Lo-Fi disabled doesn't call ShouldEnableLoFiMode and
+// already has LOFI_OFF.
+IN_PROC_BROWSER_TEST_F(LoFiResourceDispatcherHostBrowserTest,
+ ShouldEnableLoFiModeReloadDisableLoFi) {
+ // Navigate with ShouldEnableLoFiMode returning true.
+ Reset(true);
+ NavigateToURLBlockUntilNavigationsComplete(
+ shell(), embedded_test_server()->GetURL("/page_with_iframe.html"), 1);
+ CheckResourcesRequested(true);
+
+ // Reload with Lo-Fi disabled.
+ Reset(false);
+ TestNavigationObserver tab_observer(shell()->web_contents(), 1);
+ shell()->web_contents()->GetController().ReloadDisableLoFi(true);
+ tab_observer.Wait();
+ CheckResourcesRequested(false);
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index 2d7512b63ae..529b9781866 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -6,8 +6,10 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include <stddef.h>
#include <algorithm>
#include <set>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -16,13 +18,16 @@
#include "base/compiler_specific.h"
#include "base/debug/alias.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/profiler/scoped_tracker.h"
#include "base/stl_util.h"
+#include "base/strings/string_util.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/time/time.h"
#include "content/browser/appcache/appcache_interceptor.h"
@@ -37,6 +42,7 @@
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/loader/async_resource_handler.h"
+#include "content/browser/loader/async_revalidation_manager.h"
#include "content/browser/loader/cross_site_resource_handler.h"
#include "content/browser/loader/detachable_resource_handler.h"
#include "content/browser/loader/mime_type_resource_handler.h"
@@ -54,6 +60,7 @@
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/resource_context_impl.h"
+#include "content/browser/service_worker/foreign_fetch_request_handler.h"
#include "content/browser/service_worker/service_worker_request_handler.h"
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_context.h"
@@ -77,6 +84,7 @@
#include "content/public/browser/stream_handle.h"
#include "content/public/browser/stream_info.h"
#include "content/public/browser/user_metrics.h"
+#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
#include "ipc/ipc_message_macros.h"
@@ -202,6 +210,7 @@ bool IsDetachableResourceType(ResourceType type) {
switch (type) {
case RESOURCE_TYPE_PREFETCH:
case RESOURCE_TYPE_PING:
+ case RESOURCE_TYPE_CSP_REPORT:
return true;
default:
return false;
@@ -429,13 +438,33 @@ void LogResourceRequestTimeOnUI(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHostImpl* host =
RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
- if (host != NULL) {
+ if (host != nullptr) {
DCHECK(host->frame_tree_node()->IsMainFrame());
host->frame_tree_node()->navigator()->LogResourceRequestTime(
timestamp, url);
}
}
+bool IsUsingLoFi(LoFiState lofi_state,
+ ResourceDispatcherHostDelegate* delegate,
+ const net::URLRequest& request,
+ ResourceContext* resource_context) {
+ if (lofi_state == LOFI_UNSPECIFIED && delegate)
+ return delegate->ShouldEnableLoFiMode(request, resource_context);
+ return lofi_state == LOFI_ON;
+}
+
+// Record RAPPOR for aborted main frame loads. Separate into a fast and
+// slow bucket because a shocking number of aborts happen under 100ms.
+void RecordAbortRapporOnUI(const GURL& url,
+ base::TimeDelta request_loading_time) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (request_loading_time.InMilliseconds() < 100)
+ GetContentClient()->browser()->RecordURLMetric("Net.ErrAborted.Fast", url);
+ else
+ GetContentClient()->browser()->RecordURLMetric("Net.ErrAborted.Slow", url);
+}
+
} // namespace
// static
@@ -473,6 +502,24 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl()
base::Unretained(this)));
update_load_states_timer_.reset(new base::RepeatingTimer());
+
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ // This needs to be called to mark the trial as active, even if the result
+ // isn't used.
+ std::string stale_while_revalidate_trial_group =
+ base::FieldTrialList::FindFullName("StaleWhileRevalidate");
+ // stale-while-revalidate currently doesn't work with browser-side navigation.
+ // Only enable stale-while-revalidate if browser navigation is not enabled.
+ //
+ // TODO(ricea): Make stale-while-revalidate and browser-side navigation work
+ // together. Or disable stale-while-revalidate completely before browser-side
+ // navigation becomes the default. crbug.com/561610
+ if (!IsBrowserSideNavigationEnabled() &&
+ (base::StartsWith(stale_while_revalidate_trial_group, "Enabled",
+ base::CompareCase::SENSITIVE) ||
+ command_line->HasSwitch(switches::kEnableStaleWhileRevalidate))) {
+ async_revalidation_manager_.reset(new AsyncRevalidationManager);
+ }
}
ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() {
@@ -578,6 +625,13 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
loaders_to_cancel.clear();
+ if (async_revalidation_manager_) {
+ // Cancelling async revalidations should not result in the creation of new
+ // requests. Do it before the CHECKs to ensure this does not happen.
+ async_revalidation_manager_->CancelAsyncRevalidationsForResourceContext(
+ context);
+ }
+
// Validate that no more requests for this context were added.
for (LoaderMap::const_iterator i = pending_loaders_.begin();
i != pending_loaders_.end(); ++i) {
@@ -607,7 +661,7 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
bool prefer_cache,
bool do_not_prompt_for_login,
scoped_ptr<DownloadSaveInfo> save_info,
- uint32 download_id,
+ uint32_t download_id,
const DownloadStartedCallback& started_callback) {
if (is_shutdown_)
return CallbackAndReturn(started_callback,
@@ -682,12 +736,11 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
// From this point forward, the |DownloadResourceHandler| is responsible for
// |started_callback|.
- scoped_ptr<ResourceHandler> handler(
- CreateResourceHandlerForDownload(request.get(), is_content_initiated,
- true, download_id, save_info.Pass(),
- started_callback));
+ scoped_ptr<ResourceHandler> handler(CreateResourceHandlerForDownload(
+ request.get(), is_content_initiated, true, download_id,
+ std::move(save_info), started_callback));
- BeginRequestInternal(request.Pass(), handler.Pass());
+ BeginRequestInternal(std::move(request), std::move(handler));
return DOWNLOAD_INTERRUPT_REASON_NONE;
}
@@ -715,14 +768,14 @@ ResourceDispatcherHostImpl::CreateResourceHandlerForDownload(
net::URLRequest* request,
bool is_content_initiated,
bool must_download,
- uint32 id,
+ uint32_t id,
scoped_ptr<DownloadSaveInfo> save_info,
const DownloadUrlParameters::OnStartedCallback& started_cb) {
- scoped_ptr<ResourceHandler> handler(
- new DownloadResourceHandler(id, request, started_cb, save_info.Pass()));
+ scoped_ptr<ResourceHandler> handler(new DownloadResourceHandler(
+ id, request, started_cb, std::move(save_info)));
if (delegate_) {
- const ResourceRequestInfo* request_info(
- ResourceRequestInfo::ForRequest(request));
+ const ResourceRequestInfoImpl* request_info(
+ ResourceRequestInfoImpl::ForRequest(request));
ScopedVector<ResourceThrottle> throttles;
delegate_->DownloadStarting(
@@ -730,12 +783,11 @@ ResourceDispatcherHostImpl::CreateResourceHandlerForDownload(
request_info->GetRouteID(), request_info->GetRequestID(),
is_content_initiated, must_download, &throttles);
if (!throttles.empty()) {
- handler.reset(
- new ThrottlingResourceHandler(
- handler.Pass(), request, throttles.Pass()));
+ handler.reset(new ThrottlingResourceHandler(std::move(handler), request,
+ std::move(throttles)));
}
}
- return handler.Pass();
+ return handler;
}
scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::MaybeInterceptAsStream(
@@ -774,8 +826,8 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::MaybeInterceptAsStream(
stream_info->response_headers =
new net::HttpResponseHeaders(response->head.headers->raw_headers());
}
- delegate_->OnStreamCreated(request, stream_info.Pass());
- return handler.Pass();
+ delegate_->OnStreamCreated(request, std::move(stream_info));
+ return std::move(handler);
}
ResourceDispatcherHostLoginDelegate*
@@ -804,8 +856,8 @@ bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader,
return false;
return delegate_->HandleExternalProtocol(
- url, info->GetChildID(), info->GetRouteID(), info->IsMainFrame(),
- info->GetPageTransition(), info->HasUserGesture());
+ url, info->GetChildID(), info->GetWebContentsGetterForRequest(),
+ info->IsMainFrame(), info->GetPageTransition(), info->HasUserGesture());
}
void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) {
@@ -826,6 +878,28 @@ void ResourceDispatcherHostImpl::DidReceiveRedirect(ResourceLoader* loader,
if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_host))
return;
+ net::URLRequest* request = loader->request();
+ if (request->response_info().async_revalidation_required) {
+ // Async revalidation is only supported for the first redirect leg.
+ DCHECK_EQ(request->url_chain().size(), 1u);
+ DCHECK(async_revalidation_manager_);
+
+ async_revalidation_manager_->BeginAsyncRevalidation(*request,
+ scheduler_.get());
+ }
+
+ // Remove the LOAD_SUPPORT_ASYNC_REVALIDATION flag if it is present.
+ // It is difficult to create a URLRequest with the correct flags and headers
+ // for redirect legs other than the first one. Since stale-while-revalidate in
+ // combination with redirects isn't needed for experimental use, punt on it
+ // for now.
+ // TODO(ricea): Fix this before launching the feature.
+ if (request->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION) {
+ int new_load_flags =
+ request->load_flags() & ~net::LOAD_SUPPORT_ASYNC_REVALIDATION;
+ request->SetLoadFlags(new_load_flags);
+ }
+
// Don't notify WebContents observers for requests known to be
// downloads; they aren't really associated with the Webcontents.
// Note that not all downloads are known before content sniffing.
@@ -854,6 +928,12 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
info->GetChildID(), info->GetRouteID());
}
+ if (request->response_info().async_revalidation_required) {
+ DCHECK(async_revalidation_manager_);
+ async_revalidation_manager_->BeginAsyncRevalidation(*request,
+ scheduler_.get());
+ }
+
int render_process_id, render_frame_host;
if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_host))
return;
@@ -875,7 +955,7 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
}
void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
- ResourceRequestInfo* info = loader->GetRequestInfo();
+ ResourceRequestInfoImpl* info = loader->GetRequestInfo();
// Record final result of all resource loads.
if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME) {
@@ -895,8 +975,19 @@ void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
"Net.RequestTime2.Success", request_loading_time);
break;
case net::ERR_ABORTED:
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ErrAborted.SentBytes",
+ loader->request()->GetTotalSentBytes(), 1,
+ 50000000, 50);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ErrAborted.ReceivedBytes",
+ loader->request()->GetTotalReceivedBytes(),
+ 1, 50000000, 50);
UMA_HISTOGRAM_LONG_TIMES(
"Net.RequestTime2.ErrAborted", request_loading_time);
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&RecordAbortRapporOnUI, loader->request()->url(),
+ request_loading_time));
break;
case net::ERR_CONNECTION_RESET:
UMA_HISTOGRAM_LONG_TIMES(
@@ -1046,10 +1137,11 @@ void ResourceDispatcherHostImpl::OnRequestResource(
"477117 ResourceDispatcherHostImpl::OnRequestResource"));
// When logging time-to-network only care about main frame and non-transfer
// navigations.
+ // PlzNavigate: this log happens from NavigationRequest::OnRequestStarted
+ // instead.
if (request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME &&
request_data.transferred_request_request_id == -1 &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation)) {
+ !IsBrowserSideNavigationEnabled()) {
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
@@ -1105,8 +1197,8 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
// ResourceHandlers should always get state related to the request from the
// ResourceRequestInfo rather than caching it locally. This lets us update
// the info object when a transfer occurs.
- info->UpdateForTransfer(child_id, route_id, request_data.origin_pid,
- request_id, request_data.parent_render_frame_id,
+ info->UpdateForTransfer(child_id, route_id, request_data.render_frame_id,
+ request_data.origin_pid, request_id,
filter_->GetWeakPtr());
// Update maps that used the old IDs, if necessary. Some transfers in tests
@@ -1163,8 +1255,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
int child_id = filter_->child_id();
// PlzNavigate: reject invalid renderer main resource request.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation) &&
+ if (IsBrowserSideNavigationEnabled() &&
IsResourceTypeFrame(request_data.resource_type) &&
!request_data.url.SchemeIs(url::kBlobScheme)) {
bad_message::ReceivedBadMessage(filter_, bad_message::RDH_INVALID_URL);
@@ -1207,7 +1298,8 @@ void ResourceDispatcherHostImpl::BeginRequest(
ResourceContext* resource_context = NULL;
net::URLRequestContext* request_context = NULL;
- filter_->GetContexts(request_data, &resource_context, &request_context);
+ filter_->GetContexts(request_data.resource_type, request_data.origin_pid,
+ &resource_context, &request_context);
// http://crbug.com/90971
CHECK(ContainsKey(active_resource_contexts_, resource_context));
@@ -1239,6 +1331,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
new_request->set_method(request_data.method);
new_request->set_first_party_for_cookies(
request_data.first_party_for_cookies);
+ new_request->set_initiator(request_data.request_initiator);
// If the request is a MAIN_FRAME request, the first-party URL gets updated on
// redirects.
@@ -1312,6 +1405,13 @@ void ResourceDispatcherHostImpl::BeginRequest(
load_flags |= net::LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
}
+ bool support_async_revalidation =
+ !is_sync_load && async_revalidation_manager_ &&
+ AsyncRevalidationManager::QualifiesForAsyncRevalidation(request_data);
+
+ if (support_async_revalidation)
+ load_flags |= net::LOAD_SUPPORT_ASYNC_REVALIDATION;
+
// Sync loads should have maximum priority and should be the only
// requets that have the ignore limits flag set.
if (is_sync_load) {
@@ -1331,7 +1431,6 @@ void ResourceDispatcherHostImpl::BeginRequest(
request_data.render_frame_id,
request_data.is_main_frame,
request_data.parent_is_main_frame,
- request_data.parent_render_frame_id,
request_data.resource_type,
request_data.transition_type,
request_data.should_replace_current_entry,
@@ -1346,7 +1445,10 @@ void ResourceDispatcherHostImpl::BeginRequest(
request_data.visiblity_state,
resource_context, filter_->GetWeakPtr(),
report_raw_headers,
- !is_sync_load);
+ !is_sync_load,
+ IsUsingLoFi(request_data.lofi_state, delegate_,
+ *new_request, resource_context),
+ support_async_revalidation ? request_data.headers : std::string());
// Request takes ownership.
extra_info->AssociateWithRequest(new_request.get());
@@ -1361,15 +1463,29 @@ void ResourceDispatcherHostImpl::BeginRequest(
// Initialize the service worker handler for the request. We don't use
// ServiceWorker for synchronous loads to avoid renderer deadlocks.
+ const bool should_skip_service_worker =
+ request_data.skip_service_worker || is_sync_load;
ServiceWorkerRequestHandler::InitializeHandler(
new_request.get(), filter_->service_worker_context(), blob_context,
child_id, request_data.service_worker_provider_id,
- request_data.skip_service_worker || is_sync_load,
+ should_skip_service_worker,
request_data.fetch_request_mode, request_data.fetch_credentials_mode,
request_data.fetch_redirect_mode, request_data.resource_type,
request_data.fetch_request_context_type, request_data.fetch_frame_type,
request_data.request_body);
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures)) {
+ ForeignFetchRequestHandler::InitializeHandler(
+ new_request.get(), filter_->service_worker_context(), blob_context,
+ child_id, request_data.service_worker_provider_id,
+ should_skip_service_worker,
+ request_data.fetch_request_mode, request_data.fetch_credentials_mode,
+ request_data.fetch_redirect_mode, request_data.resource_type,
+ request_data.fetch_request_context_type, request_data.fetch_frame_type,
+ request_data.request_body);
+ }
+
// Have the appcache associate its extra info with the request.
AppCacheInterceptor::SetExtraRequestInfo(
new_request.get(), filter_->appcache_service(), child_id,
@@ -1383,7 +1499,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
resource_context));
if (handler)
- BeginRequestInternal(new_request.Pass(), handler.Pass());
+ BeginRequestInternal(std::move(new_request), std::move(handler));
}
scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler(
@@ -1414,7 +1530,7 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler(
// The RedirectToFileResourceHandler depends on being next in the chain.
if (request_data.download_to_file) {
handler.reset(
- new RedirectToFileResourceHandler(handler.Pass(), request));
+ new RedirectToFileResourceHandler(std::move(handler), request));
}
}
@@ -1423,15 +1539,14 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler(
handler.reset(new DetachableResourceHandler(
request,
base::TimeDelta::FromMilliseconds(kDefaultDetachableCancelDelayMs),
- handler.Pass()));
+ std::move(handler)));
}
// PlzNavigate: If using --enable-browser-side-navigation, the
// CrossSiteResourceHandler is not needed. This codepath is not used for the
// actual navigation request, but only the subsequent blob URL load. This does
// not require request transfers.
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation)) {
+ if (!IsBrowserSideNavigationEnabled()) {
// Install a CrossSiteResourceHandler for all main frame requests. This will
// check whether a transfer is required and, if so, pause for the UI thread
// to drive the transfer.
@@ -1446,12 +1561,12 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler(
request_data.resource_type == RESOURCE_TYPE_SUB_FRAME;
}
if (is_swappable_navigation && process_type == PROCESS_TYPE_RENDERER)
- handler.reset(new CrossSiteResourceHandler(handler.Pass(), request));
+ handler.reset(new CrossSiteResourceHandler(std::move(handler), request));
}
return AddStandardHandlers(request, request_data.resource_type,
resource_context, filter_->appcache_service(),
- child_id, route_id, handler.Pass());
+ child_id, route_id, std::move(handler));
}
scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::AddStandardHandlers(
@@ -1465,11 +1580,10 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::AddStandardHandlers(
// PlzNavigate: do not add ResourceThrottles for main resource requests from
// the renderer. Decisions about the navigation should have been done in the
// initial request.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation) &&
- IsResourceTypeFrame(resource_type) && child_id != -1) {
+ if (IsBrowserSideNavigationEnabled() && IsResourceTypeFrame(resource_type) &&
+ child_id != -1) {
DCHECK(request->url().SchemeIs(url::kBlobScheme));
- return handler.Pass();
+ return handler;
}
PluginService* plugin_service = nullptr;
@@ -1477,7 +1591,7 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::AddStandardHandlers(
plugin_service = PluginService::GetInstance();
#endif
// Insert a buffered event handler before the actual one.
- handler.reset(new MimeTypeResourceHandler(handler.Pass(), this,
+ handler.reset(new MimeTypeResourceHandler(std::move(handler), this,
plugin_service, request));
ScopedVector<ResourceThrottle> throttles;
@@ -1485,11 +1599,8 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::AddStandardHandlers(
// Add a NavigationResourceThrottle for navigations.
// PlzNavigate: the throttle is unnecessary as communication with the UI
// thread is handled by the NavigationURLloader.
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation) &&
- IsResourceTypeFrame(resource_type)) {
+ if (!IsBrowserSideNavigationEnabled() && IsResourceTypeFrame(resource_type))
throttles.push_back(new NavigationResourceThrottle(request));
- }
if (delegate_) {
delegate_->RequestBeginning(request,
@@ -1501,7 +1612,8 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::AddStandardHandlers(
if (request->has_upload()) {
// Block power save while uploading data.
- throttles.push_back(new PowerSaveBlockResourceThrottle());
+ throttles.push_back(
+ new PowerSaveBlockResourceThrottle(request->url().host()));
}
// TODO(ricea): Stop looking this up so much.
@@ -1509,10 +1621,10 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::AddStandardHandlers(
throttles.push_back(scheduler_->ScheduleRequest(child_id, route_id,
info->IsAsync(), request));
- handler.reset(
- new ThrottlingResourceHandler(handler.Pass(), request, throttles.Pass()));
+ handler.reset(new ThrottlingResourceHandler(std::move(handler), request,
+ std::move(throttles)));
- return handler.Pass();
+ return handler;
}
void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) {
@@ -1616,7 +1728,6 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
render_frame_route_id,
false, // is_main_frame
false, // parent_is_main_frame
- -1, // parent_render_frame_id
RESOURCE_TYPE_SUB_RESOURCE,
ui::PAGE_TRANSITION_LINK,
false, // should_replace_current_entry
@@ -1632,7 +1743,9 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
context,
base::WeakPtr<ResourceMessageFilter>(), // filter
false, // report_raw_headers
- true); // is_async
+ true, // is_async
+ false, // is_using_lofi
+ std::string()); // original_headers
}
void ResourceDispatcherHostImpl::OnRenderViewHostCreated(int child_id,
@@ -1679,13 +1792,14 @@ void ResourceDispatcherHostImpl::OnAudioRenderHostStreamStateChanged(
}
// This function is only used for saving feature.
-void ResourceDispatcherHostImpl::BeginSaveFile(
- const GURL& url,
- const Referrer& referrer,
- int child_id,
- int render_view_route_id,
- int render_frame_route_id,
- ResourceContext* context) {
+void ResourceDispatcherHostImpl::BeginSaveFile(const GURL& url,
+ const Referrer& referrer,
+ SaveItemId save_item_id,
+ SavePackageId save_package_id,
+ int child_id,
+ int render_view_route_id,
+ int render_frame_route_id,
+ ResourceContext* context) {
if (is_shutdown_)
return;
@@ -1723,14 +1837,11 @@ void ResourceDispatcherHostImpl::BeginSaveFile(
render_frame_route_id, false, context);
extra_info->AssociateWithRequest(request.get()); // Request takes ownership.
- scoped_ptr<ResourceHandler> handler(
- new SaveFileResourceHandler(request.get(),
- child_id,
- render_frame_route_id,
- url,
- save_file_manager_.get()));
+ scoped_ptr<ResourceHandler> handler(new SaveFileResourceHandler(
+ request.get(), save_item_id, save_package_id, child_id,
+ render_frame_route_id, url, save_file_manager_.get()));
- BeginRequestInternal(request.Pass(), handler.Pass());
+ BeginRequestInternal(std::move(request), std::move(handler));
}
void ResourceDispatcherHostImpl::MarkAsTransferredNavigation(
@@ -1957,11 +2068,11 @@ void ResourceDispatcherHostImpl::FinishedWithResourcesForRequest(
void ResourceDispatcherHostImpl::BeginNavigationRequest(
ResourceContext* resource_context,
const NavigationRequestInfo& info,
- NavigationURLLoaderImplCore* loader) {
+ NavigationURLLoaderImplCore* loader,
+ ServiceWorkerNavigationHandleCore* service_worker_handle_core) {
// PlzNavigate: BeginNavigationRequest currently should only be used for the
// browser-side navigations project.
- CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation));
+ CHECK(IsBrowserSideNavigationEnabled());
ResourceType resource_type = info.is_main_frame ?
RESOURCE_TYPE_MAIN_FRAME : RESOURCE_TYPE_SUB_FRAME;
@@ -2009,6 +2120,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
new_request->set_method(info.begin_params.method);
new_request->set_first_party_for_cookies(
info.first_party_for_cookies);
+ new_request->set_initiator(info.request_initiator);
if (info.is_main_frame) {
new_request->set_first_party_url_policy(
net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT);
@@ -2022,10 +2134,11 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
new_request->SetLoadFlags(load_flags);
+ storage::BlobStorageContext* blob_context = GetBlobStorageContext(
+ GetChromeBlobStorageContextForResourceContext(resource_context));
+
// Resolve elements from request_body and prepare upload data.
if (info.request_body.get()) {
- storage::BlobStorageContext* blob_context = GetBlobStorageContext(
- GetChromeBlobStorageContextForResourceContext(resource_context));
AttachRequestBodyBlobDataHandles(
info.request_body.get(),
blob_context);
@@ -2054,18 +2167,14 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
-1, // request_data.origin_pid,
request_id_,
-1, // request_data.render_frame_id,
- info.is_main_frame,
- info.parent_is_main_frame,
- -1, // request_data.parent_render_frame_id,
- resource_type,
- info.common_params.transition,
+ info.is_main_frame, info.parent_is_main_frame,
+ resource_type, info.common_params.transition,
// should_replace_current_entry. This was only maintained at layer for
// request transfers and isn't needed for browser-side navigations.
false,
false, // is download
false, // is stream
- info.common_params.allow_download,
- info.begin_params.has_user_gesture,
+ info.common_params.allow_download, info.begin_params.has_user_gesture,
true, // enable_load_timing
false, // enable_upload_progress
false, // do_not_prompt_for_login
@@ -2073,26 +2182,37 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
// TODO(davidben): This is only used for prerenders. Replace
// is_showing with something for that. Or maybe it just comes from the
// same mechanism as the cookie one.
- blink::WebPageVisibilityStateVisible,
- resource_context,
+ blink::WebPageVisibilityStateVisible, resource_context,
base::WeakPtr<ResourceMessageFilter>(), // filter
false, // request_data.report_raw_headers
- true);
+ true, // is_async
+ IsUsingLoFi(info.common_params.lofi_state, delegate_,
+ *new_request, resource_context),
+ // The original_headers field is for stale-while-revalidate but the
+ // feature doesn't work with PlzNavigate, so it's just a placeholder
+ // here.
+ // TODO(ricea): Make the feature work with stale-while-revalidate
+ // and clean this up.
+ std::string()); // original_headers
// Request takes ownership.
extra_info->AssociateWithRequest(new_request.get());
if (new_request->url().SchemeIs(url::kBlobScheme)) {
// Hang on to a reference to ensure the blob is not released prior
// to the job being started.
- ChromeBlobStorageContext* blob_context =
- GetChromeBlobStorageContextForResourceContext(resource_context);
storage::BlobProtocolHandler::SetRequestedBlobDataHandle(
new_request.get(),
- blob_context->context()->GetBlobDataFromPublicURL(new_request->url()));
+ blob_context->GetBlobDataFromPublicURL(new_request->url()));
}
- // TODO(davidben): Attach ServiceWorkerRequestHandler.
- // TODO(michaeln): Help out with this and that.
+ RequestContextFrameType frame_type =
+ info.is_main_frame ? REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL
+ : REQUEST_CONTEXT_FRAME_TYPE_NESTED;
+ ServiceWorkerRequestHandler::InitializeForNavigation(
+ new_request.get(), service_worker_handle_core, blob_context,
+ info.begin_params.skip_service_worker, resource_type,
+ info.begin_params.request_context_type, frame_type, info.request_body);
+
// TODO(davidben): Attach AppCacheInterceptor.
scoped_ptr<ResourceHandler> handler(new NavigationResourceHandler(
@@ -2101,14 +2221,19 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
// TODO(davidben): Pass in the appropriate appcache_service. Also fix the
// dependency on child_id/route_id. Those are used by the ResourceScheduler;
// currently it's a no-op.
- handler = AddStandardHandlers(new_request.get(), resource_type,
- resource_context,
- nullptr, // appcache_service
- -1, // child_id
- -1, // route_id
- handler.Pass());
+ handler =
+ AddStandardHandlers(new_request.get(), resource_type, resource_context,
+ nullptr, // appcache_service
+ -1, // child_id
+ -1, // route_id
+ std::move(handler));
+
+ BeginRequestInternal(std::move(new_request), std::move(handler));
+}
- BeginRequestInternal(new_request.Pass(), handler.Pass());
+void ResourceDispatcherHostImpl::EnableStaleWhileRevalidateForTesting() {
+ if (!async_revalidation_manager_)
+ async_revalidation_manager_.reset(new AsyncRevalidationManager);
}
// static
@@ -2166,7 +2291,7 @@ void ResourceDispatcherHostImpl::BeginRequestInternal(
}
linked_ptr<ResourceLoader> loader(
- new ResourceLoader(request.Pass(), handler.Pass(), this));
+ new ResourceLoader(std::move(request), std::move(handler), this));
GlobalRoutingID id(info->GetGlobalRoutingID());
BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.find(id);
@@ -2210,11 +2335,11 @@ bool ResourceDispatcherHostImpl::LoadInfoIsMoreInteresting(const LoadInfo& a,
// Set |*_uploading_size| to be the size of the corresponding upload body if
// it's currently being uploaded.
- uint64 a_uploading_size = 0;
+ uint64_t a_uploading_size = 0;
if (a.load_state.state == net::LOAD_STATE_SENDING_REQUEST)
a_uploading_size = a.upload_size;
- uint64 b_uploading_size = 0;
+ uint64_t b_uploading_size = 0;
if (b.load_state.state == net::LOAD_STATE_SENDING_REQUEST)
b_uploading_size = b.upload_size;
@@ -2269,7 +2394,7 @@ ResourceDispatcherHostImpl::GetLoadInfoForAllRoutes() {
(*info_map)[id] = load_info;
}
}
- return info_map.Pass();
+ return info_map;
}
void ResourceDispatcherHostImpl::UpdateLoadInfo() {
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index 7772917990c..74922647f29 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -12,19 +12,22 @@
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_DISPATCHER_HOST_IMPL_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_DISPATCHER_HOST_IMPL_H_
+#include <stdint.h>
+
#include <map>
#include <set>
#include <string>
#include <vector>
-#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
+#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/browser/download/download_resource_handler.h"
+#include "content/browser/download/save_types.h"
#include "content/browser/loader/global_routing_id.h"
#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_loader_delegate.h"
@@ -60,6 +63,7 @@ class ShareableFileReference;
namespace content {
class AppCacheService;
+class AsyncRevalidationManager;
class NavigationURLLoaderImplCore;
class ResourceContext;
class ResourceDispatcherHostDelegate;
@@ -67,6 +71,7 @@ class ResourceMessageDelegate;
class ResourceMessageFilter;
class ResourceRequestInfoImpl;
class SaveFileManager;
+class ServiceWorkerNavigationHandleCore;
class WebContentsImpl;
struct CommonNavigationParams;
struct DownloadSaveInfo;
@@ -98,7 +103,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
bool prefer_cache,
bool do_not_prompt_for_login,
scoped_ptr<DownloadSaveInfo> save_info,
- uint32 download_id,
+ uint32_t download_id,
const DownloadStartedCallback& started_callback) override;
void ClearLoginDelegateForRequest(net::URLRequest* request) override;
void BlockRequestsForRoute(int child_id, int route_id) override;
@@ -127,6 +132,8 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// request from the renderer or another child process).
void BeginSaveFile(const GURL& url,
const Referrer& referrer,
+ SaveItemId save_item_id,
+ SavePackageId save_package_id,
int child_id,
int render_view_route_id,
int render_frame_route_id,
@@ -236,7 +243,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
net::URLRequest* request,
bool is_content_initiated,
bool must_download,
- uint32 id,
+ uint32_t id,
scoped_ptr<DownloadSaveInfo> save_info,
const DownloadUrlParameters::OnStartedCallback& started_cb);
@@ -273,9 +280,15 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// PlzNavigate: Begins a request for NavigationURLLoader. |loader| is the
// loader to attach to the leaf resource handler.
- void BeginNavigationRequest(ResourceContext* resource_context,
- const NavigationRequestInfo& info,
- NavigationURLLoaderImplCore* loader);
+ void BeginNavigationRequest(
+ ResourceContext* resource_context,
+ const NavigationRequestInfo& info,
+ NavigationURLLoaderImplCore* loader,
+ ServiceWorkerNavigationHandleCore* service_worker_handle_core);
+
+ // Turns on stale-while-revalidate support, regardless of command-line flags
+ // or experiment status. For unit tests only.
+ void EnableStaleWhileRevalidateForTesting();
private:
friend class ResourceDispatcherHostTest;
@@ -301,8 +314,8 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
struct LoadInfo {
GURL url;
net::LoadStateWithParam load_state;
- uint64 upload_position;
- uint64 upload_size;
+ uint64_t upload_position;
+ uint64_t upload_size;
};
// Map from ProcessID+RouteID pair to the "most interesting" LoadState.
@@ -585,6 +598,10 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
bool allow_cross_origin_auth_prompt_;
+ // AsyncRevalidationManager is non-NULL if and only if
+ // stale-while-revalidate is enabled.
+ scoped_ptr<AsyncRevalidationManager> async_revalidation_manager_;
+
// http://crbug.com/90971 - Assists in tracking down use-after-frees on
// shutdown.
std::set<const ResourceContext*> active_resource_contexts_;
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index da62f4a89ad..7fbe3995c21 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -2,14 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <stddef.h>
+#include <utility>
#include <vector>
-#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
+#include "base/macros.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/shared_memory.h"
#include "base/pickle.h"
@@ -38,8 +39,8 @@
#include "content/public/browser/resource_throttle.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
-#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
#include "content/public/common/resource_response.h"
#include "content/public/test/test_browser_context.h"
@@ -51,6 +52,7 @@
#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/http/http_util.h"
+#include "net/test/url_request/url_request_failed_job.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job.h"
@@ -151,7 +153,6 @@ static ResourceHostMsg_Request CreateResourceRequest(const char* method,
request.should_reset_appcache = false;
request.is_main_frame = true;
request.parent_is_main_frame = false;
- request.parent_render_frame_id = -1;
request.transition_type = ui::PAGE_TRANSITION_LINK;
request.allow_download = true;
return request;
@@ -181,6 +182,7 @@ class ResourceIPCAccumulator {
// within the groups will be in the order that they appeared.
// Note that this clears messages_. The caller takes ownership of any
// SharedMemoryHandles in messages placed into |msgs|.
+ // TODO(mmenke): This seems really fragile. Consider reworking ownership.
typedef std::vector< std::vector<IPC::Message> > ClassifiedMessages;
void GetClassifiedMessages(ClassifiedMessages* msgs);
@@ -253,7 +255,8 @@ class TestFilterSpecifyingChild : public ResourceMessageFilter {
~TestFilterSpecifyingChild() override {}
private:
- void GetContexts(const ResourceHostMsg_Request& request,
+ void GetContexts(ResourceType resource_type,
+ int origin_pid,
ResourceContext** resource_context,
net::URLRequestContext** request_context) {
*resource_context = resource_context_;
@@ -340,12 +343,6 @@ class URLRequestTestDelayedStartJob : public net::URLRequestTestJob {
}
URLRequestTestDelayedStartJob(net::URLRequest* request,
net::NetworkDelegate* network_delegate,
- bool auto_advance)
- : net::URLRequestTestJob(request, network_delegate, auto_advance) {
- Init();
- }
- URLRequestTestDelayedStartJob(net::URLRequest* request,
- net::NetworkDelegate* network_delegate,
const std::string& response_headers,
const std::string& response_data,
bool auto_advance)
@@ -534,6 +531,7 @@ class TestURLRequestJobFactory : public net::URLRequestJobFactory {
public:
explicit TestURLRequestJobFactory(ResourceDispatcherHostTest* test_fixture)
: test_fixture_(test_fixture),
+ hang_after_start_(false),
delay_start_(false),
delay_complete_(false),
network_start_notification_(false),
@@ -548,6 +546,11 @@ class TestURLRequestJobFactory : public net::URLRequestJobFactory {
return url_request_jobs_created_count_;
}
+ // When set, jobs will hang eternally once started.
+ void SetHangAfterStartJobGeneration(bool hang_after_start) {
+ hang_after_start_ = hang_after_start;
+ }
+
void SetDelayedStartJobGeneration(bool delay_job_start) {
delay_start_ = delay_job_start;
}
@@ -588,6 +591,7 @@ class TestURLRequestJobFactory : public net::URLRequestJobFactory {
private:
ResourceDispatcherHostTest* test_fixture_;
+ bool hang_after_start_;
bool delay_start_;
bool delay_complete_;
bool network_start_notification_;
@@ -945,6 +949,9 @@ class ResourceDispatcherHostTest : public testing::Test,
ResourceType type);
void MakeWebContentsAssociatedTestRequest(int request_id, const GURL& url);
+ void MakeWebContentsAssociatedTestRequestWithResourceType(int request_id,
+ const GURL& url,
+ ResourceType type);
// Generates a request with the given priority.
void MakeTestRequestWithPriority(int render_view_id,
@@ -974,11 +981,10 @@ class ResourceDispatcherHostTest : public testing::Test,
}
// Sets a particular response for any request from now on. To switch back to
- // the default bahavior, pass an empty |headers|. |headers| should be raw-
- // formatted (NULLs instead of EOLs).
+ // the default bahavior, pass an empty |headers|. |headers| should be CR[LF]
+ // terminated.
void SetResponse(const std::string& headers, const std::string& data) {
- response_headers_ = net::HttpUtil::AssembleRawHeaders(headers.data(),
- headers.size());
+ response_headers_ = headers;
response_data_ = data;
}
void SetResponse(const std::string& headers) {
@@ -1070,8 +1076,15 @@ void ResourceDispatcherHostTest::MakeTestRequestWithResourceType(
void ResourceDispatcherHostTest::MakeWebContentsAssociatedTestRequest(
int request_id,
const GURL& url) {
- ResourceHostMsg_Request request =
- CreateResourceRequest("GET", RESOURCE_TYPE_SUB_RESOURCE, url);
+ MakeWebContentsAssociatedTestRequestWithResourceType(
+ request_id, url, RESOURCE_TYPE_SUB_RESOURCE);
+}
+
+void ResourceDispatcherHostTest::
+ MakeWebContentsAssociatedTestRequestWithResourceType(int request_id,
+ const GURL& url,
+ ResourceType type) {
+ ResourceHostMsg_Request request = CreateResourceRequest("GET", type, url);
request.origin_pid = web_contents_->GetRenderProcessHost()->GetID();
request.render_frame_id = web_contents_->GetMainFrame()->GetRoutingID();
ResourceHostMsg_RequestResource msg(web_contents_->GetRoutingID(), request_id,
@@ -1100,19 +1113,14 @@ void ResourceDispatcherHostTest::MakeWebContentsAssociatedDownloadRequest(
browser_context_->GetResourceContext()->GetRequestContext();
scoped_ptr<net::URLRequest> request(
request_context->CreateRequest(url, net::DEFAULT_PRIORITY, NULL));
- host_.BeginDownload(
- request.Pass(),
- Referrer(),
- false, // is_content_initiated
- browser_context_->GetResourceContext(),
- web_contents_->GetRenderProcessHost()->GetID(),
- web_contents_->GetRoutingID(),
- web_contents_->GetMainFrame()->GetRoutingID(),
- false,
- false,
- save_info.Pass(),
- DownloadItem::kInvalidId,
- ResourceDispatcherHostImpl::DownloadStartedCallback());
+ host_.BeginDownload(std::move(request), Referrer(),
+ false, // is_content_initiated
+ browser_context_->GetResourceContext(),
+ web_contents_->GetRenderProcessHost()->GetID(),
+ web_contents_->GetRoutingID(),
+ web_contents_->GetMainFrame()->GetRoutingID(), false,
+ false, std::move(save_info), DownloadItem::kInvalidId,
+ ResourceDispatcherHostImpl::DownloadStartedCallback());
}
void ResourceDispatcherHostTest::CancelRequest(int request_id) {
@@ -1669,9 +1677,6 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
child_ids_.insert(test_filter->child_id());
// request 1 goes to the test delegate
- ResourceHostMsg_Request request = CreateResourceRequest(
- "GET", RESOURCE_TYPE_SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
-
MakeTestRequestWithResourceType(test_filter.get(), 0, 1,
net::URLRequestTestJob::test_url_1(),
RESOURCE_TYPE_SUB_RESOURCE);
@@ -1741,6 +1746,55 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
EXPECT_EQ(0, network_delegate()->error_count());
}
+// Tests whether the correct requests get canceled when a RenderViewHost is
+// deleted.
+TEST_F(ResourceDispatcherHostTest, CancelRequestsOnRenderViewHostDeleted) {
+ // Requests all hang once started. This prevents requests from being
+ // destroyed due to completion.
+ job_factory_->SetHangAfterStartJobGeneration(true);
+ HandleScheme("http");
+
+ TestResourceDispatcherHostDelegate delegate;
+ host_.SetDelegate(&delegate);
+ host_.OnRenderViewHostCreated(filter_->child_id(), 0, true, false);
+
+ // One RenderView issues a high priority request and a low priority one. Both
+ // should be started.
+ MakeTestRequestWithPriority(0, 1, net::HIGHEST);
+ MakeTestRequestWithPriority(0, 2, net::LOWEST);
+ KickOffRequest();
+ EXPECT_EQ(2, network_delegate_.created_requests());
+ EXPECT_EQ(0, network_delegate_.canceled_requests());
+
+ // The same RenderView issues two more low priority requests. The
+ // ResourceScheduler shouldn't let them start immediately.
+ MakeTestRequestWithPriority(0, 3, net::LOWEST);
+ MakeTestRequestWithPriority(0, 4, net::LOWEST);
+ KickOffRequest();
+ EXPECT_EQ(2, network_delegate_.created_requests());
+ EXPECT_EQ(0, network_delegate_.canceled_requests());
+
+ // Another RenderView in the same process as the old one issues a request,
+ // which is then started.
+ MakeTestRequestWithPriority(1, 5, net::LOWEST);
+ KickOffRequest();
+ EXPECT_EQ(3, network_delegate_.created_requests());
+ EXPECT_EQ(0, network_delegate_.canceled_requests());
+
+ // The first RenderView is destroyed. All 4 of its requests should be
+ // cancelled, and none of the two deferred requests should be started.
+ host_.OnRenderViewHostDeleted(filter_->child_id(), 0);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(3, network_delegate_.created_requests());
+ EXPECT_EQ(4, network_delegate_.canceled_requests());
+
+ // No messages should have been sent, since none of the jobs made any
+ // progress.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+ EXPECT_EQ(0U, msgs.size());
+}
+
TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
MakeTestRequestWithResourceType(filter_.get(), 0, 1,
net::URLRequestTestJob::test_url_4(),
@@ -1989,7 +2043,7 @@ TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
scoped_ptr<net::UploadElementReader> reader(new net::UploadBytesElementReader(
upload_content.data(), upload_content.size()));
req->set_upload(
- net::ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0));
+ net::ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
// Since the upload throttling is disabled, this has no effect on the cost.
EXPECT_EQ(
@@ -2389,7 +2443,6 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextDetached) {
TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
EXPECT_EQ(0, host_.pending_requests());
- int render_view_id = 0;
int request_id = 1;
std::string raw_headers("HTTP/1.1 200 OK\n"
@@ -2399,17 +2452,16 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
SetResponse(raw_headers, response_data);
HandleScheme("http");
- MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
- GURL("http://example.com/blah"),
- RESOURCE_TYPE_MAIN_FRAME);
-
+ MakeWebContentsAssociatedTestRequestWithResourceType(
+ request_id, GURL("http://example.com/blah"), RESOURCE_TYPE_MAIN_FRAME);
- GlobalRequestID global_request_id(filter_->child_id(), request_id);
+ GlobalRequestID global_request_id(web_contents_filter_->child_id(),
+ request_id);
host_.MarkAsTransferredNavigation(global_request_id);
// And now simulate a cancellation coming from the renderer.
ResourceHostMsg_CancelRequest msg(request_id);
- host_.OnMessageReceived(msg, filter_.get());
+ host_.OnMessageReceived(msg, web_contents_filter_.get());
// Since the request is marked as being transferred,
// the cancellation above should have been ignored and the request
@@ -2417,19 +2469,18 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
EXPECT_EQ(1, host_.pending_requests());
// Cancelling by other methods shouldn't work either.
- host_.CancelRequestsForProcess(render_view_id);
+ host_.CancelRequestsForProcess(web_contents_->GetRoutingID());
EXPECT_EQ(1, host_.pending_requests());
// Cancelling by context should work.
- host_.CancelRequestsForContext(filter_->resource_context());
+ host_.CancelRequestsForContext(web_contents_filter_->resource_context());
EXPECT_EQ(0, host_.pending_requests());
}
// Test transferred navigations with text/html, which doesn't trigger any
// content sniffing.
TEST_F(ResourceDispatcherHostTest, TransferNavigationHtml) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation)) {
+ if (IsBrowserSideNavigationEnabled()) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
}
@@ -2503,8 +2554,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationHtml) {
// Test transferring two navigations with text/html, to ensure the resource
// accounting works.
TEST_F(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation)) {
+ if (IsBrowserSideNavigationEnabled()) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
}
@@ -2591,8 +2641,7 @@ TEST_F(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
// MimeTypeResourceHandler to buffer the response to sniff the content before
// the transfer occurs.
TEST_F(ResourceDispatcherHostTest, TransferNavigationText) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation)) {
+ if (IsBrowserSideNavigationEnabled()) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
}
@@ -2666,8 +2715,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationText) {
}
TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation)) {
+ if (IsBrowserSideNavigationEnabled()) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
}
@@ -2757,8 +2805,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
}
TEST_F(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBrowserSideNavigation)) {
+ if (IsBrowserSideNavigationEnabled()) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
}
@@ -3444,10 +3491,14 @@ net::URLRequestJob* TestURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
if (test_fixture_->loader_test_request_info_) {
DCHECK_EQ(test_fixture_->loader_test_request_info_->url, request->url());
scoped_ptr<LoadInfoTestRequestInfo> info =
- test_fixture_->loader_test_request_info_.Pass();
+ std::move(test_fixture_->loader_test_request_info_);
return new URLRequestLoadInfoJob(request, network_delegate,
info->load_state, info->upload_progress);
}
+ if (hang_after_start_) {
+ return new net::URLRequestFailedJob(request, network_delegate,
+ net::ERR_IO_PENDING);
+ }
if (test_fixture_->response_headers_.empty()) {
if (delay_start_) {
return new URLRequestTestDelayedStartJob(request, network_delegate);
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index 64f5e7b341b..eee044c6aaf 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/resource_loader.h"
+#include <utility>
+
#include "base/command_line.h"
#include "base/location.h"
#include "base/metrics/histogram.h"
@@ -35,6 +37,8 @@
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h"
#include "net/ssl/client_cert_store.h"
+#include "net/ssl/ssl_platform_key.h"
+#include "net/ssl/ssl_private_key.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request_status.h"
@@ -94,6 +98,10 @@ void PopulateResourceResponse(ResourceRequestInfoImpl* info,
response->head.was_fetched_via_proxy = request->was_fetched_via_proxy();
response->head.proxy_server = response_info.proxy_server;
response->head.socket_address = request->GetSocketAddress();
+ const content::ResourceRequestInfo* request_info =
+ content::ResourceRequestInfo::ForRequest(request);
+ if (request_info)
+ response->head.is_using_lofi = request_info->IsUsingLoFi();
if (ServiceWorkerRequestHandler* handler =
ServiceWorkerRequestHandler::GetHandler(request)) {
handler->GetExtraResponseInfo(&response->head);
@@ -109,6 +117,9 @@ void PopulateResourceResponse(ResourceRequestInfoImpl* info,
GetSSLStatusForRequest(request->url(), request->ssl_info(),
info->GetChildID(), &ssl_status);
response->head.security_info = SerializeSecurityInfo(ssl_status);
+ response->head.has_major_certificate_errors =
+ net::IsCertStatusError(ssl_status.cert_status) &&
+ !net::IsCertStatusMinorError(ssl_status.cert_status);
} else {
// We should not have any SSL state.
DCHECK(!request->ssl_info().cert_status);
@@ -124,8 +135,8 @@ ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request,
scoped_ptr<ResourceHandler> handler,
ResourceLoaderDelegate* delegate)
: deferred_stage_(DEFERRED_NONE),
- request_(request.Pass()),
- handler_(handler.Pass()),
+ request_(std::move(request)),
+ handler_(std::move(handler)),
delegate_(delegate),
is_transferring_(false),
times_cancelled_before_request_start_(0),
@@ -306,19 +317,9 @@ void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
bool fatal) {
ResourceRequestInfoImpl* info = GetRequestInfo();
- int render_process_id;
- int render_frame_id;
- if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
- NOTREACHED();
-
SSLManager::OnSSLCertificateError(
- weak_ptr_factory_.GetWeakPtr(),
- info->GetResourceType(),
- request_->url(),
- render_process_id,
- render_frame_id,
- ssl_info,
- fatal);
+ weak_ptr_factory_.GetWeakPtr(), info->GetResourceType(), request_->url(),
+ info->GetWebContentsGetterForRequest(), ssl_info, fatal);
}
void ResourceLoader::OnBeforeNetworkStart(net::URLRequest* unused,
@@ -419,7 +420,13 @@ void ResourceLoader::ContinueSSLRequest() {
void ResourceLoader::ContinueWithCertificate(net::X509Certificate* cert) {
DCHECK(ssl_client_auth_handler_);
ssl_client_auth_handler_.reset();
- request_->ContinueWithCertificate(cert);
+ if (!cert) {
+ request_->ContinueWithCertificate(nullptr, nullptr);
+ return;
+ }
+ scoped_refptr<net::SSLPrivateKey> private_key =
+ net::FetchClientCertPrivateKey(cert);
+ request_->ContinueWithCertificate(cert, private_key.get());
}
void ResourceLoader::CancelCertificateSelection() {
@@ -671,6 +678,12 @@ void ResourceLoader::CallDidFinishLoading() {
}
void ResourceLoader::RecordHistograms() {
+ if (request_->response_info().network_accessed) {
+ UMA_HISTOGRAM_ENUMERATION("Net.HttpResponseInfo.ConnectionInfo",
+ request_->response_info().connection_info,
+ net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS);
+ }
+
ResourceRequestInfoImpl* info = GetRequestInfo();
if (info->GetResourceType() == RESOURCE_TYPE_PREFETCH) {
diff --git a/chromium/content/browser/loader/resource_loader.h b/chromium/content/browser/loader/resource_loader.h
index 41f3d7e38b1..5b5ecdb500e 100644
--- a/chromium/content/browser/loader/resource_loader.h
+++ b/chromium/content/browser/loader/resource_loader.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_LOADER_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_LOADER_H_
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
diff --git a/chromium/content/browser/loader/resource_loader_unittest.cc b/chromium/content/browser/loader/resource_loader_unittest.cc
index 90418f3f114..05ed7fc4efb 100644
--- a/chromium/content/browser/loader/resource_loader_unittest.cc
+++ b/chromium/content/browser/loader/resource_loader_unittest.cc
@@ -4,11 +4,16 @@
#include "content/browser/loader/resource_loader.h"
+#include <stddef.h>
+#include <stdint.h>
+#include <utility>
+
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
@@ -38,6 +43,7 @@
#include "net/cert/x509_certificate.h"
#include "net/ssl/client_cert_store.h"
#include "net/ssl/ssl_cert_request_info.h"
+#include "net/ssl/ssl_private_key.h"
#include "net/test/cert_test_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/url_request/url_request.h"
@@ -146,7 +152,8 @@ class MockClientCertURLRequestJob : public net::URLRequestTestJob {
public:
MockClientCertURLRequestJob(net::URLRequest* request,
net::NetworkDelegate* network_delegate)
- : net::URLRequestTestJob(request, network_delegate) {}
+ : net::URLRequestTestJob(request, network_delegate),
+ weak_factory_(this) {}
static std::vector<std::string> test_authorities() {
return std::vector<std::string>(1, "dummy");
@@ -160,16 +167,19 @@ class MockClientCertURLRequestJob : public net::URLRequestTestJob {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
- this, cert_request_info));
+ weak_factory_.GetWeakPtr(), cert_request_info));
}
- void ContinueWithCertificate(net::X509Certificate* cert) override {
+ void ContinueWithCertificate(net::X509Certificate* cert,
+ net::SSLPrivateKey* private_key) override {
net::URLRequestTestJob::Start();
}
private:
~MockClientCertURLRequestJob() override {}
+ base::WeakPtrFactory<MockClientCertURLRequestJob> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(MockClientCertURLRequestJob);
};
@@ -227,9 +237,9 @@ class MockHTTPSURLRequestJob : public net::URLRequestTestJob {
};
const char kRedirectHeaders[] =
- "HTTP/1.1 302 Found\0"
- "Location: https://example.test\0"
- "\0";
+ "HTTP/1.1 302 Found\n"
+ "Location: https://example.test\n"
+ "\n";
class MockHTTPSJobURLRequestInterceptor : public net::URLRequestInterceptor {
public:
@@ -441,7 +451,7 @@ class SelectCertificateBrowserClient : public TestContentBrowserClient {
++call_count_;
passed_certs_ = cert_request_info->client_certs;
- delegate_ = delegate.Pass();
+ delegate_ = std::move(delegate);
select_certificate_run_loop_.Quit();
}
@@ -471,11 +481,11 @@ class ResourceContextStub : public MockResourceContext {
: MockResourceContext(test_request_context) {}
scoped_ptr<net::ClientCertStore> CreateClientCertStore() override {
- return dummy_cert_store_.Pass();
+ return std::move(dummy_cert_store_);
}
void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
- dummy_cert_store_ = store.Pass();
+ dummy_cert_store_ = std::move(store);
}
private:
@@ -486,7 +496,7 @@ class ResourceContextStub : public MockResourceContext {
// progress reporting.
class NonChunkedUploadDataStream : public net::UploadDataStream {
public:
- explicit NonChunkedUploadDataStream(uint64 size)
+ explicit NonChunkedUploadDataStream(uint64_t size)
: net::UploadDataStream(false, 0), stream_(0), size_(size) {}
void AppendData(const char* data) {
@@ -510,7 +520,7 @@ class NonChunkedUploadDataStream : public net::UploadDataStream {
void ResetInternal() override { stream_.Reset(); }
net::ChunkedUploadDataStream stream_;
- uint64 size_;
+ uint64_t size_;
DISALLOW_COPY_AND_ASSIGN(NonChunkedUploadDataStream);
};
@@ -552,7 +562,7 @@ class ResourceLoaderTest : public testing::Test,
virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
scoped_ptr<ResourceHandlerStub> leaf_handler,
net::URLRequest* request) {
- return leaf_handler.Pass();
+ return std::move(leaf_handler);
}
// Replaces loader_ with a new one for |request|.
@@ -565,13 +575,13 @@ class ResourceLoaderTest : public testing::Test,
rfh->GetProcess()->GetID(), rfh->GetRenderViewHost()->GetRoutingID(),
rfh->GetRoutingID(), true /* is_main_frame */,
false /* parent_is_main_frame */, true /* allow_download */,
- false /* is_async */);
+ false /* is_async */, false /* is_using_lofi_ */);
scoped_ptr<ResourceHandlerStub> resource_handler(
new ResourceHandlerStub(request.get()));
raw_ptr_resource_handler_ = resource_handler.get();
loader_.reset(new ResourceLoader(
- request.Pass(),
- WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_),
+ std::move(request),
+ WrapResourceHandler(std::move(resource_handler), raw_ptr_to_request_),
this));
}
@@ -589,7 +599,7 @@ class ResourceLoaderTest : public testing::Test,
test_url(),
net::DEFAULT_PRIORITY,
nullptr /* delegate */));
- SetUpResourceLoader(request.Pass());
+ SetUpResourceLoader(std::move(request));
}
void TearDown() override {
@@ -684,7 +694,7 @@ TEST_F(ClientCertResourceLoaderTest, WithStoreLookup) {
new net::X509Certificate("test", "test", base::Time(), base::Time())));
scoped_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub(
dummy_certs, &store_request_count, &store_requested_authorities));
- resource_context_.SetClientCertStore(test_store.Pass());
+ resource_context_.SetClientCertStore(std::move(test_store));
// Plug in test content browser client.
SelectCertificateBrowserClient test_client;
@@ -707,7 +717,7 @@ TEST_F(ClientCertResourceLoaderTest, WithStoreLookup) {
EXPECT_EQ(dummy_certs, test_client.passed_certs());
// Continue the request.
- test_client.ContinueWithCertificate(dummy_certs[0].get());
+ test_client.ContinueWithCertificate(nullptr);
raw_ptr_resource_handler_->WaitForResponseComplete();
EXPECT_EQ(net::OK, raw_ptr_resource_handler_->status().error());
@@ -732,9 +742,7 @@ TEST_F(ClientCertResourceLoaderTest, WithNullStore) {
EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
// Continue the request.
- scoped_refptr<net::X509Certificate> cert(
- new net::X509Certificate("test", "test", base::Time(), base::Time()));
- test_client.ContinueWithCertificate(cert.get());
+ test_client.ContinueWithCertificate(nullptr);
raw_ptr_resource_handler_->WaitForResponseComplete();
EXPECT_EQ(net::OK, raw_ptr_resource_handler_->status().error());
@@ -886,7 +894,7 @@ class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
// Create mock file streams and a ShareableFileReference.
scoped_ptr<net::testing::MockFileStream> file_stream(
- new net::testing::MockFileStream(file.Pass(),
+ new net::testing::MockFileStream(std::move(file),
base::ThreadTaskRunnerHandle::Get()));
file_stream_ = file_stream.get();
deletable_file_ = ShareableFileReference::GetOrCreate(
@@ -897,13 +905,13 @@ class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
// Inject them into the handler.
scoped_ptr<RedirectToFileResourceHandler> handler(
- new RedirectToFileResourceHandler(leaf_handler.Pass(), request));
+ new RedirectToFileResourceHandler(std::move(leaf_handler), request));
redirect_to_file_resource_handler_ = handler.get();
handler->SetCreateTemporaryFileStreamFunctionForTesting(
base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback,
base::Unretained(this),
base::Passed(&file_stream)));
- return handler.Pass();
+ return std::move(handler);
}
private:
@@ -1074,7 +1082,7 @@ TEST_F(HTTPSSecurityInfoResourceLoaderTest, SecurityInfoOnHTTPSResource) {
scoped_ptr<net::URLRequest> request(
resource_context_.GetRequestContext()->CreateRequest(
test_https_url(), net::DEFAULT_PRIORITY, nullptr /* delegate */));
- SetUpResourceLoader(request.Pass());
+ SetUpResourceLoader(std::move(request));
// Send the request and wait until it completes.
loader_->StartRequest();
@@ -1113,7 +1121,7 @@ TEST_F(HTTPSSecurityInfoResourceLoaderTest,
resource_context_.GetRequestContext()->CreateRequest(
test_https_redirect_url(), net::DEFAULT_PRIORITY,
nullptr /* delegate */));
- SetUpResourceLoader(request.Pass());
+ SetUpResourceLoader(std::move(request));
// Send the request and wait until it completes.
loader_->StartRequest();
diff --git a/chromium/content/browser/loader/resource_message_delegate.h b/chromium/content/browser/loader/resource_message_delegate.h
index 2a5dc45ebc4..f007f1ca356 100644
--- a/chromium/content/browser/loader/resource_message_delegate.h
+++ b/chromium/content/browser/loader/resource_message_delegate.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_DELEGATE_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_DELEGATE_H_
-#include "base/basictypes.h"
+#include "base/macros.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
diff --git a/chromium/content/browser/loader/resource_message_filter.cc b/chromium/content/browser/loader/resource_message_filter.cc
index 4a20d9ac1df..186bf66316e 100644
--- a/chromium/content/browser/loader/resource_message_filter.cc
+++ b/chromium/content/browser/loader/resource_message_filter.cc
@@ -50,10 +50,12 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) {
}
void ResourceMessageFilter::GetContexts(
- const ResourceHostMsg_Request& request,
+ ResourceType resource_type,
+ int origin_pid,
ResourceContext** resource_context,
net::URLRequestContext** request_context) {
- return get_contexts_callback_.Run(request, resource_context, request_context);
+ return get_contexts_callback_.Run(resource_type, origin_pid, resource_context,
+ request_context);
}
const HostZoomMap* ResourceMessageFilter::GetHostZoomMap() const {
diff --git a/chromium/content/browser/loader/resource_message_filter.h b/chromium/content/browser/loader/resource_message_filter.h
index 1240cb4f5b3..9bac4198f60 100644
--- a/chromium/content/browser/loader/resource_message_filter.h
+++ b/chromium/content/browser/loader/resource_message_filter.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_FILTER_H_
#include "base/callback_forward.h"
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
@@ -38,12 +39,18 @@ class ServiceWorkerContextWrapper;
// will not interfere with browser UI.
class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
public:
- typedef base::Callback<void(const ResourceHostMsg_Request&,
+ // TODO(ricea): Remove origin_pid when support for NPAPI plugins is removed.
+ // crbug.com/493212 is the tracking bug for NPAPI removal.
+ typedef base::Callback<void(ResourceType resource_type,
+ int origin_pid,
ResourceContext**,
net::URLRequestContext**)> GetContextsCallback;
// |appcache_service|, |blob_storage_context|, |file_system_context| may be
// NULL in unittests or for requests from the (NPAPI) plugin process.
+ // The |origin_pid| argument to |get_contexts_callback| is not used
+ // (and may be invalid) for requests that are NOT from the NPAPI plugin
+ // process.
ResourceMessageFilter(int child_id,
int process_type,
ChromeAppCacheService* appcache_service,
@@ -57,7 +64,10 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
void OnChannelClosing() override;
bool OnMessageReceived(const IPC::Message& message) override;
- void GetContexts(const ResourceHostMsg_Request& request,
+ // |origin_pid| is only required for NPAPI plugin processes. Its value is
+ // ignored otherwise.
+ void GetContexts(ResourceType resource_type,
+ int origin_pid,
ResourceContext** resource_context,
net::URLRequestContext** request_context);
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index eb400bca9cc..8511653ee50 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -4,15 +4,33 @@
#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/loader/global_routing_id.h"
#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/net/url_request_user_data.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_request_id.h"
+#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/process_type.h"
#include "net/url_request/url_request.h"
namespace content {
+namespace {
+
+WebContents* GetWebContentsFromFTNID(int frame_tree_node_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ FrameTreeNode* frame_tree_node =
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+ if (!frame_tree_node)
+ return nullptr;
+
+ return WebContentsImpl::FromFrameTreeNode(frame_tree_node);
+}
+
+} // namespace
+
// ----------------------------------------------------------------------------
// ResourceRequestInfo
@@ -32,7 +50,8 @@ void ResourceRequestInfo::AllocateForTesting(net::URLRequest* request,
bool is_main_frame,
bool parent_is_main_frame,
bool allow_download,
- bool is_async) {
+ bool is_async,
+ bool is_using_lofi) {
// Make sure both |is_main_frame| and |parent_is_main_frame| aren't set at the
// same time.
DCHECK(!(is_main_frame && parent_is_main_frame));
@@ -52,7 +71,6 @@ void ResourceRequestInfo::AllocateForTesting(net::URLRequest* request,
render_frame_id, // render_frame_id
is_main_frame, // is_main_frame
parent_is_main_frame, // parent_is_main_frame
- 0, // parent_render_frame_id
resource_type, // resource_type
ui::PAGE_TRANSITION_LINK, // transition_type
false, // should_replace_current_entry
@@ -68,7 +86,9 @@ void ResourceRequestInfo::AllocateForTesting(net::URLRequest* request,
context, // context
base::WeakPtr<ResourceMessageFilter>(), // filter
false, // report_raw_headers
- is_async); // is_async
+ is_async, // is_async
+ is_using_lofi, // is_using_lofi
+ std::string()); // original_headers
info->AssociateWithRequest(request);
}
@@ -111,7 +131,6 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
int render_frame_id,
bool is_main_frame,
bool parent_is_main_frame,
- int parent_render_frame_id,
ResourceType resource_type,
ui::PageTransition transition_type,
bool should_replace_current_entry,
@@ -127,7 +146,9 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
ResourceContext* context,
base::WeakPtr<ResourceMessageFilter> filter,
bool report_raw_headers,
- bool is_async)
+ bool is_async,
+ bool is_using_lofi,
+ const std::string& original_headers)
: cross_site_handler_(NULL),
detachable_handler_(NULL),
process_type_(process_type),
@@ -139,7 +160,6 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
render_frame_id_(render_frame_id),
is_main_frame_(is_main_frame),
parent_is_main_frame_(parent_is_main_frame),
- parent_render_frame_id_(parent_render_frame_id),
should_replace_current_entry_(should_replace_current_entry),
is_download_(is_download),
is_stream_(is_stream),
@@ -158,12 +178,37 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
context_(context),
filter_(filter),
report_raw_headers_(report_raw_headers),
- is_async_(is_async) {
+ is_async_(is_async),
+ is_using_lofi_(is_using_lofi),
+ original_headers_(original_headers) {
}
ResourceRequestInfoImpl::~ResourceRequestInfoImpl() {
}
+ResourceRequestInfo::WebContentsGetter
+ResourceRequestInfoImpl::GetWebContentsGetterForRequest() const {
+ // PlzNavigate: navigation requests are created with a valid FrameTreeNode ID
+ // and invalid RenderProcessHost and RenderFrameHost IDs. The FrameTreeNode
+ // ID should be used to access the WebContents.
+ if (frame_tree_node_id_ != -1) {
+ DCHECK(IsBrowserSideNavigationEnabled());
+ return base::Bind(&GetWebContentsFromFTNID, frame_tree_node_id_);
+ }
+
+ // In other cases, use the RenderProcessHost ID + RenderFrameHost ID to get
+ // the WebContents.
+ int render_process_host_id = -1;
+ int render_frame_host_id = -1;
+ if (!GetAssociatedRenderFrame(&render_process_host_id,
+ &render_frame_host_id)) {
+ NOTREACHED();
+ }
+
+ return base::Bind(&WebContentsImpl::FromRenderFrameHostID,
+ render_process_host_id, render_frame_host_id);
+}
+
ResourceContext* ResourceRequestInfoImpl::GetContext() const {
return context_;
}
@@ -180,10 +225,6 @@ int ResourceRequestInfoImpl::GetOriginPID() const {
return origin_pid_;
}
-int ResourceRequestInfoImpl::GetRequestID() const {
- return request_id_;
-}
-
int ResourceRequestInfoImpl::GetRenderFrameID() const {
return render_frame_id_;
}
@@ -196,10 +237,6 @@ bool ResourceRequestInfoImpl::ParentIsMainFrame() const {
return parent_is_main_frame_;
}
-int ResourceRequestInfoImpl::GetParentRenderFrameID() const {
- return parent_render_frame_id_;
-}
-
ResourceType ResourceRequestInfoImpl::GetResourceType() const {
return resource_type_;
}
@@ -250,6 +287,10 @@ bool ResourceRequestInfoImpl::IsDownload() const {
return is_download_;
}
+bool ResourceRequestInfoImpl::IsUsingLoFi() const {
+ return is_using_lofi_;
+}
+
bool ResourceRequestInfoImpl::ShouldReportRawHeaders() const {
return report_raw_headers_;
}
@@ -265,6 +306,10 @@ void ResourceRequestInfoImpl::AssociateWithRequest(net::URLRequest* request) {
}
}
+int ResourceRequestInfoImpl::GetRequestID() const {
+ return request_id_;
+}
+
GlobalRequestID ResourceRequestInfoImpl::GetGlobalRequestID() const {
return GlobalRequestID(child_id_, request_id_);
}
@@ -276,15 +321,15 @@ GlobalRoutingID ResourceRequestInfoImpl::GetGlobalRoutingID() const {
void ResourceRequestInfoImpl::UpdateForTransfer(
int child_id,
int route_id,
+ int render_frame_id,
int origin_pid,
int request_id,
- int parent_render_frame_id,
base::WeakPtr<ResourceMessageFilter> filter) {
child_id_ = child_id;
route_id_ = route_id;
+ render_frame_id_ = render_frame_id;
origin_pid_ = origin_pid;
request_id_ = request_id;
- parent_render_frame_id_ = parent_render_frame_id;
filter_ = filter;
}
diff --git a/chromium/content/browser/loader/resource_request_info_impl.h b/chromium/content/browser/loader/resource_request_info_impl.h
index f0251e51325..625e58ca890 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -7,8 +7,8 @@
#include <string>
-#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
@@ -49,7 +49,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
int render_frame_id,
bool is_main_frame,
bool parent_is_main_frame,
- int parent_render_frame_id,
ResourceType resource_type,
ui::PageTransition transition_type,
bool should_replace_current_entry,
@@ -65,19 +64,20 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
ResourceContext* context,
base::WeakPtr<ResourceMessageFilter> filter,
bool report_raw_headers,
- bool is_async);
+ bool is_async,
+ bool is_using_lofi,
+ const std::string& original_headers);
~ResourceRequestInfoImpl() override;
// ResourceRequestInfo implementation:
+ WebContentsGetter GetWebContentsGetterForRequest() const override;
ResourceContext* GetContext() const override;
int GetChildID() const override;
int GetRouteID() const override;
int GetOriginPID() const override;
- int GetRequestID() const override;
int GetRenderFrameID() const override;
bool IsMainFrame() const override;
bool ParentIsMainFrame() const override;
- int GetParentRenderFrameID() const override;
ResourceType GetResourceType() const override;
int GetProcessType() const override;
blink::WebReferrerPolicy GetReferrerPolicy() const override;
@@ -89,10 +89,12 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
int* render_frame_id) const override;
bool IsAsync() const override;
bool IsDownload() const override;
+ bool IsUsingLoFi() const override;
bool ShouldReportRawHeaders() const;
CONTENT_EXPORT void AssociateWithRequest(net::URLRequest* request);
+ CONTENT_EXPORT int GetRequestID() const;
CONTENT_EXPORT GlobalRequestID GetGlobalRequestID() const;
GlobalRoutingID GetGlobalRoutingID() const;
@@ -112,9 +114,9 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
// does not need to be updated.
void UpdateForTransfer(int child_id,
int route_id,
+ int render_frame_id,
int origin_pid,
int request_id,
- int parent_render_frame_id,
base::WeakPtr<ResourceMessageFilter> filter);
// CrossSiteResourceHandler for this request. May be null.
@@ -180,6 +182,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
void set_do_not_prompt_for_login(bool do_not_prompt) {
do_not_prompt_for_login_ = do_not_prompt;
}
+ const std::string& original_headers() const { return original_headers_; }
private:
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
@@ -199,7 +202,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
int render_frame_id_;
bool is_main_frame_;
bool parent_is_main_frame_;
- int parent_render_frame_id_;
bool should_replace_current_entry_;
bool is_download_;
bool is_stream_;
@@ -221,6 +223,8 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
base::WeakPtr<ResourceMessageFilter> filter_;
bool report_raw_headers_;
bool is_async_;
+ bool is_using_lofi_;
+ const std::string original_headers_;
DISALLOW_COPY_AND_ASSIGN(ResourceRequestInfoImpl);
};
diff --git a/chromium/content/browser/loader/resource_scheduler.cc b/chromium/content/browser/loader/resource_scheduler.cc
index 2d9071612a3..690f20f0a03 100644
--- a/chromium/content/browser/loader/resource_scheduler.cc
+++ b/chromium/content/browser/loader/resource_scheduler.cc
@@ -5,11 +5,12 @@
#include "content/browser/loader/resource_scheduler.h"
#include <stdint.h>
-
#include <set>
#include <string>
+#include <utility>
#include <vector>
+#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
@@ -32,6 +33,11 @@ namespace content {
namespace {
+enum StartMode {
+ START_SYNC,
+ START_ASYNC
+};
+
// Field trial constants
const char kThrottleCoalesceFieldTrial[] = "RequestThrottlingAndCoalescing";
const char kThrottleCoalesceFieldTrialThrottle[] = "Throttle";
@@ -162,14 +168,14 @@ class ResourceScheduler::RequestQueue {
private:
typedef std::map<ScheduledResourceRequest*, NetQueue::iterator> PointerMap;
- uint32 MakeFifoOrderingId() {
+ uint32_t MakeFifoOrderingId() {
fifo_ordering_ids_ += 1;
return fifo_ordering_ids_;
}
// Used to create an ordering ID for scheduled resources so that resources
// with same priority/intra_priority stay in fifo order.
- uint32 fifo_ordering_ids_;
+ uint32_t fifo_ordering_ids_;
NetQueue queue_;
PointerMap pointers_;
@@ -193,7 +199,8 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
attributes_(kAttributeNone),
scheduler_(scheduler),
priority_(priority),
- fifo_ordering_(0) {
+ fifo_ordering_(0),
+ weak_ptr_factory_(this) {
DCHECK(!request_->GetUserData(kUserDataKey));
request_->SetUserData(kUserDataKey, new UnownedPointer(this));
}
@@ -208,10 +215,39 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
->get();
}
- void Start() {
- ready_ = true;
+ // Starts the request. If |start_mode| is START_ASYNC, the request will not
+ // be started immediately.
+ void Start(StartMode start_mode) {
+ DCHECK(!ready_);
+
+ // If the request was cancelled, do nothing.
if (!request_->status().is_success())
return;
+
+ bool was_deferred = deferred_;
+
+ // If the request was deferred, need to start it. Otherwise, will just not
+ // defer starting it in the first place, and the value of |start_mode|
+ // makes no difference.
+ if (deferred_) {
+ // If can't start the request synchronously, post a task to start the
+ // request.
+ if (start_mode == START_ASYNC) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&ScheduledResourceRequest::Start,
+ weak_ptr_factory_.GetWeakPtr(),
+ START_SYNC));
+ return;
+ }
+ deferred_ = false;
+ controller()->Resume();
+ }
+
+ ready_ = true;
+
+ // The rest of this method is just collecting histograms.
+
base::TimeTicks time = base::TimeTicks::Now();
ClientState current_state = scheduler_->GetClientState(client_id_);
// Note: the client state isn't perfectly accurate since it won't capture
@@ -227,11 +263,8 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
}
base::TimeDelta time_was_deferred = base::TimeDelta::FromMicroseconds(0);
- if (deferred_) {
- deferred_ = false;
- controller()->Resume();
+ if (was_deferred)
time_was_deferred = time - time_deferred_;
- }
PostHistogram("RequestTimeDeferred", client_state, NULL, time_was_deferred);
PostHistogram("RequestTimeThrottled", client_state, NULL,
time - request_->creation_time());
@@ -250,8 +283,8 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
net::URLRequest* url_request() { return request_; }
const net::URLRequest* url_request() const { return request_; }
bool is_async() const { return is_async_; }
- uint32 fifo_ordering() const { return fifo_ordering_; }
- void set_fifo_ordering(uint32 fifo_ordering) {
+ uint32_t fifo_ordering() const { return fifo_ordering_; }
+ void set_fifo_ordering(uint32_t fifo_ordering) {
fifo_ordering_ = fifo_ordering;
}
RequestAttributes attributes() const {
@@ -294,9 +327,12 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
RequestAttributes attributes_;
ResourceScheduler* scheduler_;
RequestPriorityParams priority_;
- uint32 fifo_ordering_;
+ uint32_t fifo_ordering_;
base::TimeTicks time_deferred_;
+ base::WeakPtrFactory<ResourceScheduler::ScheduledResourceRequest>
+ weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest);
};
@@ -356,10 +392,12 @@ class ResourceScheduler::Client {
void ScheduleRequest(net::URLRequest* url_request,
ScheduledResourceRequest* request) {
SetRequestAttributes(request, DetermineRequestAttributes(request));
- if (ShouldStartRequest(request) == START_REQUEST)
- StartRequest(request);
- else
+ if (ShouldStartRequest(request) == START_REQUEST) {
+ // New requests can be started synchronously without issue.
+ StartRequest(request, START_SYNC);
+ } else {
pending_requests_.Insert(request);
+ }
}
void RemoveRequest(ScheduledResourceRequest* request) {
@@ -385,8 +423,9 @@ class ResourceScheduler::Client {
ScheduledResourceRequest* request =
*pending_requests_.GetNextHighestIterator();
pending_requests_.Erase(request);
- // StartRequest() may modify pending_requests_. TODO(ricea): Does it?
- StartRequest(request);
+ // Starting requests asynchronously ensures no side effects, and avoids
+ // starting a bunch of requests that may be about to be deleted.
+ StartRequest(request, START_ASYNC);
}
RequestSet unowned_requests;
for (RequestSet::iterator it = in_flight_requests_.begin();
@@ -716,9 +755,10 @@ class ResourceScheduler::Client {
return false;
}
- void StartRequest(ScheduledResourceRequest* request) {
+ void StartRequest(ScheduledResourceRequest* request,
+ StartMode start_mode) {
InsertInFlightRequest(request);
- request->Start();
+ request->Start(start_mode);
}
// ShouldStartRequest is the main scheduling algorithm.
@@ -890,7 +930,7 @@ class ResourceScheduler::Client {
if (query_result == START_REQUEST) {
pending_requests_.Erase(request);
- StartRequest(request);
+ StartRequest(request, START_ASYNC);
// StartRequest can modify the pending list, so we (re)start evaluation
// from the currently highest priority request. Avoid copying a singular
@@ -1043,13 +1083,13 @@ scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
// 2. Most unittests don't send the IPCs needed to register Clients.
// 3. The tab is closed while a RequestResource IPC is in flight.
unowned_requests_.insert(request.get());
- request->Start();
- return request.Pass();
+ request->Start(START_SYNC);
+ return std::move(request);
}
Client* client = it->second;
client->ScheduleRequest(url_request, request.get());
- return request.Pass();
+ return std::move(request);
}
void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) {
@@ -1086,7 +1126,7 @@ void ResourceScheduler::OnClientDeleted(int child_id, int route_id) {
DCHECK(CalledOnValidThread());
ClientId client_id = MakeClientId(child_id, route_id);
ClientMap::iterator it = client_map_.find(client_id);
- CHECK(it != client_map_.end());
+ DCHECK(it != client_map_.end());
Client* client = it->second;
// ResourceDispatcherHost cancels all requests except for cross-renderer
diff --git a/chromium/content/browser/loader/resource_scheduler.h b/chromium/content/browser/loader/resource_scheduler.h
index a50324b5a59..444d97d1693 100644
--- a/chromium/content/browser/loader/resource_scheduler.h
+++ b/chromium/content/browser/loader/resource_scheduler.h
@@ -5,11 +5,14 @@
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_H_
+#include <stddef.h>
+#include <stdint.h>
+
#include <map>
#include <set>
-#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "base/timer/timer.h"
@@ -218,7 +221,7 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
};
class Client;
- typedef int64 ClientId;
+ typedef int64_t ClientId;
typedef std::map<ClientId, Client*> ClientMap;
typedef std::set<ScheduledResourceRequest*> RequestSet;
diff --git a/chromium/content/browser/loader/resource_scheduler_filter.cc b/chromium/content/browser/loader/resource_scheduler_filter.cc
index 2777eaae121..0738ec188fe 100644
--- a/chromium/content/browser/loader/resource_scheduler_filter.cc
+++ b/chromium/content/browser/loader/resource_scheduler_filter.cc
@@ -4,6 +4,9 @@
#include "content/browser/loader/resource_scheduler_filter.h"
+#include <stdint.h>
+
+#include "base/macros.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_scheduler.h"
#include "content/common/frame_messages.h"
@@ -12,9 +15,8 @@
namespace content {
namespace {
-const uint32 kFilteredMessageClasses[] = {
- FrameMsgStart,
- ViewMsgStart,
+const uint32_t kFilteredMessageClasses[] = {
+ FrameMsgStart, ViewMsgStart,
};
} // namespace
diff --git a/chromium/content/browser/loader/resource_scheduler_unittest.cc b/chromium/content/browser/loader/resource_scheduler_unittest.cc
index 3aaf23d5977..1399b52dde3 100644
--- a/chromium/content/browser/loader/resource_scheduler_unittest.cc
+++ b/chromium/content/browser/loader/resource_scheduler_unittest.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/resource_scheduler.h"
+#include <utility>
+
#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
@@ -53,8 +55,8 @@ class TestRequest : public ResourceController {
scoped_ptr<ResourceThrottle> throttle,
ResourceScheduler* scheduler)
: started_(false),
- url_request_(url_request.Pass()),
- throttle_(throttle.Pass()),
+ url_request_(std::move(url_request)),
+ throttle_(std::move(throttle)),
scheduler_(scheduler) {
throttle_->set_controller_for_testing(this);
}
@@ -102,10 +104,10 @@ class CancelingTestRequest : public TestRequest {
CancelingTestRequest(scoped_ptr<net::URLRequest> url_request,
scoped_ptr<ResourceThrottle> throttle,
ResourceScheduler* scheduler)
- : TestRequest(url_request.Pass(), throttle.Pass(), scheduler) {}
+ : TestRequest(std::move(url_request), std::move(throttle), scheduler) {}
void set_request_to_cancel(scoped_ptr<TestRequest> request_to_cancel) {
- request_to_cancel_ = request_to_cancel.Pass();
+ request_to_cancel_ = std::move(request_to_cancel);
}
private:
@@ -181,7 +183,7 @@ class ResourceSchedulerTest : public testing::Test {
int route_id) {
scoped_ptr<net::URLRequest> url_request(
context_.CreateRequest(GURL(url), priority, NULL));
- return url_request.Pass();
+ return url_request;
}
scoped_ptr<net::URLRequest> NewURLRequest(const char* url,
@@ -238,8 +240,8 @@ class ResourceSchedulerTest : public testing::Test {
NewURLRequestWithChildAndRoute(url, priority, child_id, route_id));
scoped_ptr<ResourceThrottle> throttle(scheduler_->ScheduleRequest(
child_id, route_id, is_async, url_request.get()));
- TestRequest* request =
- new TestRequest(url_request.Pass(), throttle.Pass(), scheduler());
+ TestRequest* request = new TestRequest(std::move(url_request),
+ std::move(throttle), scheduler());
request->Start();
return request;
}
@@ -282,7 +284,9 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilIdle) {
EXPECT_TRUE(high->started());
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
+
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low2->started());
}
@@ -293,8 +297,15 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInserted) {
EXPECT_TRUE(high->started());
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
+
high.reset();
+ base::RunLoop().RunUntilIdle();
+ // TODO(mmenke): The name of this test implies this should be false.
+ // Investigate if this is now expected, remove or update this test if it is.
+ EXPECT_TRUE(low2->started());
+
scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low2->started());
}
@@ -305,9 +316,13 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilCriticalComplete) {
EXPECT_TRUE(high->started());
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
+
scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(low2->started());
+
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low2->started());
}
@@ -319,7 +334,9 @@ TEST_F(ResourceSchedulerTest, LowDoesNotBlockCriticalComplete) {
EXPECT_TRUE(low->started());
EXPECT_TRUE(lowest->started());
EXPECT_FALSE(lowest2->started());
+
scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(lowest2->started());
}
@@ -335,8 +352,10 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInsertedExceptSpdy) {
EXPECT_TRUE(low_spdy->started());
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
+
scheduler()->OnWillInsertBody(kChildId, kRouteId);
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low2->started());
}
@@ -367,9 +386,13 @@ TEST_F(ResourceSchedulerTest, StartMultipleLowRequestsWhenIdle) {
EXPECT_TRUE(high2->started());
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
+
high1.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(low2->started());
+
high2.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low2->started());
}
@@ -382,16 +405,18 @@ TEST_F(ResourceSchedulerTest, CancelOtherRequestsWhileResuming) {
scoped_ptr<ResourceThrottle> throttle(scheduler()->ScheduleRequest(
kChildId, kRouteId, true, url_request.get()));
scoped_ptr<CancelingTestRequest> low2(new CancelingTestRequest(
- url_request.Pass(), throttle.Pass(), scheduler()));
+ std::move(url_request), std::move(throttle), scheduler()));
low2->Start();
scoped_ptr<TestRequest> low3(NewRequest("http://host/low3", net::LOWEST));
- low2->set_request_to_cancel(low3.Pass());
+ low2->set_request_to_cancel(std::move(low3));
scoped_ptr<TestRequest> low4(NewRequest("http://host/low4", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_FALSE(low2->started());
+
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low1->started());
EXPECT_TRUE(low2->started());
EXPECT_TRUE(low4->started());
@@ -421,10 +446,14 @@ TEST_F(ResourceSchedulerTest, LimitedNumberOfDelayableRequestsInFlight) {
net::LOWEST));
EXPECT_FALSE(second_last_singlehost->started());
+
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(second_last_singlehost->started());
EXPECT_FALSE(last_singlehost->started());
+
lows_singlehost.erase(lows_singlehost.begin());
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(last_singlehost->started());
// Queue more requests from different hosts until we reach the total limit.
@@ -432,6 +461,7 @@ TEST_F(ResourceSchedulerTest, LimitedNumberOfDelayableRequestsInFlight) {
kMaxNumDelayableRequestsPerClient - kMaxNumDelayableRequestsPerHost;
EXPECT_GT(expected_slots_left, 0);
ScopedVector<TestRequest> lows_different_host;
+ base::RunLoop().RunUntilIdle();
for (int i = 0; i < expected_slots_left; ++i) {
string url = "http://host" + base::IntToString(i) + "/low";
lows_different_host.push_back(NewRequest(url.c_str(), net::LOWEST));
@@ -439,7 +469,7 @@ TEST_F(ResourceSchedulerTest, LimitedNumberOfDelayableRequestsInFlight) {
}
scoped_ptr<TestRequest> last_different_host(NewRequest("http://host_new/last",
- net::LOWEST));
+ net::LOWEST));
EXPECT_FALSE(last_different_host->started());
}
@@ -452,6 +482,7 @@ TEST_F(ResourceSchedulerTest, RaisePriorityAndStart) {
EXPECT_FALSE(request->started());
ChangeRequestPriority(request.get(), net::HIGHEST);
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(request->started());
}
@@ -466,6 +497,7 @@ TEST_F(ResourceSchedulerTest, RaisePriorityInQueue) {
EXPECT_FALSE(idle->started());
ChangeRequestPriority(request.get(), net::LOWEST);
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(request->started());
EXPECT_FALSE(idle->started());
@@ -478,6 +510,7 @@ TEST_F(ResourceSchedulerTest, RaisePriorityInQueue) {
scheduler()->OnWillInsertBody(kChildId, kRouteId);
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(request->started());
EXPECT_FALSE(idle->started());
@@ -494,6 +527,7 @@ TEST_F(ResourceSchedulerTest, LowerPriority) {
EXPECT_FALSE(idle->started());
ChangeRequestPriority(request.get(), net::IDLE);
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(request->started());
EXPECT_FALSE(idle->started());
@@ -509,6 +543,7 @@ TEST_F(ResourceSchedulerTest, LowerPriority) {
scheduler()->OnWillInsertBody(kChildId, kRouteId);
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(request->started());
EXPECT_TRUE(idle->started());
@@ -532,14 +567,17 @@ TEST_F(ResourceSchedulerTest, ReprioritizedRequestGoesToBackOfQueue) {
}
ChangeRequestPriority(request.get(), net::IDLE);
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(request->started());
EXPECT_FALSE(idle->started());
ChangeRequestPriority(request.get(), net::LOWEST);
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(request->started());
EXPECT_FALSE(idle->started());
scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(request->started());
EXPECT_FALSE(idle->started());
}
@@ -560,10 +598,12 @@ TEST_F(ResourceSchedulerTest, HigherIntraPriorityGoesToFrontOfQueue) {
EXPECT_FALSE(request->started());
ChangeRequestPriority(request.get(), net::IDLE, 1);
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(request->started());
scheduler()->OnWillInsertBody(kChildId, kRouteId);
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(request->started());
}
@@ -617,6 +657,7 @@ TEST_F(ResourceSchedulerTest, SpdyProxySchedulesImmediately) {
EXPECT_FALSE(request->started());
scheduler()->OnReceivedSpdyProxiedHttpResponse(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(request->started());
scoped_ptr<TestRequest> after(NewRequest("http://host/after", net::IDLE));
@@ -640,9 +681,11 @@ TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) {
http_server_properties_.SetSupportsSpdy(
net::HostPortPair("spdyhost1", 8080), true);
low1_spdy.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low1->started());
low1.reset();
+ base::RunLoop().RunUntilIdle();
scoped_ptr<TestRequest> low2_spdy(
NewRequest("http://spdyhost2:8080/low", net::IDLE));
// Reprioritize a request after we learn the server supports SPDY.
@@ -650,6 +693,7 @@ TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) {
http_server_properties_.SetSupportsSpdy(
net::HostPortPair("spdyhost2", 8080), true);
ChangeRequestPriority(low2_spdy.get(), net::LOWEST);
+ base::RunLoop().RunUntilIdle();
scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(low2->started());
}
@@ -749,9 +793,10 @@ TEST_F(ResourceSchedulerTest, UnthrottleNewlyVisibleClient) {
scheduler()->OnVisibilityChanged(
kBackgroundChildId, kBackgroundRouteId, true);
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
+ kBackgroundRouteId));
EXPECT_TRUE(request->started());
}
@@ -770,6 +815,7 @@ TEST_F(ResourceSchedulerTest, UnthrottleNewlyAudibleClient) {
scheduler()->OnAudibilityChanged(
kBackgroundChildId, kBackgroundRouteId, true);
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
scheduler()->GetClientStateForTesting(kBackgroundChildId,
kBackgroundRouteId));
@@ -843,8 +889,8 @@ TEST_F(ResourceSchedulerTest, ThrottledClientStartsNextHighestPriorityRequest) {
EXPECT_FALSE(low->started());
EXPECT_FALSE(high->started());
- // request->CancelRequest();
request->Cancel();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(high->started());
EXPECT_FALSE(low->started());
}
@@ -864,7 +910,8 @@ TEST_F(ResourceSchedulerTest, ThrottledSpdyProxySchedulesImmediately) {
EXPECT_FALSE(request->started());
scheduler()->OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId,
- kBackgroundRouteId);
+ kBackgroundRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(request->started());
scoped_ptr<TestRequest> after(
@@ -890,7 +937,8 @@ TEST_F(ResourceSchedulerTest, CoalescedClientIssuesNoRequests) {
EXPECT_FALSE(request->started());
scheduler()->OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId,
- kBackgroundRouteId);
+ kBackgroundRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(high->started());
scoped_ptr<TestRequest> after(
@@ -915,7 +963,8 @@ TEST_F(ResourceSchedulerTest, CoalescedSpdyProxyWaits) {
EXPECT_FALSE(request->started());
scheduler()->OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId,
- kBackgroundRouteId);
+ kBackgroundRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(request->started());
scoped_ptr<TestRequest> after(
@@ -1687,6 +1736,7 @@ TEST_F(ResourceSchedulerTest, FullVisibleLoadedCorrectlyUnthrottle) {
scheduler()->OnLoadingStateChanged(
kBackgroundChildId2, kBackgroundRouteId2, true);
scheduler()->OnLoadingStateChanged(kChildId2, kRouteId2, true);
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(scheduler()->active_clients_loaded());
EXPECT_EQ(ResourceScheduler::THROTTLED,
scheduler()->GetClientStateForTesting(kBackgroundChildId,
@@ -1709,6 +1759,7 @@ TEST_F(ResourceSchedulerTest, FullVisibleLoadedCorrectlyUnthrottle) {
// 2 visible loaded, 1 hidden loading, 1 hidden loaded
scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(scheduler()->active_clients_loaded());
EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
scheduler()->GetClientStateForTesting(kBackgroundChildId,
@@ -1725,6 +1776,7 @@ TEST_F(ResourceSchedulerTest, FullVisibleLoadedCorrectlyUnthrottle) {
// 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading
scheduler()->OnLoadingStateChanged(kChildId, kRouteId, false);
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(scheduler()->active_clients_loaded());
EXPECT_EQ(ResourceScheduler::THROTTLED,
scheduler()->GetClientStateForTesting(kBackgroundChildId,
@@ -1801,6 +1853,7 @@ TEST_F(ResourceSchedulerTest, CoalescedClientCreationStartsTimer) {
EXPECT_FALSE(mock_timer_->IsRunning());
scheduler()->OnLoadingStateChanged(
kBackgroundChildId, kBackgroundRouteId, true);
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(ResourceScheduler::COALESCED,
scheduler()->GetClientStateForTesting(kBackgroundChildId,
kBackgroundRouteId));
@@ -2024,6 +2077,7 @@ TEST_F(ResourceSchedulerTest, CoalescedRequestsIssueOnTimer) {
EXPECT_FALSE(low->started());
FireCoalescingTimer();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(high->started());
EXPECT_TRUE(low->started());
@@ -2082,6 +2136,7 @@ TEST_F(ResourceSchedulerTest, CoalescedRequestsUnthrottleCorrectlyOnTimer) {
EXPECT_FALSE(low_spdy->started());
FireCoalescingTimer();
+ base::RunLoop().RunUntilIdle();
// All high priority requests should issue.
EXPECT_TRUE(high->started());
@@ -2115,6 +2170,7 @@ TEST_F(ResourceSchedulerTest, CoalescedRequestsWaitForNextTimer) {
EXPECT_FALSE(high->started());
FireCoalescingTimer();
+ base::RunLoop().RunUntilIdle();
scoped_ptr<TestRequest> high2(
NewBackgroundRequest("http://host/high2", net::HIGHEST));
@@ -2126,6 +2182,7 @@ TEST_F(ResourceSchedulerTest, CoalescedRequestsWaitForNextTimer) {
EXPECT_FALSE(low->started());
FireCoalescingTimer();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(high->started());
EXPECT_TRUE(high2->started());
@@ -2163,14 +2220,14 @@ TEST_F(ResourceSchedulerTest, GetVisualSignalFromRenderViewHost) {
// Check initial visibility is set correctly.
EXPECT_EQ(scheduler->IsClientVisibleForTesting(rvh1->GetProcess()->GetID(),
rvh1->GetRoutingID()),
- !rvh1->is_hidden());
+ !rvh1->GetWidget()->is_hidden());
EXPECT_EQ(scheduler->IsClientVisibleForTesting(rvh2->GetProcess()->GetID(),
rvh1->GetRoutingID()),
- !rvh2->is_hidden());
+ !rvh2->GetWidget()->is_hidden());
- // 1 visible, 1 hidden
- rvh1->WasShown(ui::LatencyInfo());
- rvh2->WasHidden();
+ // 1 visible, 1 hidden.
+ rvh1->GetWidget()->WasShown(ui::LatencyInfo());
+ rvh2->GetWidget()->WasHidden();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(scheduler->IsClientVisibleForTesting(rvh1->GetProcess()->GetID(),
@@ -2179,8 +2236,8 @@ TEST_F(ResourceSchedulerTest, GetVisualSignalFromRenderViewHost) {
rvh2->GetRoutingID()));
// Flip the visibility and check again.
- rvh1->WasHidden();
- rvh2->WasShown(ui::LatencyInfo());
+ rvh1->GetWidget()->WasHidden();
+ rvh2->GetWidget()->WasShown(ui::LatencyInfo());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(scheduler->IsClientVisibleForTesting(rvh1->GetProcess()->GetID(),
@@ -2257,7 +2314,9 @@ TEST_F(ResourceSchedulerTest, OutstandingRequestLimitDelays) {
EXPECT_TRUE(high->started());
EXPECT_FALSE(low->started());
EXPECT_FALSE(low2->started());
+
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low->started());
EXPECT_TRUE(low2->started());
}
@@ -2274,9 +2333,11 @@ TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeleted) {
scoped_ptr<TestRequest> lowest2(NewRequestWithChildAndRoute(
"http://host/lowest", net::LOWEST, kChildId2, kRouteId2));
EXPECT_FALSE(lowest2->started());
+
scheduler_->OnClientDeleted(kChildId2, kRouteId2);
high.reset();
lowest1.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(lowest2->started());
}
@@ -2297,9 +2358,11 @@ TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeletedManyDelayable) {
scoped_ptr<TestRequest> lowest(NewRequestWithChildAndRoute(
"http://host/lowest", net::LOWEST, kChildId2, kRouteId2));
EXPECT_FALSE(lowest->started());
+
scheduler_->OnClientDeleted(kChildId2, kRouteId2);
high.reset();
delayable_requests.clear();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(lowest->started());
}
@@ -2344,7 +2407,9 @@ TEST_F(ResourceSchedulerTest, DefaultLayoutBlockingPriority) {
EXPECT_TRUE(low2->started());
EXPECT_TRUE(lowest->started());
EXPECT_FALSE(lowest2->started());
+
lowest.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(lowest2->started());
}
@@ -2391,14 +2456,20 @@ TEST_F(ResourceSchedulerTest, IncreaseLayoutBlockingPriority) {
EXPECT_FALSE(low2->started());
EXPECT_FALSE(lowest->started());
EXPECT_FALSE(lowest2->started());
+
low.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low2->started());
EXPECT_FALSE(lowest->started());
EXPECT_FALSE(lowest2->started());
+
low2.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(lowest->started());
EXPECT_FALSE(lowest2->started());
+
lowest.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(lowest2->started());
}
@@ -2432,12 +2503,18 @@ TEST_F(ResourceSchedulerTest, UseLayoutBlockingThresholdOne) {
EXPECT_TRUE(high2->started());
EXPECT_FALSE(low->started());
EXPECT_FALSE(low2->started());
+
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
+
high2.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(low2->started());
+
scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low2->started());
}
@@ -2473,13 +2550,19 @@ TEST_F(ResourceSchedulerTest, UseLayoutBlockingThresholdTwo) {
EXPECT_TRUE(high3->started());
EXPECT_FALSE(low->started());
EXPECT_FALSE(low2->started());
+
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
+
high2.reset();
high3.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(low2->started());
+
scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low2->started());
}
@@ -2513,8 +2596,10 @@ TEST_F(ResourceSchedulerTest, TwoDelayableLoadsUntilBodyInserted) {
EXPECT_TRUE(low->started());
EXPECT_TRUE(low2->started());
EXPECT_FALSE(low3->started());
+
high.reset();
scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low3->started());
}
@@ -2552,12 +2637,16 @@ TEST_F(ResourceSchedulerTest,
EXPECT_FALSE(low->started());
EXPECT_FALSE(low2->started());
EXPECT_FALSE(low3->started());
+
high.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low->started());
EXPECT_TRUE(low2->started());
EXPECT_FALSE(low3->started());
+
high2.reset();
scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low3->started());
}
@@ -2637,7 +2726,7 @@ TEST_F(ResourceSchedulerTest,
}
scoped_ptr<TestRequest> last_different_host(NewRequest("http://host_new/last",
- net::LOWEST));
+ net::LOWEST));
EXPECT_FALSE(last_different_host->started());
}
diff --git a/chromium/content/browser/loader/stream_resource_handler.h b/chromium/content/browser/loader/stream_resource_handler.h
index 37f4d0da2ea..6bc4253a2f3 100644
--- a/chromium/content/browser/loader/stream_resource_handler.h
+++ b/chromium/content/browser/loader/stream_resource_handler.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_LOADER_STREAM_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_STREAM_RESOURCE_HANDLER_H_
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "content/browser/loader/resource_handler.h"
diff --git a/chromium/content/browser/loader/sync_resource_handler.h b/chromium/content/browser/loader/sync_resource_handler.h
index fb028475fbb..49b0d919da0 100644
--- a/chromium/content/browser/loader/sync_resource_handler.h
+++ b/chromium/content/browser/loader/sync_resource_handler.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_LOADER_SYNC_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_SYNC_RESOURCE_HANDLER_H_
+#include <stdint.h>
+
#include <string>
#include "content/browser/loader/resource_handler.h"
@@ -56,7 +58,7 @@ class SyncResourceHandler : public ResourceHandler {
SyncLoadResult result_;
IPC::Message* result_message_;
ResourceDispatcherHostImpl* rdh_;
- int64 total_transfer_size_;
+ int64_t total_transfer_size_;
};
} // namespace content
diff --git a/chromium/content/browser/loader/temporary_file_stream.cc b/chromium/content/browser/loader/temporary_file_stream.cc
index fc57c8aad89..c8bb3338f5c 100644
--- a/chromium/content/browser/loader/temporary_file_stream.cc
+++ b/chromium/content/browser/loader/temporary_file_stream.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/temporary_file_stream.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_proxy.h"
@@ -43,7 +45,7 @@ void DidCreateTemporaryFile(
scoped_ptr<net::FileStream> file_stream(
new net::FileStream(file_proxy->TakeFile(), task_runner));
- callback.Run(error_code, file_stream.Pass(), deletable_file.get());
+ callback.Run(error_code, std::move(file_stream), deletable_file.get());
}
} // namespace
diff --git a/chromium/content/browser/loader/temporary_file_stream_unittest.cc b/chromium/content/browser/loader/temporary_file_stream_unittest.cc
index af57f0824ec..a5fe1453312 100644
--- a/chromium/content/browser/loader/temporary_file_stream_unittest.cc
+++ b/chromium/content/browser/loader/temporary_file_stream_unittest.cc
@@ -5,13 +5,13 @@
#include "content/browser/loader/temporary_file_stream.h"
#include <string.h>
-
#include <string>
+#include <utility>
-#include "base/basictypes.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
+#include "base/macros.h"
#include "base/run_loop.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/file_stream.h"
@@ -42,7 +42,7 @@ class WaitForFileStream {
scoped_ptr<net::FileStream> file_stream,
ShareableFileReference* deletable_file) {
error_ = error;
- file_stream_ = file_stream.Pass();
+ file_stream_ = std::move(file_stream);
deletable_file_ = deletable_file;
loop_.Quit();
}
diff --git a/chromium/content/browser/loader/throttling_resource_handler.cc b/chromium/content/browser/loader/throttling_resource_handler.cc
index 0378423ba15..93b9ad74836 100644
--- a/chromium/content/browser/loader/throttling_resource_handler.cc
+++ b/chromium/content/browser/loader/throttling_resource_handler.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/throttling_resource_handler.h"
+#include <utility>
+
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/common/resource_response.h"
@@ -15,9 +17,9 @@ ThrottlingResourceHandler::ThrottlingResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
net::URLRequest* request,
ScopedVector<ResourceThrottle> throttles)
- : LayeredResourceHandler(request, next_handler.Pass()),
+ : LayeredResourceHandler(request, std::move(next_handler)),
deferred_stage_(DEFERRED_NONE),
- throttles_(throttles.Pass()),
+ throttles_(std::move(throttles)),
next_index_(0),
cancelled_by_resource_throttle_(false) {
for (size_t i = 0; i < throttles_.size(); ++i) {
diff --git a/chromium/content/browser/loader/throttling_resource_handler.h b/chromium/content/browser/loader/throttling_resource_handler.h
index 0d1287d644e..6abefc46e04 100644
--- a/chromium/content/browser/loader/throttling_resource_handler.h
+++ b/chromium/content/browser/loader/throttling_resource_handler.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_LOADER_THROTTLING_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_THROTTLING_RESOURCE_HANDLER_H_
+#include <stddef.h>
+
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
#include "content/browser/loader/layered_resource_handler.h"
diff --git a/chromium/content/browser/loader/upload_data_stream_builder.cc b/chromium/content/browser/loader/upload_data_stream_builder.cc
index 2f30f94a7d6..bcabe99484c 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder.cc
@@ -4,11 +4,14 @@
#include "content/browser/loader/upload_data_stream_builder.h"
+#include <stdint.h>
+
#include <limits>
#include <utility>
#include <vector>
#include "base/logging.h"
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/browser/fileapi/upload_file_system_file_element_reader.h"
#include "content/common/resource_request_body.h"
@@ -77,47 +80,46 @@ scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
storage::BlobStorageContext* blob_context,
storage::FileSystemContext* file_system_context,
base::SingleThreadTaskRunner* file_task_runner) {
- ScopedVector<net::UploadElementReader> element_readers;
+ std::vector<scoped_ptr<net::UploadElementReader>> element_readers;
for (const auto& element : *body->elements()) {
switch (element.type()) {
case ResourceRequestBody::Element::TYPE_BYTES:
- element_readers.push_back(new BytesElementReader(body, element));
+ element_readers.push_back(
+ make_scoped_ptr(new BytesElementReader(body, element)));
break;
case ResourceRequestBody::Element::TYPE_FILE:
- element_readers.push_back(
- new FileElementReader(body, file_task_runner, element));
+ element_readers.push_back(make_scoped_ptr(
+ new FileElementReader(body, file_task_runner, element)));
break;
case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
// If |body| contains any filesystem URLs, the caller should have
// supplied a FileSystemContext.
DCHECK(file_system_context);
element_readers.push_back(
- new content::UploadFileSystemFileElementReader(
- file_system_context,
- element.filesystem_url(),
- element.offset(),
- element.length(),
- element.expected_modification_time()));
+ make_scoped_ptr(new content::UploadFileSystemFileElementReader(
+ file_system_context, element.filesystem_url(), element.offset(),
+ element.length(), element.expected_modification_time())));
break;
case ResourceRequestBody::Element::TYPE_BLOB: {
DCHECK_EQ(std::numeric_limits<uint64_t>::max(), element.length());
DCHECK_EQ(0ul, element.offset());
scoped_ptr<storage::BlobDataHandle> handle =
blob_context->GetBlobDataFromUUID(element.blob_uuid());
- element_readers.push_back(new storage::UploadBlobElementReader(
- handle.Pass(), file_system_context, file_task_runner));
+ element_readers.push_back(
+ make_scoped_ptr(new storage::UploadBlobElementReader(
+ std::move(handle), file_system_context, file_task_runner)));
break;
}
case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY:
+ case ResourceRequestBody::Element::TYPE_BYTES_DESCRIPTION:
case ResourceRequestBody::Element::TYPE_UNKNOWN:
NOTREACHED();
break;
}
}
- return make_scoped_ptr(
- new net::ElementsUploadDataStream(element_readers.Pass(),
- body->identifier()));
+ return make_scoped_ptr(new net::ElementsUploadDataStream(
+ std::move(element_readers), body->identifier()));
}
} // namespace content
diff --git a/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc b/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
index ae79dd93cf1..fc92cc185aa 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
@@ -4,11 +4,14 @@
#include "content/browser/loader/upload_data_stream_builder.h"
+#include <stdint.h>
+
#include <algorithm>
#include <string>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
+#include "base/macros.h"
#include "base/run_loop.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -41,10 +44,10 @@ TEST(UploadDataStreamBuilderTest, CreateUploadDataStream) {
const std::string kBlobData = "blobdata";
const char kData[] = "123";
const base::FilePath::StringType kFilePath = FILE_PATH_LITERAL("abc");
- const uint64 kFileOffset = 10U;
- const uint64 kFileLength = 100U;
+ const uint64_t kFileOffset = 10U;
+ const uint64_t kFileLength = 100U;
const base::Time kFileTime = base::Time::FromDoubleT(999);
- const int64 kIdentifier = 12345;
+ const int64_t kIdentifier = 12345;
BlobStorageContext context;
BlobDataBuilder builder(kBlob);
@@ -81,7 +84,7 @@ TEST(UploadDataStreamBuilderTest, CreateUploadDataStream) {
const storage::UploadBlobElementReader* r3 =
static_cast<storage::UploadBlobElementReader*>(
- (*upload->GetElementReaders())[2]);
+ (*upload->GetElementReaders())[2].get());
ASSERT_TRUE(r3);
EXPECT_EQ("blobuuid", r3->uuid());
}
@@ -158,7 +161,7 @@ TEST(UploadDataStreamBuilderTest, ResetUploadStreamWithBlob) {
const std::string kBlob = "blobuuid";
const std::string kBlobData = "blobdata";
const int kBlobDataLength = 8;
- const int64 kIdentifier = 12345;
+ const int64_t kIdentifier = 12345;
BlobStorageContext blob_storage_context;
BlobDataBuilder builder(kBlob);