summaryrefslogtreecommitdiff
path: root/chromium/content/browser/loader
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 15:28:34 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:54:51 +0000
commit2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch)
treeeb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/content/browser/loader
parentb014812705fc80bff0a5c120dfcef88f349816dc (diff)
downloadqtwebengine-chromium-2a19c63448c84c1805fb1a585c3651318bb86ca7.tar.gz
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/content/browser/loader')
-rw-r--r--chromium/content/browser/loader/cors_file_origin_browsertest.cc86
-rw-r--r--chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc235
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler.cc60
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler.h4
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc2
-rw-r--r--chromium/content/browser/loader/data_pipe_to_source_stream.cc6
-rw-r--r--chromium/content/browser/loader/data_pipe_to_source_stream.h5
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.cc15
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.h1
-rw-r--r--chromium/content/browser/loader/download_utils_impl.cc (renamed from chromium/content/browser/loader/navigation_loader_util.cc)11
-rw-r--r--chromium/content/browser/loader/download_utils_impl.h22
-rw-r--r--chromium/content/browser/loader/downloaded_temp_file_impl.cc30
-rw-r--r--chromium/content/browser/loader/downloaded_temp_file_impl.h40
-rw-r--r--chromium/content/browser/loader/intercepting_resource_handler.cc8
-rw-r--r--chromium/content/browser/loader/layered_resource_handler.cc5
-rw-r--r--chromium/content/browser/loader/layered_resource_handler.h1
-rw-r--r--chromium/content/browser/loader/loader_browsertest.cc50
-rw-r--r--chromium/content/browser/loader/merkle_integrity_source_stream.cc2
-rw-r--r--chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc16
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler.cc9
-rw-r--r--chromium/content/browser/loader/mock_resource_loader.cc9
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.cc90
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.h13
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc74
-rw-r--r--chromium/content/browser/loader/navigation_loader_util.h34
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.h10
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc272
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.h8
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc97
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_unittest.cc6
-rw-r--r--chromium/content/browser/loader/null_resource_controller.cc9
-rw-r--r--chromium/content/browser/loader/null_resource_controller.h2
-rw-r--r--chromium/content/browser/loader/prefetch_browsertest.cc34
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.cc36
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.h18
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.cc55
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.h27
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.cc376
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.h138
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc925
-rw-r--r--chromium/content/browser/loader/resource_buffer.cc173
-rw-r--r--chromium/content/browser/loader/resource_buffer.h122
-rw-r--r--chromium/content/browser/loader/resource_buffer_unittest.cc137
-rw-r--r--chromium/content/browser/loader/resource_controller.h11
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc195
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h52
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc153
-rw-r--r--chromium/content/browser/loader/resource_handler.cc5
-rw-r--r--chromium/content/browser/loader/resource_handler.h8
-rw-r--r--chromium/content/browser/loader/resource_hints_impl.cc38
-rw-r--r--chromium/content/browser/loader/resource_loader.cc111
-rw-r--r--chromium/content/browser/loader/resource_loader.h26
-rw-r--r--chromium/content/browser/loader/resource_loader_unittest.cc3
-rw-r--r--chromium/content/browser/loader/resource_message_filter.cc31
-rw-r--r--chromium/content/browser/loader/resource_message_filter.h2
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc29
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h41
-rw-r--r--chromium/content/browser/loader/resource_scheduler_filter.cc20
-rw-r--r--chromium/content/browser/loader/resource_scheduler_filter.h23
-rw-r--r--chromium/content/browser/loader/stream_resource_handler.cc4
-rw-r--r--chromium/content/browser/loader/stream_resource_handler.h2
-rw-r--r--chromium/content/browser/loader/temporary_file_stream.cc71
-rw-r--r--chromium/content/browser/loader/temporary_file_stream.h46
-rw-r--r--chromium/content/browser/loader/temporary_file_stream_unittest.cc121
-rw-r--r--chromium/content/browser/loader/test_resource_handler.cc13
-rw-r--r--chromium/content/browser/loader/test_resource_handler.h12
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl_unittest.cc131
-rw-r--r--chromium/content/browser/loader/wake_lock_resource_throttle.cc70
-rw-r--r--chromium/content/browser/loader/wake_lock_resource_throttle.h46
69 files changed, 1145 insertions, 3392 deletions
diff --git a/chromium/content/browser/loader/cors_file_origin_browsertest.cc b/chromium/content/browser/loader/cors_file_origin_browsertest.cc
index af3ed282f18..2b0e7a609ba 100644
--- a/chromium/content/browser/loader/cors_file_origin_browsertest.cc
+++ b/chromium/content/browser/loader/cors_file_origin_browsertest.cc
@@ -12,7 +12,10 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/scoped_command_line.h"
+#include "base/test/scoped_feature_list.h"
#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.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"
@@ -24,6 +27,7 @@
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/embedded_test_server/request_handler_util.h"
#include "services/network/public/cpp/cors/cors.h"
+#include "services/network/public/cpp/features.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -37,11 +41,20 @@ using net::test_server::HttpResponse;
// Tests end to end Origin header and CORS check behaviors without
// --allow-file-access-from-files flag.
-class CORSFileOriginBrowserTest : public ContentBrowserTest {
+class CORSFileOriginBrowserTest : public ContentBrowserTest,
+ public testing::WithParamInterface<bool> {
public:
CORSFileOriginBrowserTest()
: pass_string_(base::ASCIIToUTF16("PASS")),
- fail_string_(base::ASCIIToUTF16("FAIL")) {}
+ fail_string_(base::ASCIIToUTF16("FAIL")) {
+ if (GetParam()) {
+ scoped_feature_list_.InitAndEnableFeature(
+ network::features::kOutOfBlinkCORS);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ network::features::kOutOfBlinkCORS);
+ }
+ }
~CORSFileOriginBrowserTest() override = default;
protected:
@@ -84,7 +97,15 @@ class CORSFileOriginBrowserTest : public ContentBrowserTest {
private:
bool AllowFileAccessFromFiles() const override { return false; }
+ virtual bool IsWebSecurityEnabled() const { return true; }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ if (!IsWebSecurityEnabled()) {
+ command_line->AppendSwitch(switches::kDisableWebSecurity);
+ }
+ ContentBrowserTest::SetUpCommandLine(command_line);
+ }
void SetUpOnMainThread() override {
base::AutoLock lock(lock_);
@@ -147,6 +168,9 @@ class CORSFileOriginBrowserTest : public ContentBrowserTest {
const base::string16 pass_string_;
const base::string16 fail_string_;
+ base::test::ScopedFeatureList scoped_command_line_;
+ base::test::ScopedFeatureList scoped_feature_list_;
+
DISALLOW_COPY_AND_ASSIGN(CORSFileOriginBrowserTest);
};
@@ -158,7 +182,16 @@ class CORSFileOriginBrowserTestWithAllowFileAccessFromFiles
bool AllowFileAccessFromFiles() const override { return true; }
};
-IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTest,
+// Tests end to end Origin header and CORS check behaviors with
+// --disable-web-security flag.
+class CORSFileOriginBrowserTestWithDisableWebSecurity
+ : public CORSFileOriginBrowserTest {
+ private:
+ bool AllowFileAccessFromFiles() const override { return false; }
+ bool IsWebSecurityEnabled() const override { return false; }
+};
+
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTest,
AccessControlAllowOriginIsNull) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
@@ -170,7 +203,7 @@ IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTest,
EXPECT_TRUE(is_preflight_requested());
}
-IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTest,
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTest,
AccessControlAllowOriginIsFile) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
@@ -182,7 +215,7 @@ IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTest,
EXPECT_TRUE(is_preflight_requested());
}
-IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
AccessControlAllowOriginIsNull) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
@@ -194,7 +227,7 @@ IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
EXPECT_TRUE(is_preflight_requested());
}
-IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
AccessControlAllowOriginIsFile) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
@@ -206,6 +239,47 @@ IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
EXPECT_TRUE(is_preflight_requested());
}
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithDisableWebSecurity,
+ AccessControlAllowOriginIsNull) {
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(), CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?port=%d&allow=%s&origin=%s",
+ port(), "unused", ""))));
+
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
+ EXPECT_FALSE(is_preflight_requested());
+}
+
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithDisableWebSecurity,
+ AccessControlAllowOriginIsFile) {
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(), CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?port=%d&allow=%s&origin=%s",
+ port(), "unused", ""))));
+
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
+ EXPECT_FALSE(is_preflight_requested());
+}
+
+// --allow-file-access-from-files is currently not supported by OOR-CORS.
+// We may remove the feature.
+INSTANTIATE_TEST_CASE_P(
+ /* No test prefix */,
+ CORSFileOriginBrowserTest,
+ ::testing::Values(false));
+
+INSTANTIATE_TEST_CASE_P(
+ /* No test prefix */,
+ CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
+ ::testing::Values(false));
+
+INSTANTIATE_TEST_CASE_P(
+ /* No test prefix */,
+ CORSFileOriginBrowserTestWithDisableWebSecurity,
+ ::testing::Values(false, true));
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc b/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
index 494ecda070c..321ab2c8e87 100644
--- a/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
+++ b/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -7,11 +7,12 @@
#include <utility>
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/strings/pattern.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/loader/cross_site_document_resource_handler.h"
@@ -31,15 +32,19 @@
#include "content/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/test/test_content_browser_client.h"
+#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
using testing::Not;
using testing::HasSubstr;
+using Action = network::CrossOriginReadBlocking::Action;
namespace {
@@ -83,6 +88,14 @@ void InspectHistograms(const base::HistogramTester& histograms,
const HistogramExpectations& expectations,
const std::string& resource_name,
ResourceType resource_type) {
+ // //services/network doesn't have access to content::ResourceType and
+ // therefore cannot log some XSDB UMAs.
+ bool is_restricted_uma_expected = false;
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ is_restricted_uma_expected = true;
+ FetchHistogramsFromChildProcesses();
+ }
+
std::string bucket;
if (base::MatchPattern(resource_name, "*.html")) {
bucket = "HTML";
@@ -103,16 +116,23 @@ void InspectHistograms(const base::HistogramTester& histograms,
std::string base = "SiteIsolation.XSD.Browser";
expected_counts[base + ".Action"] = 2;
if ((base::MatchPattern(resource_name, "*prefixed*") || bucket == "Others") &&
- (0 != (expectations & kShouldBeBlocked))) {
+ (0 != (expectations & kShouldBeBlocked)) && !is_restricted_uma_expected) {
expected_counts[base + ".BlockedForParserBreaker"] = 1;
}
if (0 != (expectations & kShouldBeSniffed))
expected_counts[base + ".BytesReadForSniffing"] = 1;
- if (0 != (expectations & kShouldBeBlocked)) {
+ if (0 != (expectations & kShouldBeBlocked && !is_restricted_uma_expected)) {
expected_counts[base + ".Blocked"] = 1;
expected_counts[base + ".Blocked." + bucket] = 1;
+ }
+ if (0 != (expectations & kShouldBeBlocked)) {
expected_counts[base + ".Blocked.ContentLength.WasAvailable"] = 1;
- if (0 != (expectations & kShouldHaveContentLength))
+ bool should_have_content_length =
+ 0 != (expectations & kShouldHaveContentLength);
+ histograms.ExpectBucketCount(base + ".Blocked.ContentLength.WasAvailable",
+ should_have_content_length, 1);
+
+ if (should_have_content_length)
expected_counts[base + ".Blocked.ContentLength.ValueIfAvailable"] = 1;
}
@@ -124,7 +144,7 @@ void InspectHistograms(const base::HistogramTester& histograms,
<< ", expectations=" << expectations;
// Determine if the bucket for the resource type (XHR) was incremented.
- if (0 != (expectations & kShouldBeBlocked)) {
+ if (0 != (expectations & kShouldBeBlocked) && !is_restricted_uma_expected) {
EXPECT_THAT(histograms.GetAllSamples(base + ".Blocked"),
testing::ElementsAre(base::Bucket(resource_type, 1)))
<< "The wrong Blocked bucket was incremented.";
@@ -132,6 +152,26 @@ void InspectHistograms(const base::HistogramTester& histograms,
testing::ElementsAre(base::Bucket(resource_type, 1)))
<< "The wrong Blocked bucket was incremented.";
}
+
+ // SiteIsolation.XSD.Browser.Action should always include kResponseStarted.
+ histograms.ExpectBucketCount(base + ".Action",
+ static_cast<int>(Action::kResponseStarted), 1);
+
+ // Second value in SiteIsolation.XSD.Browser.Action depends on |expectations|.
+ Action expected_action = static_cast<Action>(-1);
+ if (expectations & kShouldBeBlocked) {
+ if (expectations & kShouldBeSniffed)
+ expected_action = Action::kBlockedAfterSniffing;
+ else
+ expected_action = Action::kBlockedWithoutSniffing;
+ } else {
+ if (expectations & kShouldBeSniffed)
+ expected_action = Action::kAllowedAfterSniffing;
+ else
+ expected_action = Action::kAllowedWithoutSniffing;
+ }
+ histograms.ExpectBucketCount(base + ".Action",
+ static_cast<int>(expected_action), 1);
}
// Helper for intercepting a resource request to the given URL and capturing the
@@ -290,16 +330,18 @@ class DisableWebSecurityContentBrowserClient : public TestContentBrowserClient {
// Note that this BaseTest class does not specify an isolation mode via
// command-line flags. Most of the tests are in the --site-per-process subclass
// below.
-class CrossSiteDocumentBlockingBaseTest : public ContentBrowserTest {
+class CrossSiteDocumentBlockingTest : public ContentBrowserTest {
public:
- CrossSiteDocumentBlockingBaseTest() {}
- ~CrossSiteDocumentBlockingBaseTest() override {}
+ CrossSiteDocumentBlockingTest() {}
+ ~CrossSiteDocumentBlockingTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
// EmbeddedTestServer::InitializeAndListen() initializes its |base_url_|
// which is required below. This cannot invoke Start() however as that kicks
// off the "EmbeddedTestServer IO Thread" which then races with
// initialization in ContentBrowserTest::SetUp(), http://crbug.com/674545.
+ // Additionally the server should not be started prior to setting up
+ // ControllableHttpResponse(s) in some individual tests below.
ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
// Add a host resolver rule to map all outgoing requests to the test server.
@@ -313,10 +355,6 @@ class CrossSiteDocumentBlockingBaseTest : public ContentBrowserTest {
}
void SetUpOnMainThread() override {
- // Complete the manual Start() after ContentBrowserTest's own
- // initialization, ref. comment on InitializeAndListen() above.
- embedded_test_server()->StartAcceptingConnections();
-
// Disable web security via the ContentBrowserClient and notify the current
// renderer process.
old_client = SetBrowserClientForTesting(&new_client);
@@ -329,22 +367,6 @@ class CrossSiteDocumentBlockingBaseTest : public ContentBrowserTest {
DisableWebSecurityContentBrowserClient new_client;
ContentBrowserClient* old_client = nullptr;
- DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentBlockingBaseTest);
-};
-
-// Most tests here use --site-per-process, which enables document blocking
-// everywhere.
-class CrossSiteDocumentBlockingTest : public CrossSiteDocumentBlockingBaseTest {
- public:
- CrossSiteDocumentBlockingTest() {}
- ~CrossSiteDocumentBlockingTest() override {}
-
- void SetUpCommandLine(base::CommandLine* command_line) override {
- IsolateAllSitesForTesting(command_line);
- CrossSiteDocumentBlockingBaseTest::SetUpCommandLine(command_line);
- }
-
- private:
DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentBlockingTest);
};
@@ -355,6 +377,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockDocuments) {
// possible since we run the browser without the same origin policy, allowing
// it to see the response body if it makes it to the renderer (even if the
// renderer would normally block access to it).
+ embedded_test_server()->StartAcceptingConnections();
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -417,7 +440,8 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockDocuments) {
// jsonp.* - JSONP (i.e., script) mislabeled as a document.
// img.* - Contents that won't match the document label.
// valid.* - Correctly labeled responses of non-document types.
- const char* sniff_allowed_resources[] = {"js.html",
+ const char* sniff_allowed_resources[] = {"html-prefix.txt",
+ "js.html",
"comment_js.html",
"js.xml",
"js.json",
@@ -469,6 +493,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockDocuments) {
// be a problem for script files mislabeled as HTML/XML/JSON/text (i.e., the
// reason for sniffing), since script tags won't send Range headers.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, RangeRequest) {
+ embedded_test_server()->StartAcceptingConnections();
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -519,6 +544,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockForVariousTargets) {
// TODO(nick): Split up these cases, and add positive assertions here about
// what actually happens in these various resource-block cases.
+ embedded_test_server()->StartAcceptingConnections();
GURL foo("http://foo.com/cross_site_document_blocking/request_target.html");
EXPECT_TRUE(NavigateToURL(shell(), foo));
@@ -530,6 +556,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockForVariousTargets) {
// Regression test for https://crbug.com/814913.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest,
BlockRequestFromErrorPage) {
+ embedded_test_server()->StartAcceptingConnections();
GURL error_url = embedded_test_server()->GetURL("bar.com", "/close-socket");
GURL subresource_url =
embedded_test_server()->GetURL("foo.com", "/site_isolation/json.js");
@@ -560,10 +587,10 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest,
}
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
- GURL foo_url("http://foo.com/title1.html");
- EXPECT_TRUE(NavigateToURL(shell(), foo_url));
+ embedded_test_server()->StartAcceptingConnections();
// Prepare to intercept the network request at the IPC layer.
+ // This has to be done before the RenderFrameHostImpl is created.
//
// Note: we want to verify that the blocking prevents the data from being sent
// over IPC. Testing later (e.g. via Response/Headers Web APIs) might give a
@@ -572,6 +599,10 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
GURL bar_url("http://bar.com/cross_site_document_blocking/headers-test.json");
RequestInterceptor interceptor(bar_url);
+ // Navigate to the test page.
+ GURL foo_url("http://foo.com/title1.html");
+ EXPECT_TRUE(NavigateToURL(shell(), foo_url));
+
// Issue the request that will be intercepted
EXPECT_TRUE(ExecuteScript(shell(),
base::StringPrintf("fetch('%s').catch(error => {})",
@@ -580,7 +611,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
// Verify that the response completed successfully and was blocked.
ASSERT_EQ(net::OK, interceptor.completion_status().error_code);
- ASSERT_TRUE(interceptor.completion_status().blocked_cross_site_document);
+ ASSERT_TRUE(interceptor.completion_status().should_report_corb_blocking);
// Verify that safelisted headers have not been removed by XSDB.
// See https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name.
@@ -623,6 +654,113 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
EXPECT_EQ(0u, interceptor.response_head().content_length);
}
+IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, PrefetchIsNotImpacted) {
+ // Prepare for intercepting the resource request for testing prefetching.
+ const char* kPrefetchResourcePath = "/prefetch-test";
+ net::test_server::ControllableHttpResponse response(embedded_test_server(),
+ kPrefetchResourcePath);
+
+ // Navigate to a webpage containing a cross-origin frame.
+ embedded_test_server()->StartAcceptingConnections();
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Inject a cross-origin <link rel="prefetch" ...> into the main frame.
+ // TODO(lukasza): https://crbug.com/827633#c5: We might need to switch to
+ // listening to the onload event below (after/if CORB starts to consistently
+ // avoid injecting net errors).
+ const char* prefetch_injection_script_template = R"(
+ var link = document.createElement("link");
+ link.rel = "prefetch";
+ link.href = "/cross-site/b.com%s";
+ link.as = "fetch";
+
+ window.is_prefetch_done = false;
+ function mark_prefetch_as_done() { window.is_prefetch_done = true }
+ link.onerror = mark_prefetch_as_done;
+
+ document.getElementsByTagName('head')[0].appendChild(link);
+ )";
+ std::string prefetch_injection_script = base::StringPrintf(
+ prefetch_injection_script_template, kPrefetchResourcePath);
+ EXPECT_TRUE(
+ ExecuteScript(shell()->web_contents(), prefetch_injection_script));
+
+ // Respond to the prefetch request in a way that:
+ // 1) will enable caching
+ // 2) won't finish until after CORB has blocked the response.
+ FetchHistogramsFromChildProcesses();
+ base::HistogramTester histograms;
+ std::string response_bytes =
+ "HTTP/1.1 200 OK\r\n"
+ "Cache-Control: public, max-age=10\r\n"
+ "Content-Type: text/html\r\n"
+ "X-Content-Type-Options: nosniff\r\n"
+ "\r\n"
+ "<p>contents of the response</p>";
+ response.WaitForRequest();
+ response.Send(response_bytes);
+
+ // Verify that CORB blocked the response.
+ // TODO(lukasza): https://crbug.com/827633#c5: We might need to switch to
+ // listening to the onload event below (after/if CORB starts to consistently
+ // avoid injecting net errors).
+ std::string wait_script = R"(
+ function notify_prefetch_is_done() { domAutomationController.send(123); }
+
+ if (window.is_prefetch_done) {
+ // Can notify immediately if |window.is_prefetch_done| has already been
+ // set by |prefetch_injection_script|.
+ notify_prefetch_is_done();
+ } else {
+ // Otherwise wait for CORB's empty response to reach the renderer.
+ link = document.getElementsByTagName('link')[0];
+ link.onerror = notify_prefetch_is_done;
+ }
+ )";
+ int answer;
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(shell()->web_contents(), wait_script,
+ &answer));
+ EXPECT_EQ(123, answer);
+ InspectHistograms(histograms, kShouldBeBlockedWithoutSniffing, "x.html",
+ RESOURCE_TYPE_PREFETCH);
+
+ // Finish the HTTP response - this should store the response in the cache.
+ response.Done();
+
+ // Stop the HTTP server - this means the only way to get the response in
+ // the |fetch_script| below is to get it from the cache (e.g. if the request
+ // goes to the network there will be no HTTP server to handle it).
+ // Note that stopping the HTTP server is not strictly required for the test to
+ // be robust - ControllableHttpResponse handles only a single request, so
+ // wouldn't handle the |fetch_script| request even if the HTTP server was
+ // still running.
+ EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+
+ // Verify that the cached response is available to the same-origin subframe
+ // (e.g. that the network cache in the browser process got populated despite
+ // CORB blocking).
+ const char* fetch_script_template = R"(
+ fetch('%s')
+ .then(response => response.text())
+ .then(responseBody => {
+ domAutomationController.send(responseBody);
+ })
+ .catch(error => {
+ var errorMessage = 'error: ' + error;
+ console.log(errorMessage);
+ domAutomationController.send(errorMessage);
+ }); )";
+ std::string fetch_script =
+ base::StringPrintf(fetch_script_template, kPrefetchResourcePath);
+ std::string response_body;
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractString(shell()->web_contents()->GetAllFrames()[1],
+ fetch_script, &response_body));
+ EXPECT_EQ("<p>contents of the response</p>", response_body);
+}
+
// This test class sets up a service worker that can be used to try to respond
// to same-origin requests with cross-origin responses.
class CrossSiteDocumentBlockingServiceWorkerTest : public ContentBrowserTest {
@@ -735,6 +873,12 @@ class CrossSiteDocumentBlockingServiceWorkerTest : public ContentBrowserTest {
// TODO(lukasza): https://crbug.com/715640: This test might become invalid
// after servicification of service workers.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingServiceWorkerTest, NoNetwork) {
+ // Skip this test when servicification of service workers (S13nServiceWorker)
+ // is enabled because the browser process doesn't see the request or response
+ // when the request is handled entirely within the service worker.
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
SetUpServiceWorker();
base::HistogramTester histograms;
@@ -766,6 +910,11 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingServiceWorkerTest,
NetworkToServiceWorkerResponse) {
SetUpServiceWorker();
+ // Make sure that the histograms generated by a service worker registration
+ // have been recorded.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ FetchHistogramsFromChildProcesses();
+
// Build a script for XHR-ing a cross-origin, nosniff HTML document.
GURL cross_origin_url =
GetURLOnCrossOriginServer("/site_isolation/nosniff.txt");
@@ -826,6 +975,7 @@ class CrossSiteDocumentBlockingKillSwitchTest
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingKillSwitchTest,
NoBlockingWithKillSwitch) {
// Load a page that issues illegal cross-site document requests to bar.com.
+ embedded_test_server()->StartAcceptingConnections();
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -855,6 +1005,7 @@ class CrossSiteDocumentBlockingDisableWebSecurityTest
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingDisableWebSecurityTest,
DisableBlocking) {
// Load a page that issues illegal cross-site document requests.
+ embedded_test_server()->StartAcceptingConnections();
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -885,6 +1036,7 @@ class CrossSiteDocumentBlockingDisableVsFeatureTest
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingDisableVsFeatureTest,
DisableBlocking) {
// Load a page that issues illegal cross-site document requests.
+ embedded_test_server()->StartAcceptingConnections();
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -894,23 +1046,9 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingDisableVsFeatureTest,
EXPECT_FALSE(was_blocked);
}
-// Even without any Site Isolation, document blocking should be turned on by
-// default.
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingBaseTest,
- BlockDocumentsByDefault) {
- // Load a page that issues illegal cross-site document requests to bar.com.
- GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
- EXPECT_TRUE(NavigateToURL(shell(), foo_url));
-
- bool was_blocked;
- ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell(), "sendRequest(\"valid.html\");", &was_blocked));
- EXPECT_TRUE(was_blocked);
-}
-
// Test class to verify that documents are blocked for isolated origins as well.
class CrossSiteDocumentBlockingIsolatedOriginTest
- : public CrossSiteDocumentBlockingBaseTest {
+ : public CrossSiteDocumentBlockingTest {
public:
CrossSiteDocumentBlockingIsolatedOriginTest() {}
~CrossSiteDocumentBlockingIsolatedOriginTest() override {}
@@ -918,7 +1056,7 @@ class CrossSiteDocumentBlockingIsolatedOriginTest
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kIsolateOrigins,
"http://bar.com");
- CrossSiteDocumentBlockingBaseTest::SetUpCommandLine(command_line);
+ CrossSiteDocumentBlockingTest::SetUpCommandLine(command_line);
}
private:
@@ -927,6 +1065,7 @@ class CrossSiteDocumentBlockingIsolatedOriginTest
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingIsolatedOriginTest,
BlockDocumentsFromIsolatedOrigin) {
+ embedded_test_server()->StartAcceptingConnections();
if (AreAllSitesIsolatedForTesting())
return;
diff --git a/chromium/content/browser/loader/cross_site_document_resource_handler.cc b/chromium/content/browser/loader/cross_site_document_resource_handler.cc
index 9924a53b147..90792270128 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler.cc
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler.cc
@@ -20,6 +20,7 @@
#include "content/browser/loader/detachable_resource_handler.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/site_instance_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
@@ -66,16 +67,15 @@ void CrossSiteDocumentResourceHandler::LogBlockedResponseOnUIThread(
if (!web_contents)
return;
- ukm::UkmRecorder* recorder = ukm::UkmRecorder::Get();
- ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
- recorder->UpdateSourceURL(source_id, web_contents->GetLastCommittedURL());
+ ukm::SourceId source_id = static_cast<WebContentsImpl*>(web_contents)
+ ->GetUkmSourceIdForLastCommittedSource();
ukm::builders::SiteIsolation_XSD_Browser_Blocked(source_id)
.SetCanonicalMimeType(static_cast<int64_t>(canonical_mime_type))
.SetContentLengthWasZero(content_length == 0)
.SetContentResourceType(resource_type)
.SetHttpResponseCode(http_response_code)
.SetNeededSniffing(needed_sniffing)
- .Record(recorder);
+ .Record(ukm::UkmRecorder::Get());
}
void CrossSiteDocumentResourceHandler::LogBlockedResponse(
@@ -166,6 +166,14 @@ class CrossSiteDocumentResourceHandler::Controller : public ResourceController {
}
}
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ Resume();
+ }
+
void Cancel() override {
MarkAsUsed();
document_handler_->Cancel();
@@ -212,8 +220,6 @@ void CrossSiteDocumentResourceHandler::OnResponseStarted(
network::ResourceResponse* response,
std::unique_ptr<ResourceController> controller) {
has_response_started_ = true;
- http_response_code_ =
- response->head.headers ? response->head.headers->response_code() : 0;
network::CrossOriginReadBlocking::LogAction(
network::CrossOriginReadBlocking::Action::kResponseStarted);
@@ -388,8 +394,8 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
// If we have some new data, ask the |analyzer_| to sniff it.
analyzer_->SniffResponseBody(data, new_data_offset);
- const bool confirmed_allowed = analyzer_->should_allow();
- confirmed_blockable = analyzer_->should_block();
+ const bool confirmed_allowed = analyzer_->ShouldAllow();
+ confirmed_blockable = analyzer_->ShouldBlock();
DCHECK(!(confirmed_blockable && confirmed_allowed));
// If sniffing didn't yield a conclusive response, and we haven't read too
@@ -425,11 +431,13 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
: "null",
"url", request()->url().spec());
- LogBlockedResponse(info, http_response_code_);
+ LogBlockedResponse(info, analyzer_->http_response_code());
// Block the response and throw away the data. Report zero bytes read.
blocked_read_completed_ = true;
- info->set_blocked_cross_site_document(true);
+ info->set_blocked_response_from_reaching_renderer(true);
+ if (analyzer_->ShouldReportBlockedResponse())
+ info->set_should_report_corb_blocking(true);
network::CrossOriginReadBlocking::SanitizeBlockedResponse(
pending_response_start_);
@@ -535,10 +543,17 @@ void CrossSiteDocumentResourceHandler::OnResponseCompleted(
bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
const network::ResourceResponse& response) {
+ // Give embedder a chance to skip document blocking for this response.
+ const char* initiator_scheme_exception =
+ GetContentClient()
+ ->browser()
+ ->GetInitatorSchemeBypassingDocumentBlocking();
+
+ // Delegate most decisions to CrossOriginReadBlocking::ResponseAnalyzer.
analyzer_ =
std::make_unique<network::CrossOriginReadBlocking::ResponseAnalyzer>(
- *request(), response);
- if (analyzer_->should_allow())
+ *request(), response, initiator_scheme_exception);
+ if (analyzer_->ShouldAllow())
return false;
// Check if the response's site needs to have its documents protected. By
@@ -567,21 +582,12 @@ bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
if (!info || info->GetChildID() == -1)
return false;
- // Give embedder a chance to skip document blocking for this response.
- const char* initiator_scheme_exception =
- GetContentClient()
- ->browser()
- ->GetInitatorSchemeBypassingDocumentBlocking();
- if (initiator_scheme_exception && request()->initiator().has_value() &&
- request()->initiator()->scheme() == initiator_scheme_exception) {
- return false;
- }
-
- // Don't block plugin requests with universal access (e.g., Flash). Such
- // requests are made without CORS, and thus dont have an Origin request
- // header. Other plugin requests (e.g., NaCl) are made using CORS and have an
- // Origin request header. If they fail the CORS check above, they should be
- // blocked.
+ // Don't block plugin requests.
+ // TODO(lukasza): Only disable CORB for plugins with universal access (see
+ // PepperURLLoaderHost::has_universal_access_), because only such plugins may
+ // have their own CORS-like mechanisms - e.g. crossdomain.xml in Flash). We
+ // should still enforce CORB for other kinds of plugins (i.e. ones without
+ // universal access).
if (info->GetResourceType() == RESOURCE_TYPE_PLUGIN_RESOURCE &&
is_nocors_plugin_request_) {
return false;
diff --git a/chromium/content/browser/loader/cross_site_document_resource_handler.h b/chromium/content/browser/loader/cross_site_document_resource_handler.h
index 447c6ed2699..1598fb024bd 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler.h
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler.h
@@ -164,10 +164,6 @@ class CONTENT_EXPORT CrossSiteDocumentResourceHandler
// completed, and thus it is safe to cancel or detach on the next read.
bool blocked_read_completed_ = false;
- // The HTTP response code (e.g. 200 or 404) received in response to this
- // resource request.
- int http_response_code_ = 0;
-
base::WeakPtrFactory<CrossSiteDocumentResourceHandler> weak_this_;
DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentResourceHandler);
diff --git a/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc b/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc
index 7f66b566c8b..99405d1b48e 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc
@@ -20,7 +20,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/loader/intercepting_resource_handler.h"
#include "content/browser/loader/mime_sniffing_resource_handler.h"
diff --git a/chromium/content/browser/loader/data_pipe_to_source_stream.cc b/chromium/content/browser/loader/data_pipe_to_source_stream.cc
index 8a5c372798f..4a3694f5b01 100644
--- a/chromium/content/browser/loader/data_pipe_to_source_stream.cc
+++ b/chromium/content/browser/loader/data_pipe_to_source_stream.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/data_pipe_to_source_stream.h"
+#include <utility>
+
#include "base/auto_reset.h"
#include "net/base/io_buffer.h"
@@ -30,7 +32,7 @@ std::string DataPipeToSourceStream::Description() const {
int DataPipeToSourceStream::Read(net::IOBuffer* buf,
int buf_size,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
base::AutoReset<bool>(&inside_read_, true);
if (!body_.get()) {
@@ -56,7 +58,7 @@ int DataPipeToSourceStream::Read(net::IOBuffer* buf,
return 0;
case MOJO_RESULT_SHOULD_WAIT:
// Data is not available yet.
- pending_callback_ = callback;
+ pending_callback_ = std::move(callback);
output_buf_ = buf;
output_buf_size_ = buf_size;
handle_watcher_.ArmOrNotify();
diff --git a/chromium/content/browser/loader/data_pipe_to_source_stream.h b/chromium/content/browser/loader/data_pipe_to_source_stream.h
index e45d2482e87..f77287f0611 100644
--- a/chromium/content/browser/loader/data_pipe_to_source_stream.h
+++ b/chromium/content/browser/loader/data_pipe_to_source_stream.h
@@ -8,6 +8,7 @@
#include "content/common/content_export.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
+#include "net/base/completion_once_callback.h"
#include "net/filter/source_stream.h"
namespace content {
@@ -19,7 +20,7 @@ class CONTENT_EXPORT DataPipeToSourceStream final : public net::SourceStream {
int Read(net::IOBuffer* buf,
int buf_size,
- const net::CompletionCallback& callback) override;
+ net::CompletionOnceCallback callback) override;
std::string Description() const override;
private:
@@ -33,7 +34,7 @@ class CONTENT_EXPORT DataPipeToSourceStream final : public net::SourceStream {
scoped_refptr<net::IOBuffer> output_buf_;
int output_buf_size_ = 0;
- net::CompletionCallback pending_callback_;
+ net::CompletionOnceCallback pending_callback_;
DISALLOW_COPY_AND_ASSIGN(DataPipeToSourceStream);
};
diff --git a/chromium/content/browser/loader/detachable_resource_handler.cc b/chromium/content/browser/loader/detachable_resource_handler.cc
index b8222d203d1..26593e97ec0 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.cc
+++ b/chromium/content/browser/loader/detachable_resource_handler.cc
@@ -38,6 +38,14 @@ class DetachableResourceHandler::Controller : public ResourceController {
detachable_handler_->ResumeInternal();
}
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ Resume();
+ }
+
void Cancel() override {
MarkAsUsed();
detachable_handler_->Cancel();
@@ -249,13 +257,6 @@ void DetachableResourceHandler::OnResponseCompleted(
std::make_unique<Controller>(this));
}
-void DetachableResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- if (!next_handler_)
- return;
-
- next_handler_->OnDataDownloaded(bytes_downloaded);
-}
-
void DetachableResourceHandler::ResumeInternal() {
parent_read_buffer_ = nullptr;
parent_read_buffer_size_ = nullptr;
diff --git a/chromium/content/browser/loader/detachable_resource_handler.h b/chromium/content/browser/loader/detachable_resource_handler.h
index 972ffd13523..9e7e418a2f2 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.h
+++ b/chromium/content/browser/loader/detachable_resource_handler.h
@@ -69,7 +69,6 @@ class CONTENT_EXPORT DetachableResourceHandler : public ResourceHandler {
void OnResponseCompleted(
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- void OnDataDownloaded(int bytes_downloaded) override;
private:
class Controller;
diff --git a/chromium/content/browser/loader/navigation_loader_util.cc b/chromium/content/browser/loader/download_utils_impl.cc
index 96a7879b520..4af0a41e592 100644
--- a/chromium/content/browser/loader/navigation_loader_util.cc
+++ b/chromium/content/browser/loader/download_utils_impl.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/loader/navigation_loader_util.h"
+#include "content/browser/loader/download_utils_impl.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
@@ -10,13 +10,12 @@
#include "net/http/http_response_headers.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "url/gurl.h"
-#include "url/origin.h"
namespace content {
-namespace navigation_loader_util {
+namespace download_utils {
bool MustDownload(const GURL& url,
- net::HttpResponseHeaders* headers,
+ const net::HttpResponseHeaders* headers,
const std::string& mime_type) {
if (headers) {
std::string disposition;
@@ -43,7 +42,7 @@ bool MustDownload(const GURL& url,
}
bool IsDownload(const GURL& url,
- net::HttpResponseHeaders* headers,
+ const net::HttpResponseHeaders* headers,
const std::string& mime_type) {
if (MustDownload(url, headers, mime_type))
return true;
@@ -54,5 +53,5 @@ bool IsDownload(const GURL& url,
return !headers || headers->response_code() / 100 == 2;
}
-} // namespace navigation_loader_util
+} // namespace download_utils
} // namespace content
diff --git a/chromium/content/browser/loader/download_utils_impl.h b/chromium/content/browser/loader/download_utils_impl.h
new file mode 100644
index 00000000000..724e45ba529
--- /dev/null
+++ b/chromium/content/browser/loader/download_utils_impl.h
@@ -0,0 +1,22 @@
+// Copyright 2018 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_DOWNLOAD_UTILS_IMPL_H_
+#define CONTENT_BROWSER_LOADER_DOWNLOAD_UTILS_IMPL_H_
+
+#include "content/public/browser/download_utils.h"
+
+namespace content {
+namespace download_utils {
+
+// Determines whether given response would result in a download.
+// Note this doesn't handle the case when a plugin exists for the |mime_type|.
+bool IsDownload(const GURL& url,
+ const net::HttpResponseHeaders* headers,
+ const std::string& mime_type);
+
+} // namespace download_utils
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_DOWNLOAD_UTILS_IMPL_H_
diff --git a/chromium/content/browser/loader/downloaded_temp_file_impl.cc b/chromium/content/browser/loader/downloaded_temp_file_impl.cc
deleted file mode 100644
index f699d84df04..00000000000
--- a/chromium/content/browser/loader/downloaded_temp_file_impl.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2016 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/downloaded_temp_file_impl.h"
-
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace content {
-
-// static
-network::mojom::DownloadedTempFilePtr DownloadedTempFileImpl::Create(
- int child_id,
- int request_id) {
- mojo::InterfacePtr<network::mojom::DownloadedTempFile> ptr;
- mojo::MakeStrongBinding(
- std::make_unique<DownloadedTempFileImpl>(child_id, request_id),
- mojo::MakeRequest(&ptr));
- return ptr;
-}
-
-DownloadedTempFileImpl::~DownloadedTempFileImpl() {
- ResourceDispatcherHostImpl::Get()->UnregisterDownloadedTempFile(child_id_,
- request_id_);
-}
-DownloadedTempFileImpl::DownloadedTempFileImpl(int child_id, int request_id)
- : child_id_(child_id), request_id_(request_id) {}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/downloaded_temp_file_impl.h b/chromium/content/browser/loader/downloaded_temp_file_impl.h
deleted file mode 100644
index 07deff40610..00000000000
--- a/chromium/content/browser/loader/downloaded_temp_file_impl.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2016 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_DOWNLOADED_TEMP_FILE_IMPL_H_
-#define CONTENT_BROWSER_LOADER_DOWNLOADED_TEMP_FILE_IMPL_H_
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-
-namespace content {
-
-// DownloadedTempFileImpl is created on the download_to_file mode of resource
-// loading. The instance is held by the client and lives until the client
-// destroys the interface, slightly after the URLLoader is destroyed.
-class CONTENT_EXPORT DownloadedTempFileImpl final
- : public network::mojom::DownloadedTempFile {
- public:
- // Creates a DownloadedTempFileImpl, binds it as a strong interface, and
- // returns the interface ptr to be passed to the client.
- // That means:
- // * The DownloadedTempFile object created here is essentially owned by the
- // client. It keeps alive until the client destroys the other endpoint.
- static network::mojom::DownloadedTempFilePtr Create(int child_id,
- int request_id);
-
- DownloadedTempFileImpl(int child_id, int request_id);
- ~DownloadedTempFileImpl() override;
-
- private:
- const int child_id_;
- const int request_id_;
-
- DISALLOW_COPY_AND_ASSIGN(DownloadedTempFileImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_DOWNLOADED_TEMP_FILE_IMPL_H_
diff --git a/chromium/content/browser/loader/intercepting_resource_handler.cc b/chromium/content/browser/loader/intercepting_resource_handler.cc
index 0b038d238a1..a7c3a1010ea 100644
--- a/chromium/content/browser/loader/intercepting_resource_handler.cc
+++ b/chromium/content/browser/loader/intercepting_resource_handler.cc
@@ -29,6 +29,14 @@ class InterceptingResourceHandler::Controller : public ResourceController {
intercepting_handler_->ResumeInternal();
}
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ Resume();
+ }
+
void Cancel() override {
MarkAsUsed();
intercepting_handler_->Cancel();
diff --git a/chromium/content/browser/loader/layered_resource_handler.cc b/chromium/content/browser/loader/layered_resource_handler.cc
index 340025a4b70..9a163e7d18b 100644
--- a/chromium/content/browser/loader/layered_resource_handler.cc
+++ b/chromium/content/browser/loader/layered_resource_handler.cc
@@ -69,9 +69,4 @@ void LayeredResourceHandler::OnResponseCompleted(
next_handler_->OnResponseCompleted(status, std::move(controller));
}
-void LayeredResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- DCHECK(next_handler_.get());
- next_handler_->OnDataDownloaded(bytes_downloaded);
-}
-
} // namespace content
diff --git a/chromium/content/browser/loader/layered_resource_handler.h b/chromium/content/browser/loader/layered_resource_handler.h
index 47d37bca55f..2aa0e245127 100644
--- a/chromium/content/browser/loader/layered_resource_handler.h
+++ b/chromium/content/browser/loader/layered_resource_handler.h
@@ -45,7 +45,6 @@ class CONTENT_EXPORT LayeredResourceHandler : public ResourceHandler {
void OnResponseCompleted(
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- void OnDataDownloaded(int bytes_downloaded) override;
std::unique_ptr<ResourceHandler> next_handler_;
};
diff --git a/chromium/content/browser/loader/loader_browsertest.cc b/chromium/content/browser/loader/loader_browsertest.cc
index 450919d3c3b..024fadee921 100644
--- a/chromium/content/browser/loader/loader_browsertest.cc
+++ b/chromium/content/browser/loader/loader_browsertest.cc
@@ -273,17 +273,20 @@ namespace {
// Responds with a HungResponse for the specified URL to hang on the request.
// If the network service is enabled, crashes the process. If it's disabled,
// cancels all requests from specifield |child_id|.
+//
+// |crash_network_service_callback| crashes the network service when invoked,
+// and must be called on the UI thread.
std::unique_ptr<net::test_server::HttpResponse> CancelOnRequest(
const std::string& relative_url,
int child_id,
+ base::RepeatingClosure crash_network_service_callback,
const net::test_server::HttpRequest& request) {
if (request.relative_url != relative_url)
return nullptr;
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
- base::BindOnce(SimulateNetworkServiceCrash));
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ crash_network_service_callback);
} else {
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
@@ -303,7 +306,9 @@ std::unique_ptr<net::test_server::HttpResponse> CancelOnRequest(
IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, SyncXMLHttpRequest_Cancelled) {
embedded_test_server()->RegisterRequestHandler(base::Bind(
&CancelOnRequest, "/hung",
- shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(),
+ base::BindRepeating(&BrowserTestBase::SimulateNetworkServiceCrash,
+ base::Unretained(this))));
ASSERT_TRUE(embedded_test_server()->Start());
WaitForLoadStop(shell()->web_contents());
@@ -813,25 +818,6 @@ IN_PROC_BROWSER_TEST_F(PreviewsStateBrowserTest,
CheckResourcesRequested(true);
}
-// Test that reloading with Lo-Fi disabled doesn't call ShouldEnableLoFiMode and
-// already has LOFI_OFF.
-IN_PROC_BROWSER_TEST_F(PreviewsStateBrowserTest,
- ShouldEnableLoFiModeReloadDisableLoFi) {
- // Navigate with GetPreviewsState returning SERVER_LOFI_ON.
- Reset(SERVER_LOFI_ON);
- NavigateToURLBlockUntilNavigationsComplete(
- shell(), embedded_test_server()->GetURL("/page_with_iframe.html"), 1);
- CheckResourcesRequested(true);
-
- // Reload with Lo-Fi disabled.
- Reset(PREVIEWS_NO_TRANSFORM);
- TestNavigationObserver tab_observer(shell()->web_contents(), 1);
- shell()->web_contents()->GetController().Reload(ReloadType::DISABLE_PREVIEWS,
- true);
- tab_observer.Wait();
- CheckResourcesRequested(false);
-}
-
namespace {
struct RequestData {
@@ -871,6 +857,19 @@ class RequestDataBrowserTest : public ContentBrowserTest {
return copy;
}
+ void WaitForRequests(size_t count) {
+ while (true) {
+ base::RunLoop run_loop;
+ {
+ base::AutoLock auto_lock(requests_lock_);
+ if (requests_.size() == count)
+ return;
+ requests_closure_ = run_loop.QuitClosure();
+ }
+ run_loop.Run();
+ }
+ }
+
private:
void SetUpOnMainThread() override {
ContentBrowserTest::SetUpOnMainThread();
@@ -893,10 +892,13 @@ class RequestDataBrowserTest : public ContentBrowserTest {
void RequestCreated(RequestData data) {
base::AutoLock auto_lock(requests_lock_);
requests_.push_back(data);
+ if (requests_closure_)
+ requests_closure_.Run();
}
base::Lock requests_lock_;
std::vector<RequestData> requests_;
+ base::Closure requests_closure_;
std::unique_ptr<URLLoaderInterceptor> interceptor_;
};
@@ -928,6 +930,7 @@ IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, LinkRelPrefetch) {
url::Origin top_origin = url::Origin::Create(top_url);
NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+ WaitForRequests(2u);
auto requests = data();
EXPECT_EQ(2u, requests.size());
@@ -944,6 +947,7 @@ IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, LinkRelPrefetchReferrerPolicy) {
url::Origin top_origin = url::Origin::Create(top_url);
NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+ WaitForRequests(2u);
auto requests = data();
EXPECT_EQ(2u, requests.size());
diff --git a/chromium/content/browser/loader/merkle_integrity_source_stream.cc b/chromium/content/browser/loader/merkle_integrity_source_stream.cc
index 4643113b761..94c532f18e2 100644
--- a/chromium/content/browser/loader/merkle_integrity_source_stream.cc
+++ b/chromium/content/browser/loader/merkle_integrity_source_stream.cc
@@ -19,7 +19,7 @@ namespace {
// maximum record size in TLS and the default maximum frame size in HTTP/2.
constexpr uint64_t kMaxRecordSize = 16 * 1024;
-constexpr char kMiSha256Header[] = "mi-sha256=";
+constexpr char kMiSha256Header[] = "mi-sha256-draft2=";
constexpr size_t kMiSha256HeaderLength = sizeof(kMiSha256Header) - 1;
// Copies as many bytes from |input| as will fit in |output| and advances both.
diff --git a/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc b/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
index dc1d802e457..61c61692ec5 100644
--- a/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
+++ b/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
@@ -17,13 +17,13 @@ const int kBigBufferSize = 4096;
const int kSmallBufferSize = 1;
const char kMIEmptyBody[] =
- "mi-sha256=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0";
+ "mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0";
const char kMISingleRecord[] =
- "mi-sha256=dcRDgR2GM35DluAV13PzgnG6-pvQwPywfFvAu1UeFrs";
+ "mi-sha256-draft2=dcRDgR2GM35DluAV13PzgnG6-pvQwPywfFvAu1UeFrs";
const char kMIMultipleRecords[] =
- "mi-sha256=IVa9shfs0nyKEhHqtB3WVNANJ2Njm5KjQLjRtnbkYJ4";
+ "mi-sha256-draft2=IVa9shfs0nyKEhHqtB3WVNANJ2Njm5KjQLjRtnbkYJ4";
const char kMIWholeNumberOfRecords[] =
- "mi-sha256=L2vdwBplKvIr0ZPkcuskWZfEVDgVdHa6aD363UpKuZs";
+ "mi-sha256-draft2=L2vdwBplKvIr0ZPkcuskWZfEVDgVdHa6aD363UpKuZs";
enum class ReadResultType {
// Each call to AddReadResult is a separate read from the lower layer
@@ -180,7 +180,7 @@ TEST_P(MerkleIntegritySourceStreamTest, MalformedMIHeader) {
}
TEST_P(MerkleIntegritySourceStreamTest, WrongMIAttributeName) {
- Init("mi-sha255=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0");
+ Init("mi-sha256-draft1=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0");
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int result = ReadStream(&actual_output);
@@ -188,7 +188,7 @@ TEST_P(MerkleIntegritySourceStreamTest, WrongMIAttributeName) {
}
TEST_P(MerkleIntegritySourceStreamTest, HashTooShort) {
- Init("mi-sha256=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoA");
+ Init("mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoA");
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int result = ReadStream(&actual_output);
@@ -196,7 +196,7 @@ TEST_P(MerkleIntegritySourceStreamTest, HashTooShort) {
}
TEST_P(MerkleIntegritySourceStreamTest, HashTooLong) {
- Init("mi-sha256=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0A");
+ Init("mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0A");
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int result = ReadStream(&actual_output);
@@ -470,7 +470,7 @@ TEST_P(MerkleIntegritySourceStreamTest, Truncated) {
// represent the empty string. Update the code and possibly this test depending
// on how https://github.com/martinthomson/http-mice/issues/3 is resolved.
TEST_P(MerkleIntegritySourceStreamTest, EmptyFinalRecord) {
- Init("mi-sha256=JJnIuaOEc2247K9V88VQAQy1GJuQ6ylaVM7mG69QkE4");
+ Init("mi-sha256-draft2=JJnIuaOEc2247K9V88VQAQy1GJuQ6ylaVM7mG69QkE4");
const uint8_t kRecordSize[] = {0, 0, 0, 0, 0, 0, 0, 16};
const std::string kMessage(
"When I grow up, I want to be a watermelon!! \xf0\x9f\x8d\x89");
diff --git a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
index bed70acf54d..89e2c5351c4 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
@@ -24,7 +24,6 @@
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader/stream_resource_handler.h"
#include "content/browser/web_package/signed_exchange_utils.h"
-#include "content/browser/web_package/web_package_request_handler.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/resource_context.h"
@@ -75,6 +74,14 @@ class MimeSniffingResourceHandler::Controller : public ResourceController {
mime_handler_->ResumeInternal();
}
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ Resume();
+ }
+
void Cancel() override {
MarkAsUsed();
mime_handler_->Cancel();
diff --git a/chromium/content/browser/loader/mock_resource_loader.cc b/chromium/content/browser/loader/mock_resource_loader.cc
index 7444b0ad792..e43c857841a 100644
--- a/chromium/content/browser/loader/mock_resource_loader.cc
+++ b/chromium/content/browser/loader/mock_resource_loader.cc
@@ -10,6 +10,7 @@
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_handler.h"
#include "net/base/io_buffer.h"
+#include "net/http/http_request_headers.h"
#include "net/url_request/url_request_status.h"
#include "services/network/public/cpp/resource_response.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -24,6 +25,14 @@ class MockResourceLoader::TestResourceController : public ResourceController {
void Resume() override { mock_loader_->OnResume(); }
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ Resume();
+ }
+
void Cancel() override { CancelWithError(net::ERR_ABORTED); }
void CancelWithError(int error_code) override {
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.cc b/chromium/content/browser/loader/mojo_async_resource_handler.cc
index 08d0708f93c..4910201a2d1 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.cc
@@ -12,9 +12,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
-#include "content/browser/loader/downloaded_temp_file_impl.h"
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -40,24 +38,19 @@ constexpr size_t kMinAllocationSize = 2 * net::kMaxBytesToSniff;
constexpr size_t kMaxChunkSize = 32 * 1024;
-// Records histograms for the time spent between several events in the
-// MojoAsyncResourceHandler for a navigation.
-// - |response_started| is when the response's headers and metadata are
-// available. Loading is paused at this time.
-// - |proceed_with_response| is when loading is resumed.
-// - |first_read_completed| is when the first part of the body has been read.
-void RecordNavigationResourceHandlerMetrics(
- base::TimeTicks response_started,
- base::TimeTicks proceed_with_response,
- base::TimeTicks first_read_completed) {
- UMA_HISTOGRAM_TIMES(
- "Navigation.ResourceHandler."
- "ResponseStartedUntilProceedWithResponse",
- proceed_with_response - response_started);
- UMA_HISTOGRAM_TIMES(
- "Navigation.ResourceHandler."
- "ProceedWithResponseUntilFirstReadCompleted",
- first_read_completed - proceed_with_response);
+// Time between sending the transfer size updates to renderer. This threshold is
+// chosen as a compromise between sending too frequent updates and the limit its
+// consumers (DevTools and page load metrics) expect.
+constexpr base::TimeDelta kTransferSizeReportInterval =
+ base::TimeDelta::FromMilliseconds(500);
+
+bool ShouldReportTransferSize(
+ const ResourceRequestInfoImpl* resource_request_info) {
+ // Transfer size is reported only when report_raw_headers is set or the
+ // renderer is allowed to receive the resource response metadata (e.g. by
+ // Cross-Origin Read Blocking).
+ return resource_request_info->ShouldReportRawHeaders() ||
+ !resource_request_info->blocked_response_from_reaching_renderer();
}
} // namespace
@@ -124,6 +117,7 @@ MojoAsyncResourceHandler::MojoAsyncResourceHandler(
url_loader_client_(std::move(url_loader_client)),
weak_factory_(this) {
DCHECK(IsResourceTypeFrame(resource_type) ||
+ resource_type == RESOURCE_TYPE_SERVICE_WORKER ||
!(url_loader_options_ &
network::mojom::kURLLoadOptionSendSSLInfoWithResponse));
DCHECK(resource_type == RESOURCE_TYPE_MAIN_FRAME ||
@@ -178,37 +172,26 @@ void MojoAsyncResourceHandler::OnResponseStarted(
network::ResourceResponse* response,
std::unique_ptr<ResourceController> controller) {
DCHECK(!has_controller());
- time_response_started_ = base::TimeTicks::Now();
if (upload_progress_tracker_) {
upload_progress_tracker_->OnUploadCompleted();
upload_progress_tracker_ = nullptr;
}
- const ResourceRequestInfoImpl* info = GetRequestInfo();
response->head.encoded_data_length = request()->raw_header_size();
reported_total_received_bytes_ = response->head.encoded_data_length;
response->head.request_start = request()->creation_time();
- response->head.response_start = time_response_started_;
+ response->head.response_start = base::TimeTicks::Now();
sent_received_response_message_ = true;
- network::mojom::DownloadedTempFilePtr downloaded_file_ptr;
- if (!response->head.download_file_path.empty()) {
- downloaded_file_ptr = DownloadedTempFileImpl::Create(info->GetChildID(),
- info->GetRequestID());
- rdh_->RegisterDownloadedTempFile(info->GetChildID(), info->GetRequestID(),
- response->head.download_file_path);
- }
-
if ((url_loader_options_ &
network::mojom::kURLLoadOptionSendSSLInfoWithResponse) &&
request()->ssl_info().cert) {
response->head.ssl_info = request()->ssl_info();
}
- url_loader_client_->OnReceiveResponse(response->head,
- std::move(downloaded_file_ptr));
+ url_loader_client_->OnReceiveResponse(response->head);
net::IOBufferWithSize* metadata = GetResponseMetadata(request());
if (metadata) {
@@ -335,21 +318,18 @@ void MojoAsyncResourceHandler::OnReadCompleted(
return;
}
- const ResourceRequestInfoImpl* info = GetRequestInfo();
- if (info->ShouldReportRawHeaders()) {
+ if (ShouldReportTransferSize(GetRequestInfo()) &&
+ (time_transfer_size_next_report_.is_null() ||
+ time_transfer_size_next_report_ <= base::TimeTicks::Now())) {
auto transfer_size_diff = CalculateRecentlyReceivedBytes();
- if (transfer_size_diff > 0)
+ if (transfer_size_diff > 0) {
url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
+ time_transfer_size_next_report_ =
+ base::TimeTicks::Now() + kTransferSizeReportInterval;
+ }
}
if (response_body_consumer_handle_.is_valid()) {
- if (url_loader_options_ &
- network::mojom::kURLLoadOptionPauseOnResponseStarted) {
- base::TimeTicks time_first_read_completed = base::TimeTicks::Now();
- RecordNavigationResourceHandlerMetrics(time_response_started_,
- time_proceed_with_response_,
- time_first_read_completed);
- }
// Send the data pipe on the first OnReadCompleted call.
url_loader_client_->OnStartLoadingResponseBody(
std::move(response_body_consumer_handle_));
@@ -384,16 +364,10 @@ void MojoAsyncResourceHandler::OnReadCompleted(
controller->Resume();
}
-void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- url_loader_client_->OnDataDownloaded(bytes_downloaded,
- CalculateRecentlyReceivedBytes());
-}
-
void MojoAsyncResourceHandler::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
- DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
- "headers was not supported "
- "yet. crbug.com/845683";
if (!request()->status().is_success()) {
DVLOG(1) << "FollowRedirect for invalid request";
return;
@@ -408,14 +382,12 @@ void MojoAsyncResourceHandler::FollowRedirect(
DCHECK(!did_defer_on_writing_);
did_defer_on_redirect_ = false;
request()->LogUnblocked();
- Resume();
+ ResumeForRedirect(modified_request_headers);
}
void MojoAsyncResourceHandler::ProceedWithResponse() {
DCHECK(did_defer_on_response_started_);
- time_proceed_with_response_ = base::TimeTicks::Now();
-
request()->LogUnblocked();
Resume();
}
@@ -524,8 +496,8 @@ void MojoAsyncResourceHandler::OnResponseCompleted(
loader_status.encoded_data_length = request()->GetTotalReceivedBytes();
loader_status.encoded_body_length = request()->GetRawBodyBytes();
loader_status.decoded_body_length = total_written_bytes_;
- loader_status.blocked_cross_site_document =
- GetRequestInfo()->blocked_cross_site_document();
+ loader_status.should_report_corb_blocking =
+ GetRequestInfo()->should_report_corb_blocking();
if ((url_loader_options_ &
network::mojom::kURLLoadOptionSendSSLInfoForCertificateError) &&
@@ -534,6 +506,12 @@ void MojoAsyncResourceHandler::OnResponseCompleted(
loader_status.ssl_info = request()->ssl_info();
}
+ if (ShouldReportTransferSize(GetRequestInfo())) {
+ auto transfer_size_diff = CalculateRecentlyReceivedBytes();
+ if (transfer_size_diff > 0)
+ url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
+ }
+
url_loader_client_->OnComplete(loader_status);
controller->Resume();
}
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.h b/chromium/content/browser/loader/mojo_async_resource_handler.h
index c612b2f72e2..ad87065771e 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.h
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.h
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
#include "content/browser/loader/resource_handler.h"
#include "content/common/content_export.h"
#include "content/public/common/resource_type.h"
@@ -82,10 +81,11 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
void OnResponseCompleted(
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- void OnDataDownloaded(int bytes_downloaded) override;
// network::mojom::URLLoader implementation:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
@@ -149,13 +149,12 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
bool did_defer_on_writing_ = false;
bool did_defer_on_redirect_ = false;
bool did_defer_on_response_started_ = false;
+
+ // The time transfer size should be reported next.
+ base::TimeTicks time_transfer_size_next_report_;
int64_t reported_total_received_bytes_ = 0;
int64_t total_written_bytes_ = 0;
- // Used for UMA histograms.
- base::TimeTicks time_response_started_;
- base::TimeTicks time_proceed_with_response_;
-
// Pointer to parent's information about the read buffer. Only non-null while
// OnWillRead is deferred.
scoped_refptr<net::IOBuffer>* parent_buffer_ = nullptr;
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc b/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
index f6ca9da8125..a4170df9f58 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/logging.h"
@@ -49,7 +50,9 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.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 "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
@@ -304,9 +307,9 @@ class MojoAsyncResourceHandlerTestBase {
// Create and initialize |request_|. None of this matters, for these tests,
// just need something non-NULL.
- net::URLRequestContext* request_context =
+ request_context_ =
browser_context_->GetResourceContext()->GetRequestContext();
- request_ = request_context->CreateRequest(
+ request_ = request_context_->CreateRequest(
GURL("http://foo/"), net::DEFAULT_PRIORITY, &url_request_delegate_,
TRAFFIC_ANNOTATION_FOR_TESTS);
request_->set_upload(std::move(upload_stream));
@@ -403,6 +406,7 @@ class MojoAsyncResourceHandlerTestBase {
network::TestURLLoaderClient url_loader_client_;
std::unique_ptr<TestBrowserContext> browser_context_;
net::TestDelegate url_request_delegate_;
+ net::URLRequestContext* request_context_;
std::unique_ptr<net::URLRequest> request_;
std::unique_ptr<MojoAsyncResourceHandlerWithStubOperations> handler_;
std::unique_ptr<MockResourceLoader> mock_loader_;
@@ -1211,7 +1215,7 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, RedirectHandling) {
ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
mock_loader_->status());
- handler_->FollowRedirect(base::nullopt);
+ handler_->FollowRedirect(base::nullopt, base::nullopt);
ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
url_loader_client_.ClearHasReceivedRedirect();
@@ -1232,7 +1236,7 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, RedirectHandling) {
ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
mock_loader_->status());
- handler_->FollowRedirect(base::nullopt);
+ handler_->FollowRedirect(base::nullopt, base::nullopt);
ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
// Give the final response.
@@ -1256,7 +1260,7 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, RedirectHandling) {
// redirect, despite the fact that no redirect has been received yet.
TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
MalformedFollowRedirectRequest) {
- handler_->FollowRedirect(base::nullopt);
+ handler_->FollowRedirect(base::nullopt, base::nullopt);
EXPECT_TRUE(handler_->has_received_bad_message());
}
@@ -1459,6 +1463,66 @@ TEST_F(MojoAsyncResourceHandlerSendSSLInfoForCertificateError,
EXPECT_FALSE(url_loader_client_.completion_status().ssl_info);
};
+TEST_F(MojoAsyncResourceHandlerTest,
+ TransferSizeUpdateCalledForNonBlockedResponse) {
+ net::URLRequestJobFactoryImpl test_job_factory_;
+ auto test_job = std::make_unique<net::URLRequestTestJob>(
+ request_.get(), request_context_->network_delegate(), "response headers",
+ "response body", true);
+ auto test_job_interceptor = std::make_unique<net::TestJobInterceptor>();
+ net::TestJobInterceptor* raw_test_job_interceptor =
+ test_job_interceptor.get();
+ EXPECT_TRUE(test_job_factory_.SetProtocolHandler(
+ url::kHttpScheme, std::move(test_job_interceptor)));
+
+ request_context_->set_job_factory(&test_job_factory_);
+ raw_test_job_interceptor->set_main_intercept_job(std::move(test_job));
+ request_->Start();
+
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
+ url_request_delegate_.RunUntilComplete();
+
+ net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK);
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnResponseCompleted(status));
+ url_loader_client_.RunUntilComplete();
+ EXPECT_LT(0, url_loader_client_.body_transfer_size());
+ EXPECT_EQ(request_->GetTotalReceivedBytes(),
+ url_loader_client_.body_transfer_size());
+}
+
+TEST_F(MojoAsyncResourceHandlerTest,
+ TransferSizeUpdateNotCalledForBlockedResponse) {
+ net::URLRequestJobFactoryImpl test_job_factory_;
+ auto test_job = std::make_unique<net::URLRequestTestJob>(
+ request_.get(), request_context_->network_delegate(), "response headers",
+ "response body", true);
+ auto test_job_interceptor = std::make_unique<net::TestJobInterceptor>();
+ net::TestJobInterceptor* raw_test_job_interceptor =
+ test_job_interceptor.get();
+ EXPECT_TRUE(test_job_factory_.SetProtocolHandler(
+ url::kHttpScheme, std::move(test_job_interceptor)));
+
+ request_context_->set_job_factory(&test_job_factory_);
+ raw_test_job_interceptor->set_main_intercept_job(std::move(test_job));
+ request_->Start();
+
+ // Block the response to reach renderer.
+ ResourceRequestInfoImpl::ForRequest(request_.get())
+ ->set_blocked_response_from_reaching_renderer(true);
+
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
+
+ net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK);
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnResponseCompleted(status));
+ url_request_delegate_.RunUntilComplete();
+ EXPECT_TRUE(ResourceRequestInfoImpl::ForRequest(request_.get())
+ ->blocked_response_from_reaching_renderer());
+ EXPECT_EQ(0, url_loader_client_.body_transfer_size());
+ EXPECT_LT(0, request_->GetTotalReceivedBytes());
+}
+
INSTANTIATE_TEST_CASE_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
MojoAsyncResourceHandlerWithAllocationSizeTest,
::testing::Values(8, 32 * 2014));
diff --git a/chromium/content/browser/loader/navigation_loader_util.h b/chromium/content/browser/loader/navigation_loader_util.h
deleted file mode 100644
index d5741554aff..00000000000
--- a/chromium/content/browser/loader/navigation_loader_util.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2018 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_NAVIGATION_LOADER_UTIL_H_
-#define CONTENT_BROWSER_LOADER_NAVIGATION_LOADER_UTIL_H_
-
-#include "base/optional.h"
-
-#include <string>
-
-class GURL;
-namespace net {
-class HttpResponseHeaders;
-}
-
-namespace content {
-namespace navigation_loader_util {
-
-// Returns true if the given response must be downloaded because of the headers.
-bool MustDownload(const GURL& url,
- net::HttpResponseHeaders* headers,
- const std::string& mime_type);
-
-// Determines whether given response would result in a download.
-// Note this doesn't handle the case when a plugin exists for the |mime_type|.
-bool IsDownload(const GURL& url,
- net::HttpResponseHeaders* headers,
- const std::string& mime_type);
-
-} // namespace navigation_loader_util
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_NAVIGATION_LOADER_UTIL_H_
diff --git a/chromium/content/browser/loader/navigation_url_loader.h b/chromium/content/browser/loader/navigation_url_loader.h
index e0151260cfc..e2b961d6715 100644
--- a/chromium/content/browser/loader/navigation_url_loader.h
+++ b/chromium/content/browser/loader/navigation_url_loader.h
@@ -8,8 +8,13 @@
#include <memory>
#include "base/macros.h"
+#include "base/optional.h"
#include "content/common/content_export.h"
+namespace net {
+class HttpRequestHeaders;
+}
+
namespace content {
class AppCacheNavigationHandle;
@@ -51,7 +56,10 @@ class CONTENT_EXPORT NavigationURLLoader {
// Called in response to OnRequestRedirected to continue processing the
// request.
- virtual void FollowRedirect() = 0;
+ virtual void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) = 0;
// Called in response to OnResponseStarted to process the response.
virtual void ProceedWithResponse() = 0;
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
index 3dc15070498..0fb15c7c1be 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -10,6 +10,7 @@
#include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
#include "base/task_scheduler/post_task.h"
#include "base/trace_event/trace_event.h"
#include "components/download/public/common/download_stats.h"
@@ -22,7 +23,6 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
-#include "content/browser/loader/navigation_loader_util.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -34,17 +34,18 @@
#include "content/browser/url_loader_factory_getter.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_package/signed_exchange_consts.h"
+#include "content/browser/web_package/signed_exchange_request_handler.h"
#include "content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h"
#include "content/browser/web_package/signed_exchange_utils.h"
-#include "content/browser/web_package/web_package_request_handler.h"
#include "content/browser/webui/url_data_manager_backend.h"
#include "content/browser/webui/web_ui_url_loader_factory_internal.h"
#include "content/common/navigation_subresource_loader_params.h"
-#include "content/common/service_worker/service_worker_utils.h"
+#include "content/common/net/record_load_histograms.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/download_utils.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/navigation_data.h"
#include "content/public/browser/navigation_ui_data.h"
@@ -59,6 +60,7 @@
#include "content/public/common/webplugininfo.h"
#include "net/base/load_flags.h"
#include "net/http/http_content_disposition.h"
+#include "net/http/http_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_util.h"
#include "net/url_request/url_request.h"
@@ -73,6 +75,7 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
@@ -108,7 +111,7 @@ base::LazyInstance<NavigationURLLoaderImpl::BeginNavigationInterceptor>::Leaky
// of them is enabled.
bool IsLoaderInterceptionEnabled() {
return base::FeatureList::IsEnabled(network::features::kNetworkService) ||
- ServiceWorkerUtils::IsServicificationEnabled() ||
+ blink::ServiceWorkerUtils::IsServicificationEnabled() ||
signed_exchange_utils::IsSignedExchangeHandlingEnabled();
}
@@ -243,6 +246,8 @@ std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
new_request->fetch_redirect_mode = network::mojom::FetchRedirectMode::kManual;
new_request->fetch_request_context_type =
request_info->begin_params->request_context_type;
+ new_request->upgrade_if_insecure = request_info->upgrade_if_insecure;
+ new_request->throttling_profile_id = request_info->devtools_frame_token;
return new_request;
}
@@ -258,12 +263,11 @@ std::unique_ptr<NavigationRequestInfo> CreateNavigationRequestInfoForRedirect(
previous_request_info.common_params;
new_common_params.url = updated_resource_request.url;
new_common_params.referrer =
- Referrer(updated_resource_request.url,
+ Referrer(updated_resource_request.referrer,
Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
updated_resource_request.referrer_policy));
new_common_params.method = updated_resource_request.method;
new_common_params.post_data = updated_resource_request.request_body;
- // TODO(shimazu): Set correct base url and history url for a data URL.
mojom::BeginNavigationParamsPtr new_begin_params =
previous_request_info.begin_params.Clone();
@@ -279,8 +283,10 @@ std::unique_ptr<NavigationRequestInfo> CreateNavigationRequestInfoForRedirect(
previous_request_info.is_for_guests_only,
previous_request_info.report_raw_headers,
previous_request_info.is_prerendering,
+ previous_request_info.upgrade_if_insecure,
nullptr /* blob_url_loader_factory */,
- previous_request_info.devtools_navigation_token);
+ previous_request_info.devtools_navigation_token,
+ previous_request_info.devtools_frame_token);
}
// Called for requests that we don't have a URLLoaderFactory for.
@@ -308,7 +314,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
initial_interceptors,
std::unique_ptr<network::ResourceRequest> resource_request,
ResourceContext* resource_context,
- scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter,
const GURL& url,
network::mojom::URLLoaderFactoryRequest proxied_factory_request,
network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info,
@@ -317,7 +322,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
: interceptors_(std::move(initial_interceptors)),
resource_request_(std::move(resource_request)),
resource_context_(resource_context),
- default_url_loader_factory_getter_(default_url_loader_factory_getter),
url_(url),
owner_(owner),
response_loader_binding_(this),
@@ -328,6 +332,18 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
~URLLoaderRequestController() override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // If neither OnCompleted nor OnReceivedResponse has been invoked, the
+ // request was canceled before receiving a response, so log a cancellation.
+ // Results after receiving a non-error response are logged in the renderer,
+ // if the request is passed to one. If it's a download, or not passed to a
+ // renderer for some other reason, results will not be logged for the
+ // request. The net::OK check may not be necessary - the case where OK is
+ // received without receiving any headers looks broken, anyways.
+ if (!received_response_ && (!status_ || status_->error_code != net::OK)) {
+ RecordLoadHistograms(url_, resource_request_->resource_type,
+ status_ ? status_->error_code : net::ERR_ABORTED);
+ }
}
static uint32_t GetURLLoaderOptions(bool is_main_frame) {
@@ -352,15 +368,30 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
net::URLRequestContextGetter* url_request_context_getter,
storage::FileSystemContext* upload_file_system_context,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
- AppCacheNavigationHandleCore* appcache_handle_core) const {
+ AppCacheNavigationHandleCore* appcache_handle_core,
+ bool was_request_intercepted) const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ DCHECK(started_);
+
return base::BindOnce(
&URLLoaderRequestController::CreateNonNetworkServiceURLLoader,
weak_factory_.GetWeakPtr(),
base::Unretained(url_request_context_getter),
base::Unretained(upload_file_system_context),
std::make_unique<NavigationRequestInfo>(*request_info_),
- base::Unretained(service_worker_navigation_handle_core),
- base::Unretained(appcache_handle_core));
+ // If the request has already been intercepted, the request should not
+ // be intercepted again.
+ // S13nServiceWorker: Requests are intercepted by S13nServiceWorker
+ // before the default request handler when needed, so we never need to
+ // pass |service_worker_navigation_handle_core| here.
+ base::Unretained(
+ blink::ServiceWorkerUtils::IsServicificationEnabled() ||
+ was_request_intercepted
+ ? nullptr
+ : service_worker_navigation_handle_core),
+ base::Unretained(was_request_intercepted ? nullptr
+ : appcache_handle_core));
}
void CreateNonNetworkServiceURLLoader(
@@ -371,23 +402,25 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
AppCacheNavigationHandleCore* appcache_handle_core,
network::mojom::URLLoaderRequest url_loader,
network::mojom::URLLoaderClientPtr url_loader_client) {
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ DCHECK(started_);
default_loader_used_ = true;
if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
- DCHECK(!default_url_loader_factory_getter_);
+ DCHECK(!network_loader_factory_);
// It is safe to pass the callback of CreateURLLoaderThrottles with the
// unretained |this|, because the passed callback will be used by a
// SignedExchangeHandler which is indirectly owned by |this| until its
// header is verified and parsed, that's where the getter is used.
- interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
+ interceptors_.push_back(std::make_unique<SignedExchangeRequestHandler>(
url::Origin::Create(request_info->common_params.url),
request_info->common_params.url,
GetURLLoaderOptions(request_info->is_main_frame),
request_info->frame_tree_node_id,
request_info->devtools_navigation_token,
- request_info->report_raw_headers,
+ request_info->devtools_frame_token, request_info->report_raw_headers,
+ request_info->begin_params->load_flags,
base::MakeRefCounted<
SignedExchangeURLLoaderFactoryForNonNetworkService>(
resource_context_, url_request_context_getter),
@@ -415,7 +448,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
upload_file_system_context, *request_info,
std::move(navigation_ui_data_), std::move(url_loader_client),
std::move(url_loader), service_worker_navigation_handle_core,
- appcache_handle_core, options, &global_request_id_);
+ appcache_handle_core, options, global_request_id_);
}
// TODO(arthursonzogni): Detect when the ResourceDispatcherHost didn't
@@ -434,8 +467,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
AppCacheNavigationHandleCore* appcache_handle_core,
std::unique_ptr<NavigationRequestInfo> request_info,
std::unique_ptr<NavigationUIData> navigation_ui_data) {
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK(!started_);
started_ = true;
request_info_ = std::move(request_info);
@@ -443,6 +476,11 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
web_contents_getter_ = base::BindRepeating(
&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id_);
navigation_ui_data_ = std::move(navigation_ui_data);
+ // The ResourceDispatcherHostImpl can be null in unit tests.
+ ResourceDispatcherHostImpl* rph = ResourceDispatcherHostImpl::Get();
+ if (rph)
+ global_request_id_ = rph->MakeGlobalRequestID();
+
default_request_handler_factory_ = base::BindRepeating(
&URLLoaderRequestController::
CreateDefaultRequestHandlerForNonNetworkService,
@@ -453,16 +491,31 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
base::Unretained(service_worker_navigation_handle_core),
base::Unretained(appcache_handle_core));
+ // Requests to Blob scheme won't get redirected to/from other schemes
+ // or be intercepted, so we just let it go here.
+ if (request_info_->common_params.url.SchemeIsBlob() &&
+ request_info_->blob_url_loader_factory) {
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ network::SharedURLLoaderFactory::Create(
+ std::move(request_info_->blob_url_loader_factory)),
+ CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id? */,
+ network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
+ kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ return;
+ }
+
// If S13nServiceWorker is disabled, just use
// |default_request_handler_factory_| and return. The non network service
// request handling goes through ResourceDispatcherHost which has legacy
// hooks for service worker (ServiceWorkerRequestInterceptor), so no service
// worker interception is needed here.
- if (!ServiceWorkerUtils::IsServicificationEnabled() ||
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled() ||
!service_worker_navigation_handle_core) {
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- default_request_handler_factory_.Run()),
+ default_request_handler_factory_.Run(
+ false /* was_request_intercepted */)),
CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
network::mojom::kURLLoadOptionNone, resource_request_.get(),
this /* client */, kNavigationUrlLoaderTrafficAnnotation,
@@ -481,7 +534,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
if (!service_worker_interceptor) {
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- default_request_handler_factory_.Run()),
+ default_request_handler_factory_.Run(
+ false /* was_request_intercepted */)),
CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
network::mojom::kURLLoadOptionNone, resource_request_.get(),
this /* client */, kNavigationUrlLoaderTrafficAnnotation,
@@ -491,14 +545,13 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
interceptors_.push_back(std::move(service_worker_interceptor));
- // TODO(shimazu): Make sure we have a consistent global id for the
- // navigation request.
- global_request_id_ = MakeGlobalRequestID();
Restart();
}
void Start(
net::URLRequestContextGetter* url_request_context_getter,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ network_loader_factory_info,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
std::unique_ptr<NavigationRequestInfo> request_info,
@@ -506,8 +559,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
network::mojom::URLLoaderFactoryPtrInfo factory_for_webui,
int frame_tree_node_id,
std::unique_ptr<service_manager::Connector> connector) {
- DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK(!started_);
global_request_id_ = MakeGlobalRequestID();
frame_tree_node_id_ = frame_tree_node_id;
@@ -516,6 +569,10 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id);
navigation_ui_data_ = std::move(navigation_ui_data);
+ DCHECK(network_loader_factory_info);
+ network_loader_factory_ = network::SharedURLLoaderFactory::Create(
+ std::move(network_loader_factory_info));
+
if (resource_request_->request_body) {
GetBodyBlobDataHandles(resource_request_->request_body.get(),
resource_context_, &blob_handles_);
@@ -527,9 +584,9 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
std::move(factory_for_webui)),
- CreateURLLoaderThrottles(), 0 /* routing_id */, 0 /* request_id? */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
+ CreateURLLoaderThrottles(), 0 /* routing_id */,
+ global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
+ resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
return;
}
@@ -541,9 +598,9 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
network::SharedURLLoaderFactory::Create(
std::move(request_info->blob_url_loader_factory)),
- CreateURLLoaderThrottles(), 0 /* routing_id */, 0 /* request_id? */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
+ CreateURLLoaderThrottles(), 0 /* routing_id */,
+ global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
+ resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
return;
}
@@ -560,24 +617,29 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
AppCacheRequestHandler::InitializeForNavigationNetworkService(
*resource_request_, appcache_handle_core,
- default_url_loader_factory_getter_.get());
+ network_loader_factory_);
if (appcache_interceptor)
interceptors_.push_back(std::move(appcache_interceptor));
}
if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
+ // Signed Exchange is currently disabled when Network Service is enabled
+ // (https://crbug.com/849935), but still create
+ // SignedExchangeRequestHandler in order to show error message (and
+ // devtools warning) to users.
+
// It is safe to pass the callback of CreateURLLoaderThrottles with the
// unretained |this|, because the passed callback will be used by a
// SignedExchangeHandler which is indirectly owned by |this| until its
// header is verified and parsed, that's where the getter is used.
- interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
+ interceptors_.push_back(std::make_unique<SignedExchangeRequestHandler>(
url::Origin::Create(request_info->common_params.url),
request_info->common_params.url,
GetURLLoaderOptions(request_info->is_main_frame),
request_info->frame_tree_node_id,
request_info->devtools_navigation_token,
- request_info->report_raw_headers,
- default_url_loader_factory_getter_->GetNetworkFactory(),
+ request_info->devtools_frame_token, request_info->report_raw_headers,
+ request_info->begin_params->load_flags, network_loader_factory_,
base::BindRepeating(
&URLLoaderRequestController::CreateURLLoaderThrottles,
base::Unretained(this)),
@@ -624,7 +686,10 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
void MaybeStartLoader(
NavigationLoaderInterceptor* interceptor,
SingleRequestURLLoaderFactory::RequestHandler single_request_handler) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(IsLoaderInterceptionEnabled());
+ DCHECK(started_);
+
if (single_request_handler) {
// |interceptor| wants to handle the request with
// |single_request_handler|.
@@ -633,9 +698,9 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
base::MakeRefCounted<SingleRequestURLLoaderFactory>(
std::move(single_request_handler)),
- CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id? */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
+ CreateURLLoaderThrottles(), frame_tree_node_id_,
+ global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
+ resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
subresource_loader_params_ =
@@ -677,7 +742,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// so let it just follow the redirect.
if (url_loader_) {
DCHECK(!redirect_info_.new_url.is_empty());
- url_loader_->FollowRedirect();
+ url_loader_->FollowRedirect(
+ std::move(url_loader_modified_request_headers_));
return;
}
@@ -693,28 +759,36 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
DCHECK(!interceptors_.empty());
DCHECK(default_request_handler_factory_);
+ // The only way to come here is to enable ServiceWorkerServicification
+ // without NetworkService. We know that the service worker's request
+ // interceptor has already intercepted and decided not to handle the
+ // request.
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
default_loader_used_ = true;
// Update |request_info_| when following a redirect.
if (url_chain_.size() > 0) {
request_info_ = CreateNavigationRequestInfoForRedirect(
*request_info_, *resource_request_);
}
+ // When |subresource_loader_params_| has its value, the request should not
+ // be intercepted by any other interceptors since it means that a request
+ // interceptor already intercepted the request and it attached its info to
+ // the request.
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- default_request_handler_factory_.Run()),
- CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(),
- this /* client */, kNavigationUrlLoaderTrafficAnnotation,
+ default_request_handler_factory_.Run(
+ subresource_loader_params_.has_value()
+ /* was_request_intercepted */)),
+ CreateURLLoaderThrottles(), frame_tree_node_id_,
+ global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
+ resource_request_.get(), this /* client */,
+ kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
return;
}
- if (resource_request_->url.SchemeIs(url::kBlobScheme)) {
- factory =
- base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
- default_url_loader_factory_getter_->GetBlobFactory());
- } else if (!IsURLHandledByNetworkService(resource_request_->url) &&
- !resource_request_->url.SchemeIs(url::kDataScheme)) {
+ if (!IsURLHandledByNetworkService(resource_request_->url) &&
+ !resource_request_->url.SchemeIs(url::kDataScheme)) {
if (known_schemes_.find(resource_request_->url.scheme()) ==
known_schemes_.end()) {
bool handled = GetContentClient()->browser()->HandleExternalProtocol(
@@ -754,12 +828,11 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
!resource_request_->url.SchemeIs(url::kDataScheme)) {
DCHECK(proxied_factory_info_.is_valid());
// We don't worry about reconnection since it's a single navigation.
- default_url_loader_factory_getter_->CloneNetworkFactory(
- std::move(proxied_factory_request_));
+ network_loader_factory_->Clone(std::move(proxied_factory_request_));
factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
std::move(proxied_factory_info_));
} else {
- factory = default_url_loader_factory_getter_->GetNetworkFactory();
+ factory = network_loader_factory_;
}
}
url_chain_.push_back(resource_request_->url);
@@ -767,17 +840,18 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
RESOURCE_TYPE_MAIN_FRAME);
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
factory, CreateURLLoaderThrottles(), frame_tree_node_id_,
- 0 /* request_id? */, options, resource_request_.get(), this,
+ global_request_id_.request_id, options, resource_request_.get(), this,
kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
}
- void FollowRedirect() {
+ void FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!redirect_info_.new_url.is_empty());
if (!IsLoaderInterceptionEnabled()) {
- url_loader_->FollowRedirect();
+ url_loader_->FollowRedirect(modified_request_headers);
return;
}
@@ -794,7 +868,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
bool should_clear_upload = false;
net::RedirectUtil::UpdateHttpRequest(
resource_request_->url, resource_request_->method, redirect_info_,
- &resource_request_->headers, &should_clear_upload);
+ modified_request_headers, &resource_request_->headers,
+ &should_clear_upload);
if (should_clear_upload) {
// The request body is no longer applicable.
resource_request_->request_body = nullptr;
@@ -808,6 +883,10 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
resource_request_->referrer_policy = redirect_info_.new_referrer_policy;
url_chain_.push_back(redirect_info_.new_url);
+ // Need to cache modified headers for |url_loader_| since it doesn't use
+ // |resource_request_| during redirect.
+ url_loader_modified_request_headers_ = modified_request_headers;
+
Restart();
}
@@ -817,9 +896,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
private:
// network::mojom::URLLoaderClient implementation:
- void OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override {
+ void OnReceiveResponse(const network::ResourceResponseHead& head) override {
received_response_ = true;
// If the default loader (network) was used to handle the URL load request
@@ -847,15 +924,14 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
bool is_stream;
std::unique_ptr<NavigationData> cloned_navigation_data;
if (IsLoaderInterceptionEnabled()) {
- bool must_download = navigation_loader_util::MustDownload(
+ bool must_download = download_utils::MustDownload(
url_, head.headers.get(), head.mime_type);
bool known_mime_type = blink::IsSupportedMimeType(head.mime_type);
#if BUILDFLAG(ENABLE_PLUGINS)
if (!response_intercepted && !must_download && !known_mime_type) {
CheckPluginAndContinueOnReceiveResponse(
- head, std::move(downloaded_file),
- std::move(url_loader_client_endpoints),
+ head, std::move(url_loader_client_endpoints),
std::vector<WebPluginInfo>());
return;
}
@@ -900,14 +976,16 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
subresource_loader_params_ = SubresourceLoaderParams();
subresource_loader_params_->controller_service_worker_info =
mojom::ControllerServiceWorkerInfo::New();
- base::WeakPtr<ServiceWorkerHandle> sw_handle =
- sw_provider_host->GetOrCreateServiceWorkerHandle(
+ subresource_loader_params_->controller_service_worker_info->mode =
+ sw_provider_host->GetControllerMode();
+ base::WeakPtr<ServiceWorkerObjectHost> sw_object_host =
+ sw_provider_host->GetOrCreateServiceWorkerObjectHost(
sw_provider_host->controller());
- if (sw_handle) {
- subresource_loader_params_->controller_service_worker_handle =
- sw_handle;
+ if (sw_object_host) {
+ subresource_loader_params_->controller_service_worker_object_host =
+ sw_object_host;
subresource_loader_params_->controller_service_worker_info
- ->object_info = sw_handle->CreateIncompleteObjectInfo();
+ ->object_info = sw_object_host->CreateIncompleteObjectInfo();
}
}
} else {
@@ -915,8 +993,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
}
}
- CallOnReceivedResponse(head, std::move(downloaded_file),
- std::move(url_loader_client_endpoints),
+ CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
std::move(cloned_navigation_data), is_download,
is_stream);
}
@@ -924,7 +1001,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
#if BUILDFLAG(ENABLE_PLUGINS)
void CheckPluginAndContinueOnReceiveResponse(
const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
const std::vector<WebPluginInfo>& plugins) {
bool stale;
@@ -943,7 +1019,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// Refresh the plugins asynchronously.
PluginService::GetInstance()->GetPlugins(base::BindOnce(
&URLLoaderRequestController::CheckPluginAndContinueOnReceiveResponse,
- weak_factory_.GetWeakPtr(), head, std::move(downloaded_file),
+ weak_factory_.GetWeakPtr(), head,
std::move(url_loader_client_endpoints)));
return;
}
@@ -952,15 +1028,13 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
!has_plugin &&
(!head.headers || head.headers->response_code() / 100 == 2);
- CallOnReceivedResponse(head, std::move(downloaded_file),
- std::move(url_loader_client_endpoints), nullptr,
- is_download, false /* is_stream */);
+ CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
+ nullptr, is_download, false /* is_stream */);
}
#endif
void CallOnReceivedResponse(
const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
std::unique_ptr<NavigationData> cloned_navigation_data,
bool is_download,
@@ -981,7 +1055,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
response->DeepCopy(),
std::move(url_loader_client_endpoints),
std::move(cloned_navigation_data), global_request_id_,
- is_download, is_stream, std::move(downloaded_file)));
+ is_download, is_stream));
}
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
@@ -1013,7 +1087,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
redirect_info, response->DeepCopy()));
}
- void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {}
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override {}
@@ -1117,10 +1190,14 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
ResourceContext* resource_context_;
base::Callback<WebContents*()> web_contents_getter_;
std::unique_ptr<NavigationUIData> navigation_ui_data_;
- scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_;
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
std::unique_ptr<ThrottlingURLLoader> url_loader_;
+ // Caches the modified request headers provided by clients during redirect,
+ // will be consumed by next |url_loader_->FollowRedirect()|.
+ base::Optional<net::HttpRequestHeaders> url_loader_modified_request_headers_;
+
BlobHandles blob_handles_;
std::vector<GURL> url_chain_;
@@ -1162,7 +1239,11 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// captures all of parameters to create a
// SingleRequestURLLoaderFactory::RequestHandler. Used only when
// NetworkService is disabled but IsLoaderInterceptionEnabled() is true.
- base::RepeatingCallback<SingleRequestURLLoaderFactory::RequestHandler()>
+ // Set |was_request_intercepted| to true if the request was intercepted by an
+ // interceptor and the request is falling back to the network. In that case,
+ // any interceptors won't intercept the request.
+ base::RepeatingCallback<SingleRequestURLLoaderFactory::RequestHandler(
+ bool /* was_request_intercepted */)>
default_request_handler_factory_;
// The completion status if it has been received. This is needed to handle
@@ -1223,6 +1304,7 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
std::unique_ptr<network::ResourceRequest> new_request = CreateResourceRequest(
request_info.get(), frame_tree_node_id, allow_download_);
+ new_request->transition_type = request_info->common_params.transition;
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
DCHECK(!request_controller_);
@@ -1230,7 +1312,6 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
/* initial_interceptors = */
std::vector<std::unique_ptr<NavigationLoaderInterceptor>>(),
std::move(new_request), resource_context,
- /* default_url_factory_getter = */ nullptr,
request_info->common_params.url,
/* proxied_url_loader_factory_request */ nullptr,
/* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
@@ -1255,7 +1336,7 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
network::mojom::URLLoaderFactoryPtrInfo factory_for_webui;
const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
std::string scheme = new_request->url.scheme();
- if (std::find(schemes.begin(), schemes.end(), scheme) != schemes.end()) {
+ if (base::ContainsValue(schemes, scheme)) {
factory_for_webui = CreateWebUIURLLoaderBinding(
frame_tree_node->current_frame_host(), scheme)
.PassInterface();
@@ -1278,8 +1359,8 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
network::mojom::URLLoaderFactoryPtrInfo factory_info;
auto factory_request = mojo::MakeRequest(&factory_info);
bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
- frame_tree_node->current_frame_host(), true /* is_navigation */,
- &factory_request);
+ partition->browser_context(), frame_tree_node->current_frame_host(),
+ true /* is_navigation */, &factory_request);
if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
frame_tree_node->current_frame_host(), true, false,
&factory_request)) {
@@ -1311,15 +1392,16 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
DCHECK(!request_controller_);
request_controller_ = std::make_unique<URLLoaderRequestController>(
std::move(initial_interceptors), std::move(new_request), resource_context,
- partition->url_loader_factory_getter(), request_info->common_params.url,
- std::move(proxied_factory_request), std::move(proxied_factory_info),
- std::move(known_schemes), weak_factory_.GetWeakPtr());
+ request_info->common_params.url, std::move(proxied_factory_request),
+ std::move(proxied_factory_info), std::move(known_schemes),
+ weak_factory_.GetWeakPtr());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&URLLoaderRequestController::Start,
base::Unretained(request_controller_.get()),
base::RetainedRef(storage_partition->GetURLRequestContext()),
+ partition->url_loader_factory_getter()->GetNetworkFactoryInfo(),
service_worker_navigation_handle_core, appcache_handle_core,
std::move(request_info), std::move(navigation_ui_data),
std::move(factory_for_webui), frame_tree_node_id,
@@ -1331,11 +1413,15 @@ NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
request_controller_.release());
}
-void NavigationURLLoaderImpl::FollowRedirect() {
+void NavigationURLLoaderImpl::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&URLLoaderRequestController::FollowRedirect,
- base::Unretained(request_controller_.get())));
+ base::Unretained(request_controller_.get()),
+ modified_request_headers));
}
void NavigationURLLoaderImpl::ProceedWithResponse() {}
@@ -1346,8 +1432,7 @@ void NavigationURLLoaderImpl::OnReceiveResponse(
std::unique_ptr<NavigationData> navigation_data,
const GlobalRequestID& global_request_id,
bool is_download,
- bool is_stream,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
+ bool is_stream) {
TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
"&NavigationURLLoaderImpl", this, "success", true);
@@ -1403,9 +1488,10 @@ void NavigationURLLoaderImpl::BindNonNetworkURLLoaderFactoryRequest(
}
FrameTreeNode* frame_tree_node =
FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+ auto* frame = frame_tree_node->current_frame_host();
GetContentClient()->browser()->WillCreateURLLoaderFactory(
- frame_tree_node->current_frame_host(), true /* is_navigation */,
- &factory);
+ frame->GetSiteInstance()->GetBrowserContext(), frame,
+ true /* is_navigation */, &factory);
it->second->Clone(std::move(factory));
}
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.h b/chromium/content/browser/loader/navigation_url_loader_impl.h
index 67c1d5bb8f7..ac5e384a04d 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.h
@@ -44,7 +44,10 @@ class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
~NavigationURLLoaderImpl() override;
// NavigationURLLoader implementation:
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void OnReceiveResponse(
@@ -53,8 +56,7 @@ class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
std::unique_ptr<NavigationData> navigation_data,
const GlobalRequestID& global_request_id,
bool is_download,
- bool is_stream,
- network::mojom::DownloadedTempFilePtr downloaded_file);
+ bool is_stream);
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
scoped_refptr<network::ResourceResponse> response);
void OnComplete(const network::URLLoaderCompletionStatus& status);
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
index 4cafe900bb2..538274d42a9 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -104,7 +104,7 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
}
private:
- void DeleteURLLoader(network::URLLoader* url_loader) {
+ void DeleteURLLoader(network::mojom::URLLoader* url_loader) {
DCHECK_EQ(url_loader_.get(), url_loader);
url_loader_.reset();
}
@@ -154,7 +154,8 @@ class NavigationURLLoaderImplTest : public testing::Test {
const std::string& method,
NavigationURLLoaderDelegate* delegate,
bool allow_download = false,
- bool is_main_frame = true) {
+ bool is_main_frame = true,
+ bool upgrade_if_insecure = false) {
mojom::BeginNavigationParamsPtr begin_params =
mojom::BeginNavigationParams::New(
headers, net::LOAD_NORMAL, false /* skip_service_worker */,
@@ -176,8 +177,10 @@ class NavigationURLLoaderImplTest : public testing::Test {
false /* parent_is_main_frame */, false /* are_ancestors_secure */,
-1 /* frame_tree_node_id */, false /* is_for_guests_only */,
false /* report_raw_headers */, false /* is_prerenering */,
+ upgrade_if_insecure /* upgrade_if_insecure */,
nullptr /* blob_url_loader_factory */,
- base::UnguessableToken::Create() /* devtools_navigation_token */));
+ base::UnguessableToken::Create() /* devtools_navigation_token */,
+ base::UnguessableToken::Create() /* devtools_frame_token */));
std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors;
most_recent_resource_request_ = base::nullopt;
interceptors.push_back(std::make_unique<TestNavigationLoaderInterceptor>(
@@ -210,7 +213,7 @@ class NavigationURLLoaderImplTest : public testing::Test {
redirect_url.GetOrigin().spec().c_str()),
request_method, &delegate);
delegate.WaitForRequestRedirected();
- loader->FollowRedirect();
+ loader->FollowRedirect(base::nullopt, base::nullopt);
EXPECT_EQ(expected_redirect_method, delegate.redirect_info().new_method);
@@ -251,12 +254,32 @@ class NavigationURLLoaderImplTest : public testing::Test {
url.GetOrigin().spec().c_str()),
"GET", &delegate, false /* allow_download */, is_main_frame);
delegate.WaitForRequestRedirected();
- loader->FollowRedirect();
+ loader->FollowRedirect(base::nullopt, base::nullopt);
delegate.WaitForResponseStarted();
return most_recent_resource_request_.value().priority;
}
+ net::RedirectInfo NavigateAndReturnRedirectInfo(const GURL& url,
+ bool upgrade_if_insecure,
+ bool expect_request_fail) {
+ TestNavigationURLLoaderDelegate delegate;
+ std::unique_ptr<NavigationURLLoader> loader = CreateTestLoader(
+ url,
+ base::StringPrintf("%s: %s", net::HttpRequestHeaders::kOrigin,
+ url.GetOrigin().spec().c_str()),
+ "GET", &delegate, false /* allow_download */, true /*is_main_frame*/,
+ upgrade_if_insecure);
+ delegate.WaitForRequestRedirected();
+ loader->FollowRedirect(base::nullopt, base::nullopt);
+ if (expect_request_fail) {
+ delegate.WaitForRequestFailed();
+ } else {
+ delegate.WaitForResponseStarted();
+ }
+ return delegate.redirect_info();
+ }
+
protected:
base::test::ScopedFeatureList feature_list_;
TestBrowserThreadBundle thread_bundle_;
@@ -345,4 +368,68 @@ TEST_F(NavigationURLLoaderImplTest, Redirect308Tests) {
true);
}
+TEST_F(NavigationURLLoaderImplTest, RedirectModifiedHeaders) {
+ ASSERT_TRUE(http_test_server_.Start());
+
+ const GURL redirect_url = http_test_server_.GetURL("/redirect301-to-echo");
+
+ TestNavigationURLLoaderDelegate delegate;
+ std::unique_ptr<NavigationURLLoader> loader = CreateTestLoader(
+ redirect_url, "Header1: Value1\r\nHeader2: Value2", "GET", &delegate);
+ delegate.WaitForRequestRedirected();
+
+ ASSERT_TRUE(most_recent_resource_request_);
+
+ // Initial request should only have initial headers.
+ std::string header1, header2;
+ EXPECT_TRUE(
+ most_recent_resource_request_->headers.GetHeader("Header1", &header1));
+ EXPECT_EQ("Value1", header1);
+ EXPECT_TRUE(
+ most_recent_resource_request_->headers.GetHeader("Header2", &header2));
+ EXPECT_EQ("Value2", header2);
+ EXPECT_FALSE(most_recent_resource_request_->headers.HasHeader("Header3"));
+
+ // Overwrite Header2 and add Header3.
+ net::HttpRequestHeaders redirect_headers;
+ redirect_headers.SetHeader("Header2", "");
+ redirect_headers.SetHeader("Header3", "Value3");
+ loader->FollowRedirect(base::nullopt, redirect_headers);
+ delegate.WaitForResponseStarted();
+
+ // Redirected request should also have modified headers.
+ EXPECT_TRUE(
+ most_recent_resource_request_->headers.GetHeader("Header1", &header1));
+ EXPECT_EQ("Value1", header1);
+ EXPECT_TRUE(
+ most_recent_resource_request_->headers.GetHeader("Header2", &header2));
+ EXPECT_EQ("", header2);
+ std::string header3;
+ EXPECT_TRUE(
+ most_recent_resource_request_->headers.GetHeader("Header3", &header3));
+ EXPECT_EQ("Value3", header3);
+}
+
+// Tests that the Upgrade If Insecure flag is obeyed.
+TEST_F(NavigationURLLoaderImplTest, UpgradeIfInsecureTest) {
+ ASSERT_TRUE(http_test_server_.Start());
+ const GURL url = http_test_server_.GetURL("/redirect301-to-http");
+ GURL expected_url = GURL("http://test.test/test");
+ // We expect the request to fail since there is no server listening at
+ // test.test, but for the purpose of this test we only need to validate the
+ // redirect URL was not changed.
+ net::RedirectInfo redirect_info = NavigateAndReturnRedirectInfo(
+ url, false /* upgrade_if_insecure */, true /* expect_request_fail */);
+ EXPECT_FALSE(redirect_info.insecure_scheme_was_upgraded);
+ EXPECT_EQ(expected_url, redirect_info.new_url);
+ GURL::Replacements replacements;
+ replacements.SetSchemeStr("https");
+ expected_url = expected_url.ReplaceComponents(replacements);
+ redirect_info = NavigateAndReturnRedirectInfo(
+ url, true /* upgrade_if_insecure */, true /* expect_request_fail */);
+ // Same as above, but validating the URL is upgraded to https.
+ EXPECT_TRUE(redirect_info.insecure_scheme_was_upgraded);
+ EXPECT_EQ(expected_url, redirect_info.new_url);
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
index ea806d87222..75f70ba50a4 100644
--- a/chromium/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
@@ -95,7 +95,9 @@ class NavigationURLLoaderTest : public testing::Test {
std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo(common_params, std::move(begin_params), url,
true, false, false, -1, false, false, false,
- nullptr, base::UnguessableToken::Create()));
+ false, nullptr,
+ base::UnguessableToken::Create(),
+ base::UnguessableToken::Create()));
return NavigationURLLoader::Create(
browser_context_->GetResourceContext(),
BrowserContext::GetDefaultStoragePartition(browser_context_.get()),
@@ -226,7 +228,7 @@ TEST_F(NavigationURLLoaderTest, CancelResponseRace) {
// In the same event loop iteration, follow the redirect (allowing the
// response to go through) and destroy the loader.
- loader->FollowRedirect();
+ loader->FollowRedirect(base::nullopt, base::nullopt);
loader.reset();
// Verify the URLRequestTestJob no longer has anything paused and that no
diff --git a/chromium/content/browser/loader/null_resource_controller.cc b/chromium/content/browser/loader/null_resource_controller.cc
index da79bb5843e..8ac719d3a6a 100644
--- a/chromium/content/browser/loader/null_resource_controller.cc
+++ b/chromium/content/browser/loader/null_resource_controller.cc
@@ -5,6 +5,7 @@
#include "content/browser/loader/null_resource_controller.h"
#include "base/logging.h"
+#include "net/http/http_request_headers.h"
namespace content {
@@ -27,4 +28,12 @@ void NullResourceController::Resume() {
*was_resumed_ = true;
}
+void NullResourceController::ResumeForRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
+ DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
+ "headers was not supported "
+ "yet. crbug.com/845683";
+ Resume();
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/null_resource_controller.h b/chromium/content/browser/loader/null_resource_controller.h
index 8dd10f7102a..66c9e039467 100644
--- a/chromium/content/browser/loader/null_resource_controller.h
+++ b/chromium/content/browser/loader/null_resource_controller.h
@@ -23,6 +23,8 @@ class NullResourceController : public ResourceController {
void Cancel() override;
void CancelWithError(int error_code) override;
void Resume() override;
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
private:
bool* was_resumed_;
diff --git a/chromium/content/browser/loader/prefetch_browsertest.cc b/chromium/content/browser/loader/prefetch_browsertest.cc
index da0ea6f9f64..fb0726ef37c 100644
--- a/chromium/content/browser/loader/prefetch_browsertest.cc
+++ b/chromium/content/browser/loader/prefetch_browsertest.cc
@@ -14,7 +14,7 @@
#include "content/browser/loader/prefetch_url_loader_service.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_package/mock_signed_exchange_handler.h"
-#include "content/browser/web_package/web_package_loader.h"
+#include "content/browser/web_package/signed_exchange_loader.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
@@ -40,10 +40,10 @@ struct PrefetchBrowserTestParam {
struct ScopedSignedExchangeHandlerFactory {
explicit ScopedSignedExchangeHandlerFactory(
SignedExchangeHandlerFactory* factory) {
- WebPackageLoader::SetSignedExchangeHandlerFactoryForTest(factory);
+ SignedExchangeLoader::SetSignedExchangeHandlerFactoryForTest(factory);
}
~ScopedSignedExchangeHandlerFactory() {
- WebPackageLoader::SetSignedExchangeHandlerFactoryForTest(nullptr);
+ SignedExchangeLoader::SetSignedExchangeHandlerFactoryForTest(nullptr);
}
};
@@ -333,31 +333,31 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
int target_fetch_count = 0;
int preload_fetch_count = 0;
const char* prefetch_url = "/prefetch.html";
- const char* target_htxg = "/target.htxg";
+ const char* target_sxg = "/target.sxg";
const char* target_url = "/target.html";
- const char* preload_url_in_htxg = "/preload.js";
+ const char* preload_url_in_sxg = "/preload.js";
RegisterResponse(
prefetch_url,
ResponseEntry(base::StringPrintf(
- "<body><link rel='prefetch' href='%s'></body>", target_htxg)));
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg)));
RegisterResponse(
- target_htxg,
+ target_sxg,
// We mock the SignedExchangeHandler, so just return a HTML content
// as "application/signed-exchange;v=b0".
- ResponseEntry("<head><title>Prefetch Target (HTXG)</title></head>",
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title></head>",
"application/signed-exchange;v=b0"));
- RegisterResponse(preload_url_in_htxg,
+ RegisterResponse(preload_url_in_sxg,
ResponseEntry("function foo() {}", "text/javascript"));
base::RunLoop preload_waiter;
base::RunLoop prefetch_waiter;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- target_htxg, &target_fetch_count, prefetch_waiter.QuitClosure()));
+ target_sxg, &target_fetch_count, prefetch_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- preload_url_in_htxg, &preload_fetch_count, preload_waiter.QuitClosure()));
+ preload_url_in_sxg, &preload_fetch_count, preload_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -367,7 +367,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
net::OK, GURL(target_url), "text/html",
{base::StringPrintf(
"Link: <%s>;rel=\"preload\";as=\"script\"",
- embedded_test_server()->GetURL(preload_url_in_htxg).spec().c_str())});
+ embedded_test_server()->GetURL(preload_url_in_sxg).spec().c_str())});
ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
// Loading a page that prefetches the target URL would increment both
@@ -377,11 +377,15 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
EXPECT_EQ(1, target_fetch_count);
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(1));
- // Test after this point requires SignedHTTPExchange support.
- if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
+ // Test after this point requires SignedHTTPExchange support, which is now
+ // disabled when Network Service is enabled.
+ // TODO(https://crbug.com/849935): Remove the second condition once we
+ // re-enable Signed Exchange with Network Service.
+ if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchange) ||
+ base::FeatureList::IsEnabled(network::features::kNetworkService))
return;
- // If the header in the .htxg file is correctly extracted, we should
+ // If the header in the .sxg file is correctly extracted, we should
// be able to also see the preload.
preload_waiter.Run();
EXPECT_EQ(1, preload_fetch_count);
diff --git a/chromium/content/browser/loader/prefetch_url_loader.cc b/chromium/content/browser/loader/prefetch_url_loader.cc
index c0d59319dd0..bbfd85fcc3c 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader.cc
@@ -5,8 +5,8 @@
#include "content/browser/loader/prefetch_url_loader.h"
#include "base/feature_list.h"
+#include "content/browser/web_package/signed_exchange_prefetch_handler.h"
#include "content/browser/web_package/signed_exchange_utils.h"
-#include "content/browser/web_package/web_package_prefetch_handler.h"
#include "content/public/common/content_features.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/features.h"
@@ -29,6 +29,8 @@ PrefetchURLLoader::PrefetchURLLoader(
: frame_tree_node_id_getter_(frame_tree_node_id_getter),
url_(resource_request.url),
report_raw_headers_(resource_request.report_raw_headers),
+ load_flags_(resource_request.load_flags),
+ throttling_profile_id_(resource_request.throttling_profile_id),
network_loader_factory_(std::move(network_loader_factory)),
client_binding_(this),
forwarding_client_(std::move(client)),
@@ -52,18 +54,20 @@ PrefetchURLLoader::PrefetchURLLoader(
PrefetchURLLoader::~PrefetchURLLoader() = default;
void PrefetchURLLoader::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
"headers was not supported "
"yet. crbug.com/845683";
- if (web_package_prefetch_handler_) {
+ if (signed_exchange_prefetch_handler_) {
// Rebind |client_binding_| and |loader_|.
- client_binding_.Bind(web_package_prefetch_handler_->FollowRedirect(
+ client_binding_.Bind(signed_exchange_prefetch_handler_->FollowRedirect(
mojo::MakeRequest(&loader_)));
return;
}
- loader_->FollowRedirect(base::nullopt);
+ loader_->FollowRedirect(base::nullopt, base::nullopt);
}
void PrefetchURLLoader::ProceedWithResponse() {
@@ -84,21 +88,22 @@ void PrefetchURLLoader::ResumeReadingBodyFromNet() {
}
void PrefetchURLLoader::OnReceiveResponse(
- const network::ResourceResponseHead& response,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
+ const network::ResourceResponseHead& response) {
if (signed_exchange_utils::ShouldHandleAsSignedHTTPExchange(url_, response)) {
- DCHECK(!web_package_prefetch_handler_);
+ DCHECK(!signed_exchange_prefetch_handler_);
// Note that after this point this doesn't directly get upcalls from the
// network. (Until |this| calls the handler's FollowRedirect.)
- web_package_prefetch_handler_ = std::make_unique<WebPackagePrefetchHandler>(
- frame_tree_node_id_getter_, report_raw_headers_, response,
- std::move(loader_), client_binding_.Unbind(), network_loader_factory_,
- request_initiator_, url_, url_loader_throttles_getter_,
- resource_context_, request_context_getter_, this);
+ signed_exchange_prefetch_handler_ =
+ std::make_unique<SignedExchangePrefetchHandler>(
+ frame_tree_node_id_getter_, report_raw_headers_, load_flags_,
+ throttling_profile_id_, response, std::move(loader_),
+ client_binding_.Unbind(), network_loader_factory_,
+ request_initiator_, url_, url_loader_throttles_getter_,
+ resource_context_, request_context_getter_, this);
return;
}
- forwarding_client_->OnReceiveResponse(response, std::move(downloaded_file));
+ forwarding_client_->OnReceiveResponse(response);
}
void PrefetchURLLoader::OnReceiveRedirect(
@@ -107,11 +112,6 @@ void PrefetchURLLoader::OnReceiveRedirect(
forwarding_client_->OnReceiveRedirect(redirect_info, head);
}
-void PrefetchURLLoader::OnDataDownloaded(int64_t data_length,
- int64_t encoded_length) {
- forwarding_client_->OnDataDownloaded(data_length, encoded_length);
-}
-
void PrefetchURLLoader::OnUploadProgress(int64_t current_position,
int64_t total_size,
base::OnceCallback<void()> callback) {
diff --git a/chromium/content/browser/loader/prefetch_url_loader.h b/chromium/content/browser/loader/prefetch_url_loader.h
index 3a63bb0c4cc..ef4ff33677d 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.h
+++ b/chromium/content/browser/loader/prefetch_url_loader.h
@@ -9,6 +9,8 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/optional.h"
+#include "base/unguessable_token.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
@@ -28,7 +30,7 @@ namespace content {
class ResourceContext;
class URLLoaderThrottle;
-class WebPackagePrefetchHandler;
+class SignedExchangePrefetchHandler;
// PrefetchURLLoader which basically just keeps draining the data.
class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
@@ -60,7 +62,9 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
private:
// network::mojom::URLLoader overrides:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
@@ -69,12 +73,9 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
void ResumeReadingBodyFromNet() override;
// network::mojom::URLLoaderClient overrides:
- void OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override;
+ void OnReceiveResponse(const network::ResourceResponseHead& head) override;
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) override;
- void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
base::OnceCallback<void()> callback) override;
@@ -94,6 +95,8 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
const base::RepeatingCallback<int(void)> frame_tree_node_id_getter_;
const GURL url_;
const bool report_raw_headers_;
+ const int load_flags_;
+ const base::Optional<base::UnguessableToken> throttling_profile_id_;
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
@@ -114,7 +117,8 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
std::unique_ptr<mojo::DataPipeDrainer> pipe_drainer_;
- std::unique_ptr<WebPackagePrefetchHandler> web_package_prefetch_handler_;
+ std::unique_ptr<SignedExchangePrefetchHandler>
+ signed_exchange_prefetch_handler_;
DISALLOW_COPY_AND_ASSIGN(PrefetchURLLoader);
};
diff --git a/chromium/content/browser/loader/prefetch_url_loader_service.cc b/chromium/content/browser/loader/prefetch_url_loader_service.cc
index a8c1638bf9e..b7baa69c5cf 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.cc
@@ -20,9 +20,22 @@
namespace content {
-PrefetchURLLoaderService::PrefetchURLLoaderService(
- scoped_refptr<URLLoaderFactoryGetter> factory_getter)
- : loader_factory_getter_(std::move(factory_getter)) {}
+struct PrefetchURLLoaderService::BindContext {
+ BindContext(int frame_tree_node_id,
+ scoped_refptr<URLLoaderFactoryBundle> factory)
+ : frame_tree_node_id(frame_tree_node_id), factory(factory) {}
+
+ explicit BindContext(const std::unique_ptr<BindContext>& other)
+ : frame_tree_node_id(other->frame_tree_node_id),
+ factory(other->factory) {}
+
+ ~BindContext() = default;
+
+ const int frame_tree_node_id;
+ scoped_refptr<URLLoaderFactoryBundle> factory;
+};
+
+PrefetchURLLoaderService::PrefetchURLLoaderService() = default;
void PrefetchURLLoaderService::InitializeResourceContext(
ResourceContext* resource_context,
@@ -34,17 +47,16 @@ void PrefetchURLLoaderService::InitializeResourceContext(
request_context_getter_ = request_context_getter;
}
-void PrefetchURLLoaderService::ConnectToService(
+void PrefetchURLLoaderService::GetFactory(
+ network::mojom::URLLoaderFactoryRequest request,
int frame_tree_node_id,
- blink::mojom::PrefetchURLLoaderServiceRequest request) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PrefetchURLLoaderService::ConnectToService, this,
- frame_tree_node_id, std::move(request)));
- return;
- }
- service_bindings_.AddBinding(this, std::move(request), frame_tree_node_id);
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factories) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ auto factory_bundle =
+ base::MakeRefCounted<URLLoaderFactoryBundle>(std::move(factories));
+ loader_factory_bindings_.AddBinding(
+ this, std::move(request),
+ std::make_unique<BindContext>(frame_tree_node_id, factory_bundle));
}
void PrefetchURLLoaderService::CreateLoaderAndStart(
@@ -82,13 +94,6 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
PrefetchURLLoaderService::~PrefetchURLLoaderService() = default;
-void PrefetchURLLoaderService::GetFactory(
- network::mojom::URLLoaderFactoryRequest request) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- loader_factory_bindings_.AddBinding(this, std::move(request),
- service_bindings_.dispatch_context());
-}
-
void PrefetchURLLoaderService::CreateLoaderAndStart(
network::mojom::URLLoaderRequest request,
int32_t routing_id,
@@ -99,11 +104,11 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
- int frame_tree_node_id = loader_factory_bindings_.dispatch_context();
+ const auto& dispatch_context = *loader_factory_bindings_.dispatch_context();
+ int frame_tree_node_id = dispatch_context.frame_tree_node_id;
CreateLoaderAndStart(
std::move(request), routing_id, request_id, options, resource_request,
- std::move(client), traffic_annotation,
- loader_factory_getter_->GetNetworkFactory(),
+ std::move(client), traffic_annotation, dispatch_context.factory,
base::BindRepeating([](int id) { return id; }, frame_tree_node_id));
}
@@ -111,7 +116,9 @@ void PrefetchURLLoaderService::Clone(
network::mojom::URLLoaderFactoryRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
loader_factory_bindings_.AddBinding(
- this, std::move(request), loader_factory_bindings_.dispatch_context());
+ this, std::move(request),
+ std::make_unique<BindContext>(
+ loader_factory_bindings_.dispatch_context()));
}
std::vector<std::unique_ptr<content::URLLoaderThrottle>>
diff --git a/chromium/content/browser/loader/prefetch_url_loader_service.h b/chromium/content/browser/loader/prefetch_url_loader_service.h
index 6573ee69d52..69c241394f2 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.h
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.h
@@ -9,10 +9,10 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+#include "content/common/url_loader_factory_bundle.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/strong_binding_set.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "third_party/blink/public/mojom/loader/prefetch_url_loader_service.mojom.h"
namespace net {
class URLRequestContextGetter;
@@ -20,6 +20,7 @@ class URLRequestContextGetter;
namespace network {
class SharedURLLoaderFactory;
+class URLLoaderFactoryBundleInfo;
}
namespace content {
@@ -31,13 +32,9 @@ class URLLoaderThrottle;
class CONTENT_EXPORT PrefetchURLLoaderService final
: public base::RefCountedThreadSafe<PrefetchURLLoaderService,
BrowserThread::DeleteOnIOThread>,
- public network::mojom::URLLoaderFactory,
- public blink::mojom::PrefetchURLLoaderService {
+ public network::mojom::URLLoaderFactory {
public:
- // |factory_getter| could be null in non-NetworkService case.
- // Created on the UI thread.
- PrefetchURLLoaderService(
- scoped_refptr<URLLoaderFactoryGetter> network_loader_factory);
+ PrefetchURLLoaderService();
// Must be called on the IO thread. The given |resource_context| will
// be valid as far as request_context_getter returns non-null context.
@@ -45,8 +42,9 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
ResourceContext* resource_context,
scoped_refptr<net::URLRequestContextGetter> request_context_getter);
- void ConnectToService(int frame_tree_node_id,
- blink::mojom::PrefetchURLLoaderServiceRequest request);
+ void GetFactory(network::mojom::URLLoaderFactoryRequest request,
+ int frame_tree_node_id,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_info);
// Used only when NetworkService is not enabled (or indirectly via the
// other CreateLoaderAndStart when NetworkService is enabled).
@@ -75,10 +73,9 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
private:
friend class base::DeleteHelper<content::PrefetchURLLoaderService>;
friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
- ~PrefetchURLLoaderService() override;
+ struct BindContext;
- // blink::mojom::PrefetchURLLoaderService:
- void GetFactory(network::mojom::URLLoaderFactoryRequest request) override;
+ ~PrefetchURLLoaderService() override;
// network::mojom::URLLoaderFactory:
void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
@@ -97,16 +94,12 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
const network::ResourceRequest& request,
base::RepeatingCallback<int(void)> frame_tree_node_id_getter);
- mojo::BindingSet<blink::mojom::PrefetchURLLoaderService,
- int /* frame_tree_node_id */>
- service_bindings_;
-
scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
ResourceContext* resource_context_ = nullptr;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
mojo::BindingSet<network::mojom::URLLoaderFactory,
- int /* frame_tree_node_id */>
+ std::unique_ptr<BindContext>>
loader_factory_bindings_;
base::RepeatingClosure prefetch_load_callback_for_testing_;
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
deleted file mode 100644
index a6ce3d0b48f..00000000000
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
+++ /dev/null
@@ -1,376 +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/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_controller.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/browser/loader/temporary_file_stream.h"
-#include "net/base/file_stream.h"
-#include "net/base/io_buffer.h"
-#include "net/base/mime_sniffer.h"
-#include "net/base/net_errors.h"
-#include "services/network/public/cpp/resource_response.h"
-#include "storage/browser/blob/shareable_file_reference.h"
-
-using storage::ShareableFileReference;
-
-namespace {
-
-// This class is similar to identically named classes in AsyncResourceHandler
-// and MimeTypeResourceHandler, but not quite.
-// TODO(ncbray): generalize and unify these cases?
-// In general, it's a bad idea to point to a subbuffer (particularly with
-// GrowableIOBuffer) because the backing IOBuffer may realloc its data. In this
-// particular case we know RedirectToFileResourceHandler will not realloc its
-// buffer while a write is occurring, so we should be safe. This property is
-// somewhat fragile, however, and depending on it is dangerous. A more
-// principled approach would require significant refactoring, however, so for
-// the moment we're relying on fragile properties.
-class DependentIOBufferForRedirectToFile : public net::WrappedIOBuffer {
- public:
- DependentIOBufferForRedirectToFile(net::IOBuffer* backing, char* memory)
- : net::WrappedIOBuffer(memory), backing_(backing) {}
-
- private:
- ~DependentIOBufferForRedirectToFile() override {}
-
- scoped_refptr<net::IOBuffer> backing_;
-};
-
-} // namespace
-
-namespace content {
-
-const int RedirectToFileResourceHandler::kInitialReadBufSize = 32768;
-const int RedirectToFileResourceHandler::kMaxReadBufSize = 524288;
-
-// A separate IO thread object to manage the lifetime of the net::FileStream and
-// the ShareableFileReference. When the handler is destroyed, it asynchronously
-// closes net::FileStream after all pending writes complete. Only after the
-// stream is closed is the ShareableFileReference released, to ensure the
-// temporary is not deleted before it is closed.
-class RedirectToFileResourceHandler::Writer {
- public:
- Writer(RedirectToFileResourceHandler* handler,
- std::unique_ptr<net::FileStream> file_stream,
- ShareableFileReference* deletable_file)
- : handler_(handler),
- file_stream_(std::move(file_stream)),
- is_writing_(false),
- deletable_file_(deletable_file) {
- DCHECK(!deletable_file_->path().empty());
- }
-
- bool is_writing() const { return is_writing_; }
- const base::FilePath& path() const { return deletable_file_->path(); }
-
- int Write(net::IOBuffer* buf, int buf_len) {
- DCHECK(!is_writing_);
- DCHECK(handler_);
- int result = file_stream_->Write(
- buf, buf_len,
- base::BindOnce(&Writer::DidWriteToFile, base::Unretained(this)));
- if (result == net::ERR_IO_PENDING)
- is_writing_ = true;
- return result;
- }
-
- void Close() {
- handler_ = nullptr;
- if (!is_writing_)
- CloseAndDelete();
- }
-
- private:
- // Only DidClose can delete this.
- ~Writer() {
- }
-
- void DidWriteToFile(int result) {
- DCHECK(is_writing_);
- is_writing_ = false;
- if (handler_) {
- handler_->DidWriteToFile(result);
- } else {
- CloseAndDelete();
- }
- }
-
- void CloseAndDelete() {
- DCHECK(!is_writing_);
- int result = file_stream_->Close(
- base::BindOnce(&Writer::DidClose, base::Unretained(this)));
- if (result != net::ERR_IO_PENDING)
- DidClose(result);
- }
-
- void DidClose(int result) {
- delete this;
- }
-
- RedirectToFileResourceHandler* handler_;
-
- std::unique_ptr<net::FileStream> file_stream_;
- bool is_writing_;
-
- // We create a ShareableFileReference that's deletable for the temp file
- // created as a result of the download.
- scoped_refptr<storage::ShareableFileReference> deletable_file_;
-
- DISALLOW_COPY_AND_ASSIGN(Writer);
-};
-
-RedirectToFileResourceHandler::RedirectToFileResourceHandler(
- std::unique_ptr<ResourceHandler> next_handler,
- net::URLRequest* request)
- : LayeredResourceHandler(request, std::move(next_handler)),
- buf_(new net::GrowableIOBuffer()),
- weak_factory_(this) {}
-
-RedirectToFileResourceHandler::~RedirectToFileResourceHandler() {
- // Orphan the writer to asynchronously close and release the temporary file.
- if (writer_) {
- writer_->Close();
- writer_ = nullptr;
- }
-}
-
-void RedirectToFileResourceHandler::
- SetCreateTemporaryFileStreamFunctionForTesting(
- const CreateTemporaryFileStreamFunction& create_temporary_file_stream) {
- create_temporary_file_stream_ = create_temporary_file_stream;
-}
-
-void RedirectToFileResourceHandler::OnResponseStarted(
- network::ResourceResponse* response,
- std::unique_ptr<ResourceController> controller) {
- if (!writer_) {
- response_pending_file_creation_ = response;
- HoldController(std::move(controller));
- request()->LogBlockedBy("RedirectToFileResourceHandler");
- return;
- }
- response->head.download_file_path = writer_->path();
- next_handler_->OnResponseStarted(response, std::move(controller));
-}
-
-void RedirectToFileResourceHandler::OnWillStart(
- const GURL& url,
- std::unique_ptr<ResourceController> controller) {
- DCHECK(!writer_);
-
- // Create the file ASAP but don't block.
- if (create_temporary_file_stream_.is_null()) {
- CreateTemporaryFileStream(
- base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile,
- weak_factory_.GetWeakPtr()));
- } else {
- create_temporary_file_stream_.Run(
- base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile,
- weak_factory_.GetWeakPtr()));
- }
- next_handler_->OnWillStart(url, std::move(controller));
-}
-
-void RedirectToFileResourceHandler::OnWillRead(
- scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- std::unique_ptr<ResourceController> controller) {
- if (buf_->capacity() < next_buffer_size_)
- buf_->SetCapacity(next_buffer_size_);
-
- // We should have paused this network request already if the buffer is full.
- DCHECK(!BufIsFull());
-
- *buf = buf_.get();
- *buf_size = buf_->RemainingCapacity();
-
- buf_write_pending_ = true;
- controller->Resume();
-}
-
-void RedirectToFileResourceHandler::OnReadCompleted(
- int bytes_read,
- std::unique_ptr<ResourceController> controller) {
- DCHECK(buf_write_pending_);
- buf_write_pending_ = false;
-
- // We use the buffer's offset field to record the end of the buffer.
- int new_offset = buf_->offset() + bytes_read;
- DCHECK(new_offset <= buf_->capacity());
- buf_->set_offset(new_offset);
-
- if (buf_->capacity() == bytes_read) {
- // The network layer has saturated our buffer in one read. Next time, we
- // should give it a bigger buffer for it to fill.
- next_buffer_size_ = std::min(next_buffer_size_ * 2, kMaxReadBufSize);
- }
-
- HoldController(std::move(controller));
- // WriteMore will resume the request if there's more buffer space.
- if (!WriteMore()) {
- CancelWithError(net::ERR_FAILED);
- return;
- }
-
- if (has_controller())
- request()->LogBlockedBy("RedirectToFileResourceHandler");
-}
-
-void RedirectToFileResourceHandler::OnResponseCompleted(
- const net::URLRequestStatus& status,
- std::unique_ptr<ResourceController> controller) {
- if (writer_ && writer_->is_writing()) {
- completed_during_write_ = true;
- completed_status_ = status;
- HoldController(std::move(controller));
- request()->LogBlockedBy("RedirectToFileResourceHandler");
- return;
- }
- next_handler_->OnResponseCompleted(status, std::move(controller));
-}
-
-int RedirectToFileResourceHandler::GetBufferSizeForTesting() const {
- return buf_->capacity();
-}
-
-void RedirectToFileResourceHandler::DidCreateTemporaryFile(
- base::File::Error error_code,
- std::unique_ptr<net::FileStream> file_stream,
- ShareableFileReference* deletable_file) {
- DCHECK(!writer_);
- if (error_code != base::File::FILE_OK) {
- if (has_controller()) {
- CancelWithError(net::FileErrorToNetError(error_code));
- } else {
- OutOfBandCancel(net::FileErrorToNetError(error_code),
- true /* tell_renderer */);
- }
- return;
- }
-
- writer_ = new Writer(this, std::move(file_stream), deletable_file);
-
- if (response_pending_file_creation_) {
- scoped_refptr<network::ResourceResponse> response =
- std::move(response_pending_file_creation_);
- request()->LogUnblocked();
- OnResponseStarted(response.get(), ReleaseController());
- }
-}
-
-void RedirectToFileResourceHandler::DidWriteToFile(int result) {
- bool failed = false;
- if (result > 0) {
- OnDataDownloaded(result);
- write_cursor_ += result;
- // WriteMore will resume the request if the request hasn't completed and
- // there's more buffer space.
- failed = !WriteMore();
- } else {
- failed = true;
- }
-
- if (failed) {
- DCHECK(!writer_->is_writing());
- // TODO(davidben): Recover the error code from WriteMore or |result|, as
- // appropriate.
- if (completed_during_write_ && completed_status_.is_success()) {
- // If the request successfully completed mid-write, but the write failed,
- // convert the status to a failure for downstream.
- completed_status_ = net::URLRequestStatus(net::URLRequestStatus::CANCELED,
- net::ERR_FAILED);
- }
- if (!completed_during_write_) {
- if (has_controller()) {
- // If the write buffer is full, |this| has deferred the request, and
- // can do an in-band cancel.
- CancelWithError(net::ERR_FAILED);
- } else {
- OutOfBandCancel(net::ERR_FAILED, true /* tell_renderer */);
- }
- return;
- }
- }
-
- if (completed_during_write_ && !writer_->is_writing()) {
- // Resume shutdown now that all data has been written to disk. Note that
- // this should run even in the |failed| case above, otherwise a failed write
- // leaves the handler stuck.
- DCHECK(has_controller());
- request()->LogUnblocked();
- next_handler_->OnResponseCompleted(completed_status_, ReleaseController());
- }
-}
-
-bool RedirectToFileResourceHandler::WriteMore() {
- DCHECK(writer_);
-
- for (;;) {
- if (write_cursor_ == buf_->offset()) {
- // We've caught up to the network load, but it may be in the process of
- // appending more data to the buffer.
- if (!buf_write_pending_) {
- buf_->set_offset(0);
- write_cursor_ = 0;
- }
- break;
- }
- if (writer_->is_writing())
- break;
- DCHECK(write_cursor_ < buf_->offset());
-
- // Create a temporary buffer pointing to a subsection of the data buffer so
- // that it can be passed to Write. This code makes some crazy scary
- // assumptions about object lifetimes, thread sharing, and that buf_ will
- // not realloc durring the write due to how the state machine in this class
- // works.
- // Note that buf_ is also shared with the code that writes data into the
- // cache, so modifying it can cause some pretty subtle race conditions:
- // https://code.google.com/p/chromium/issues/detail?id=152076
- // We're using DependentIOBuffer instead of DrainableIOBuffer to dodge some
- // of these issues, for the moment.
- // TODO(ncbray) make this code less crazy scary.
- // Also note that Write may increase the refcount of "wrapped" deep in the
- // bowels of its implementation, the use of scoped_refptr here is not
- // spurious.
- scoped_refptr<DependentIOBufferForRedirectToFile> wrapped =
- new DependentIOBufferForRedirectToFile(
- buf_.get(), buf_->StartOfBuffer() + write_cursor_);
- int write_len = buf_->offset() - write_cursor_;
-
- int rv = writer_->Write(wrapped.get(), write_len);
- if (rv == net::ERR_IO_PENDING)
- break;
- if (rv <= 0)
- return false;
- OnDataDownloaded(rv);
- write_cursor_ += rv;
- }
-
- // If the request was defered for a reason other than having been completed,
- // and the buffer has space, resume the request.
- if (has_controller() && !completed_during_write_ && !BufIsFull()) {
- request()->LogUnblocked();
- Resume();
- }
- return true;
-}
-
-bool RedirectToFileResourceHandler::BufIsFull() const {
- // This is a hack to workaround MimeTypeResourceHandler's inability to
- // deal with a ResourceHandler that returns a buffer size of less than
- // 2 * net::kMaxBytesToSniff from its OnWillRead method.
- // TODO(darin): Fix this retardation!
- return buf_->RemainingCapacity() <= (2 * net::kMaxBytesToSniff);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.h b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
deleted file mode 100644
index 41fb23c1301..00000000000
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.h
+++ /dev/null
@@ -1,138 +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_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_
-#define CONTENT_BROWSER_LOADER_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_
-
-#include <memory>
-
-#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/weak_ptr.h"
-#include "content/browser/loader/layered_resource_handler.h"
-#include "content/browser/loader/temporary_file_stream.h"
-#include "content/common/content_export.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_status.h"
-#include "url/gurl.h"
-
-namespace net {
-class FileStream;
-class GrowableIOBuffer;
-}
-
-namespace storage {
-class ShareableFileReference;
-}
-
-namespace content {
-
-class ResourceController;
-
-// Redirects network data to a file. This is intended to be layered in front of
-// either the AsyncResourceHandler or the SyncResourceHandler. The downstream
-// resource handler does not see OnWillRead or OnReadCompleted calls. Instead,
-// the ResourceResponse contains the path to a temporary file and
-// OnDataDownloaded is called as the file downloads.
-class CONTENT_EXPORT RedirectToFileResourceHandler
- : public LayeredResourceHandler {
- public:
- // Exposed for testing.
- static const int kInitialReadBufSize;
- static const int kMaxReadBufSize;
-
- typedef base::Callback<void(const CreateTemporaryFileStreamCallback&)>
- CreateTemporaryFileStreamFunction;
-
- // Create a RedirectToFileResourceHandler for |request| which wraps
- // |next_handler|.
- RedirectToFileResourceHandler(std::unique_ptr<ResourceHandler> next_handler,
- net::URLRequest* request);
- ~RedirectToFileResourceHandler() override;
-
- // Replace the CreateTemporaryFileStream implementation with a mocked one for
- // testing purposes. The function should create a net::FileStream and a
- // ShareableFileReference and then asynchronously pass them to the
- // CreateTemporaryFileStreamCallback.
- void SetCreateTemporaryFileStreamFunctionForTesting(
- const CreateTemporaryFileStreamFunction& create_temporary_file_stream);
-
- // LayeredResourceHandler implementation:
- void OnResponseStarted(
- network::ResourceResponse* response,
- std::unique_ptr<ResourceController> controller) override;
- void OnWillStart(const GURL& url,
- std::unique_ptr<ResourceController> controller) override;
- void OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- std::unique_ptr<ResourceController> controller) override;
- void OnReadCompleted(int bytes_read,
- std::unique_ptr<ResourceController> controller) override;
- void OnResponseCompleted(
- const net::URLRequestStatus& status,
- std::unique_ptr<ResourceController> controller) override;
-
- // Returns the size of |buf_|, to make sure it's being increased as expected.
- int GetBufferSizeForTesting() const;
-
- private:
- void DidCreateTemporaryFile(base::File::Error error_code,
- std::unique_ptr<net::FileStream> file_stream,
- storage::ShareableFileReference* deletable_file);
-
- // Called by RedirectToFileResourceHandler::Writer.
- void DidWriteToFile(int result);
-
- // Attempts to write more data to the file, if possible. Returns false on
- // error. Returns true if there's already a write in progress, all data was
- // written successfully, or a new write was started that will complete
- // asynchronously. Resumes the request if there's more data to read and more
- // buffer space available.
- bool WriteMore();
-
- bool BufIsFull() const;
-
- // If populated, OnResponseStarted completion is pending on file creation.
- scoped_refptr<network::ResourceResponse> response_pending_file_creation_;
- CreateTemporaryFileStreamFunction create_temporary_file_stream_;
-
- // We allocate a single, fixed-size IO buffer (buf_) used to read from the
- // network (buf_write_pending_ is true while the system is copying data into
- // buf_), and then write this buffer out to disk (write_callback_pending_ is
- // true while writing to disk). Reading from the network is suspended while
- // the buffer is full (BufIsFull returns true). The write_cursor_ member
- // tracks the offset into buf_ that we are writing to disk.
-
- scoped_refptr<net::GrowableIOBuffer> buf_;
- bool buf_write_pending_ = false;
- int write_cursor_ = 0;
-
- // Helper writer object which maintains references to the net::FileStream and
- // storage::ShareableFileReference. This is maintained separately so that,
- // on Windows, the temporary file isn't deleted until after it is closed.
- class Writer;
- Writer* writer_ = nullptr;
-
- // |next_buffer_size_| is the size of the buffer to be allocated on the next
- // OnWillRead() call. We exponentially grow the size of the buffer allocated
- // when our owner fills our buffers. On the first OnWillRead() call, we
- // allocate a buffer of 32k and double it in OnReadCompleted() if the buffer
- // was filled, up to a maximum size of 512k.
- int next_buffer_size_ = kInitialReadBufSize;
-
- bool completed_during_write_ = false;
- net::URLRequestStatus completed_status_;
-
- base::WeakPtrFactory<RedirectToFileResourceHandler> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(RedirectToFileResourceHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc b/chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc
deleted file mode 100644
index ac012a09e0e..00000000000
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc
+++ /dev/null
@@ -1,925 +0,0 @@
-// Copyright 2017 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/redirect_to_file_resource_handler.h"
-
-#include <algorithm>
-#include <limits>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/run_loop.h"
-#include "base/strings/string_piece.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/loader/mock_resource_loader.h"
-#include "content/browser/loader/temporary_file_stream.h"
-#include "content/browser/loader/test_resource_handler.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/base/completion_callback.h"
-#include "net/base/completion_once_callback.h"
-#include "net/base/file_stream.h"
-#include "net/base/io_buffer.h"
-#include "net/base/mime_sniffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/request_priority.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_status.h"
-#include "net/url_request/url_request_test_util.h"
-#include "services/network/public/cpp/resource_response.h"
-#include "storage/browser/blob/shareable_file_reference.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace content {
-namespace {
-
-// The maximum size for which the initial read will always be sync, even when
-// the wrote completes asynchronously. See
-// RedirectToFileResourceHandler::BufIsFull().
-const int kMaxInitialSyncReadSize =
- RedirectToFileResourceHandler::kInitialReadBufSize -
- 2 * net::kMaxBytesToSniff - 1;
-
-// Used to indicate whether FileStream operations and the lower-layer
-// TestResourceHandler operations should complete immediately or by
-// asynchronously invoking a callback. Each test is run with all operations set
-// by default to each mode, though some tests override the mode of some
-// operations.
-enum class CompletionMode {
- SYNC,
- ASYNC,
-};
-
-// Mock in-memory net::FileStream implementation that can be configured to
-// return errors and complete operations synchronously or asynchronously.
-class MockFileStream : public net::FileStream {
- public:
- struct OperationResult {
- OperationResult(int result, CompletionMode completion_mode)
- : result(result), completion_mode(completion_mode) {}
-
- OperationResult()
- : OperationResult(net::ERR_UNEXPECTED, CompletionMode::SYNC) {}
-
- int result;
- CompletionMode completion_mode;
- };
-
- MockFileStream() : FileStream(base::ThreadTaskRunnerHandle::Get()) {}
-
- ~MockFileStream() override {
- EXPECT_EQ(expect_closed_, closed_);
- // Most of these tests write 32k or more, which is a bit much for the
- // command line.
- EXPECT_TRUE(expected_written_data_ == written_data_);
- }
-
- // net::FileStream implementation:
-
- int Open(const base::FilePath& path,
- int open_flags,
- net::CompletionOnceCallback callback) override {
- return ReturnResult(open_result_, std::move(callback));
- }
-
- int Close(net::CompletionOnceCallback callback) override {
- EXPECT_FALSE(closed_);
- int result = ReturnResult(
- close_result_,
- base::BindOnce(&MockFileStream::SetClosedAndRunCallback,
- base::Unretained(this), std::move(callback)));
- if (result != net::ERR_IO_PENDING)
- closed_ = true;
- return result;
- }
-
- bool IsOpen() const override {
- NOTREACHED();
- return false;
- }
-
- int Seek(int64_t offset, net::Int64CompletionOnceCallback callback) override {
- NOTREACHED();
- return net::ERR_UNEXPECTED;
- }
-
- int Read(net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback) override {
- NOTREACHED();
- return net::ERR_UNEXPECTED;
- }
-
- int Write(net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback) override {
- // 0-byte writes aren't allowed.
- EXPECT_GT(buf_len, 0);
-
- OperationResult write_result = next_write_result_;
- next_write_result_ = all_write_results_;
- if (write_result.result > buf_len)
- write_result.result = buf_len;
- if (write_result.result > 0)
- written_data_ += std::string(buf->data(), write_result.result);
-
- return ReturnResult(write_result, std::move(callback));
- }
-
- int Flush(net::CompletionOnceCallback callback) override {
- NOTREACHED();
- return net::ERR_UNEXPECTED;
- }
-
- void set_open_result(OperationResult open_result) {
- open_result_ = open_result;
- }
- void set_close_result(OperationResult close_result) {
- close_result_ = close_result;
- }
-
- // Sets the result for all write operations. Returned result is capped at
- // number of bytes the consumer actually tried to write. Overrides
- // |next_write_result_|.
- void set_all_write_results(OperationResult all_write_results) {
- next_write_result_ = all_write_results_ = all_write_results;
- }
-
- // Sets the result of only the next write operation.
- void set_next_write_result(OperationResult next_write_result) {
- next_write_result_ = next_write_result;
- }
-
- void set_expected_written_data(const std::string& expected_written_data) {
- expected_written_data_ = expected_written_data;
- }
-
- // Sets whether the file should expect to be closed.
- void set_expect_closed(bool expect_closed) { expect_closed_ = expect_closed; }
-
- private:
- void SetClosedAndRunCallback(net::CompletionOnceCallback callback,
- int result) {
- EXPECT_FALSE(closed_);
- closed_ = true;
- std::move(callback).Run(result);
- }
-
- int ReturnResult(OperationResult result,
- net::CompletionOnceCallback callback) {
- if (result.completion_mode == CompletionMode::SYNC)
- return result.result;
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), result.result));
- return net::ERR_IO_PENDING;
- }
-
- OperationResult open_result_;
- OperationResult close_result_;
- OperationResult next_write_result_;
- OperationResult all_write_results_;
-
- std::string expected_written_data_;
- std::string written_data_;
-
- bool expect_closed_ = false;
- bool closed_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(MockFileStream);
-};
-
-class RedirectToFileResourceHandlerTest
- : public testing::TestWithParam<CompletionMode> {
- public:
- RedirectToFileResourceHandlerTest()
- : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
- url_request_(
- url_request_context_.CreateRequest(GURL("foo://bar/"),
- net::DEFAULT_PRIORITY,
- &url_request_delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS)) {
- base::CreateTemporaryFile(&temp_file_path_);
- std::unique_ptr<TestResourceHandler> test_handler =
- std::make_unique<TestResourceHandler>();
- test_handler->set_expect_on_data_downloaded(true);
- if (GetParam() == CompletionMode::ASYNC) {
- // Don't defer OnResponseCompleted, by default, since that's really
- // unusual.
- test_handler->set_defer_on_response_started(true);
- test_handler->set_defer_on_will_start(true);
- }
- test_handler_ = test_handler->GetWeakPtr();
-
- redirect_to_file_handler_ = std::make_unique<RedirectToFileResourceHandler>(
- std::move(test_handler), url_request_.get());
- mock_loader_ =
- std::make_unique<MockResourceLoader>(redirect_to_file_handler_.get());
- redirect_to_file_handler_->SetCreateTemporaryFileStreamFunctionForTesting(
- base::Bind(&RedirectToFileResourceHandlerTest::
- SetCreateTemporaryFileStreamCallback,
- base::Unretained(this)));
-
- file_stream_ = std::make_unique<MockFileStream>();
- file_stream_->set_open_result(
- MockFileStream::OperationResult(net::OK, GetParam()));
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), GetParam()));
- file_stream_->set_close_result(
- MockFileStream::OperationResult(net::OK, GetParam()));
- }
-
- ~RedirectToFileResourceHandlerTest() override {
- EXPECT_FALSE(test_handler_->on_read_completed_called());
-
- // This should post a task to delete the temporary file.
- redirect_to_file_handler_.reset();
- mock_loader_.reset();
- url_request_.reset();
- // This should delete the temporary file, and ensure
- // MockFileStream::Cancel() is called.
- base::RunLoop().RunUntilIdle();
-
- EXPECT_FALSE(base::PathExists(temp_file_path_));
- }
-
- // Creates a test string of the specified length, and sets that as the
- // expected data written to |file_stream_|.
- std::string CreateTestData(size_t length) {
- std::string test_data;
- test_data.reserve(length);
- for (size_t i = 0; i < length; ++i)
- test_data.push_back(static_cast<char>(i % 256));
- file_stream_->set_expected_written_data(test_data);
- return test_data;
- }
-
- // The "CreateTemporaryFileStream" method invoked by the
- // RedirectToFileResourceHandler. Just sets a callback that will be invoked
- // directly.
- void SetCreateTemporaryFileStreamCallback(
- const CreateTemporaryFileStreamCallback& create_file_stream_callback) {
- create_file_stream_callback_ = create_file_stream_callback;
- }
-
- void PerformOnWillStart() {
- MockResourceLoader::Status expected_status;
- if (GetParam() == CompletionMode::ASYNC) {
- expected_status = MockResourceLoader::Status::CALLBACK_PENDING;
- } else {
- expected_status = MockResourceLoader::Status::IDLE;
- }
- EXPECT_EQ(expected_status, mock_loader_->OnWillStart(url_request_->url()));
- }
-
- // Sets up the file stream or error, and performs the file callback.
- void PerformCreateFile(base::File::Error file_error) {
- DCHECK(file_stream_);
-
- file_stream_->set_expect_closed(file_error == base::File::FILE_OK);
- if (file_error != base::File::FILE_OK)
- file_stream_ = nullptr;
-
- base::ResetAndReturn(&create_file_stream_callback_)
- .Run(file_error, std::move(file_stream_),
- // Not really used by the test, but the ResourceHandler expects it
- // to be non-null.
- storage::ShareableFileReference::GetOrCreate(
- temp_file_path_,
- storage::ShareableFileReference::DELETE_ON_FINAL_RELEASE,
- base::ThreadTaskRunnerHandle::Get().get())
- .get());
- }
-
- // Simulates starting the request, the response starting, and stream creation
- // completing with the specified error code. Has |test_handler_| resume the
- // request, if needed. Returns final status of |mock_loader_|.
- MockResourceLoader::Status StartAndCreateStream(base::File::Error file_error)
- WARN_UNUSED_RESULT {
- PerformOnWillStart();
-
- // Create the file right away.
- PerformCreateFile(file_error);
-
- // If this is an async test, |test_handler_| will defer the OnWillStart
- // event on success (On error, its OnWillStart method is not called).
- if (file_error == base::File::FILE_OK &&
- GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- test_handler_->Resume();
- mock_loader_->WaitUntilIdleOrCanceled();
- }
- EXPECT_NE(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- return mock_loader_->status();
- }
-
- // Convenience wrapper for MockLoader methods that will Resume |test_handler_|
- // and wait for it to resume the request if running an async test.
- MockResourceLoader::Status OnResponseStartedAndWaitForResult()
- WARN_UNUSED_RESULT {
- mock_loader_->OnResponseStarted(
- base::MakeRefCounted<network::ResourceResponse>());
- if (GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- test_handler_->Resume();
- mock_loader_->WaitUntilIdleOrCanceled();
- }
- EXPECT_NE(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- return mock_loader_->status();
- }
-
- // Utility method that simulates a final 0-byte read and response completed
- // events, and checks that completion is handled correctly. Expects all data
- // to already have been written to the file.
- void CompleteRequestSuccessfully(int expected_total_bytes_downloaded) {
- // The loader should be idle and all the data should have already been
- // processed.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
- EXPECT_EQ(expected_total_bytes_downloaded,
- test_handler_->total_bytes_downloaded());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(""));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::OK)));
- EXPECT_EQ(expected_total_bytes_downloaded,
- test_handler_->total_bytes_downloaded());
- EXPECT_EQ(net::URLRequestStatus::SUCCESS,
- test_handler_->final_status().status());
- }
-
- protected:
- TestBrowserThreadBundle thread_bundle_;
- base::FilePath temp_file_path_;
- net::TestURLRequestContext url_request_context_;
- net::TestDelegate url_request_delegate_;
- base::WeakPtr<TestResourceHandler> test_handler_;
- std::unique_ptr<net::URLRequest> url_request_;
- std::unique_ptr<MockResourceLoader> mock_loader_;
- std::unique_ptr<RedirectToFileResourceHandler> redirect_to_file_handler_;
- std::unique_ptr<MockFileStream> file_stream_;
-
- CreateTemporaryFileStreamCallback create_file_stream_callback_;
-};
-
-TEST_P(RedirectToFileResourceHandlerTest, EmptyBody) {
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- CompleteRequestSuccessfully(0);
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, SingleBodyRead) {
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
- // Wait for the write to complete, in the async case.
- base::RunLoop().RunUntilIdle();
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, SingleBodyReadDelayedFileOnResponse) {
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- PerformOnWillStart();
- if (GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- test_handler_->Resume();
- mock_loader_->WaitUntilIdleOrCanceled();
- }
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
- mock_loader_->OnResponseStarted(
- base::MakeRefCounted<network::ResourceResponse>());
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
-
- PerformCreateFile(base::File::FILE_OK);
-
- if (GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- test_handler_->Resume();
- mock_loader_->WaitUntilIdleOrCanceled();
- }
- EXPECT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
- // Wait for the write to complete, in the async case.
- base::RunLoop().RunUntilIdle();
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, SingleBodyReadDelayedFileError) {
- std::string test_data = CreateTestData(0);
-
- PerformOnWillStart();
- if (GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- test_handler_->Resume();
- mock_loader_->WaitUntilIdleOrCanceled();
- }
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
- mock_loader_->OnResponseStarted(
- base::MakeRefCounted<network::ResourceResponse>());
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
-
- PerformCreateFile(base::File::FILE_ERROR_FAILED);
-
- EXPECT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status());
- EXPECT_EQ(0, test_handler_->on_response_completed_called());
- EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, ManySequentialBodyReads) {
- const size_t kBytesPerRead = 128;
- std::string test_data =
- CreateTestData(RedirectToFileResourceHandler::kInitialReadBufSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- for (size_t offset = 0; offset < test_data.length();
- offset += kBytesPerRead) {
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- size_t length = std::min(kBytesPerRead, test_data.length() - offset);
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(
- base::StringPiece(test_data.data() + offset, length)));
- // Spin the message loop, to allow async writes to complete.
- base::RunLoop().RunUntilIdle();
- }
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, PartialWrites) {
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- RedirectToFileResourceHandler::kInitialReadBufSize / 50, GetParam()));
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
- // Wait for the writes to complete, in the async case.
- base::RunLoop().RunUntilIdle();
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-// Same as above, but read enough data to defer reading the body.
-TEST_P(RedirectToFileResourceHandlerTest, PartialWrites2) {
- std::string test_data =
- CreateTestData(RedirectToFileResourceHandler::kInitialReadBufSize);
- // Async reads, as otherwise reading won't be defered.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- RedirectToFileResourceHandler::kInitialReadBufSize / 50,
- CompletionMode::ASYNC));
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnReadCompleted(test_data));
- // Wait for the writes to complete.
- base::RunLoop().RunUntilIdle();
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, ReceiveDataWhileWritingBody) {
- const int kFirstWriteSize = 100;
-
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- // Will use multiple writes, with a combined size such that they don't
- // saturate the buffer.
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(
- MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(0, kFirstWriteSize)));
- // Next read completes before first write succeeds.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(
- kFirstWriteSize, sizeof(test_data) - kFirstWriteSize)));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // Wait for both writes to succeed.
- base::RunLoop().RunUntilIdle();
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, ReceiveDataAndDeferWhileWritingBody) {
- const int kFirstWriteSize = 100;
-
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- // Will use multiple writes, with a combined size such that they saturate the
- // buffer.
- std::string test_data =
- CreateTestData(RedirectToFileResourceHandler::kInitialReadBufSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(
- MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(0, kFirstWriteSize)));
- // Next read completes before first write succeeds.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnReadCompleted(test_data.substr(
- kFirstWriteSize, sizeof(test_data) - kFirstWriteSize)));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // Wait for both writes to succeed.
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest,
- ExpandBufferCapacityManySequentialBodyReads) {
- // The buffer is only resized when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- const int kInitialReadSize =
- RedirectToFileResourceHandler::kInitialReadBufSize;
- const int kMaxReadSize = RedirectToFileResourceHandler::kMaxReadBufSize;
- int next_read_size = kInitialReadSize;
- int total_read_bytes = 0;
- // Populate |read_sizes| with expected buffer sizes if each previous read
- // filled the entire buffer.
- std::vector<size_t> read_sizes;
- while (true) {
- total_read_bytes += next_read_size;
- read_sizes.push_back(next_read_size);
- if (next_read_size == kMaxReadSize)
- break;
- next_read_size = std::min(2 * next_read_size, kMaxReadSize);
- }
- // Once the max is reached, do another round to make sure it isn't increased.
- total_read_bytes += kMaxReadSize;
- read_sizes.push_back(kMaxReadSize);
-
- std::string test_data = CreateTestData(total_read_bytes);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- int offset = 0;
- for (int read_size : read_sizes) {
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnReadCompleted(
- base::StringPiece(test_data.data() + offset, read_size)));
- offset += read_size;
-
- EXPECT_EQ(read_size, redirect_to_file_handler_->GetBufferSizeForTesting());
-
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
- }
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, CompletedWhileWritingBody) {
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // While data is being written to the disk, the request completes.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(""));
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::OK)));
-
- // Wait for the write to complete and the final status sent to the
- // TestHandler.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(test_data.size()),
- test_handler_->total_bytes_downloaded());
- EXPECT_EQ(net::URLRequestStatus::SUCCESS,
- test_handler_->final_status().status());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest,
- CompletedWhileWritingBodyAndWritePending) {
- const int kFirstWriteSize = 100;
-
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- // Will use multiple writes, with a combined size such that they don't
- // saturate the buffer.
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(
- MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(0, kFirstWriteSize)));
- // Next read completes before first write succeeds.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(
- kFirstWriteSize, sizeof(test_data) - kFirstWriteSize)));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // While the first write is still going on, the request completes.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(""));
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::OK)));
-
- // Wait for both writes to complete and the final status to be sent to the
- // TestHandler.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(test_data.size()),
- test_handler_->total_bytes_downloaded());
- EXPECT_EQ(net::URLRequestStatus::SUCCESS,
- test_handler_->final_status().status());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, SingleBodyReadAndFail) {
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
-
- // Wait for the write to complete.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(test_data.size()),
- test_handler_->total_bytes_downloaded());
-
- // Next read fails and request is torn down synchronously.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
-
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, FailedWhileWritingBody) {
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // While data is being written to the disk, the request fails.
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
-
- // Wait for the write to complete and the final status sent to the
- // TestHandler.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(test_data.size()),
- test_handler_->total_bytes_downloaded());
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest,
- FailededWhileWritingBodyAndWritePending) {
- const int kFirstWriteSize = 100;
-
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- // Will use multiple writes, with a combined size such that they don't
- // saturate the buffer.
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(
- MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(0, kFirstWriteSize)));
- // Next read completes before first write succeeds.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(
- kFirstWriteSize, sizeof(test_data) - kFirstWriteSize)));
-
- // While the first write is still going on, the request fails.
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // Wait for both writes to complete and the final status to be sent to the
- // TestHandler.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(test_data.size()),
- test_handler_->total_bytes_downloaded());
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, CreateFileFails) {
- ASSERT_EQ(MockResourceLoader::Status::CANCELED,
- StartAndCreateStream(base::File::FILE_ERROR_FAILED));
-
- EXPECT_EQ(0, test_handler_->on_response_completed_called());
- EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
- if (GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompletedFromExternalOutOfBandCancel(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- } else {
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- }
-
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, FirstWriteFails) {
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
- file_stream_->set_expected_written_data("");
- file_stream_->set_next_write_result(
- MockFileStream::OperationResult(net::ERR_FAILED, GetParam()));
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- mock_loader_->OnReadCompleted(test_data);
- // Wait for the write to complete, in the async case.
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status());
-
- EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
- EXPECT_EQ(0, test_handler_->on_response_completed_called());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, SecondWriteFails) {
- const int kFirstWriteSize = kMaxInitialSyncReadSize;
- std::string test_data =
- CreateTestData(RedirectToFileResourceHandler::kInitialReadBufSize);
- file_stream_->set_expected_written_data(test_data.substr(0, kFirstWriteSize));
- file_stream_->set_all_write_results(
- MockFileStream::OperationResult(net::ERR_FAILED, GetParam()));
- file_stream_->set_next_write_result(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), GetParam()));
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(
- base::StringPiece(test_data.data(), kFirstWriteSize)));
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- mock_loader_->OnReadCompleted(base::StringPiece(
- test_data.data() + kFirstWriteSize, test_data.size() - kFirstWriteSize));
- // Wait for the write to complete, in the async case.
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status());
-
- EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
- EXPECT_EQ(0, test_handler_->on_response_completed_called());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- EXPECT_EQ(kFirstWriteSize, test_handler_->total_bytes_downloaded());
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-INSTANTIATE_TEST_CASE_P(/* No prefix needed */,
- RedirectToFileResourceHandlerTest,
- testing::Values(CompletionMode::SYNC,
- CompletionMode::ASYNC));
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/browser/loader/resource_buffer.cc b/chromium/content/browser/loader/resource_buffer.cc
deleted file mode 100644
index 5e34dd24f15..00000000000
--- a/chromium/content/browser/loader/resource_buffer.cc
+++ /dev/null
@@ -1,173 +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/resource_buffer.h"
-
-#include <math.h>
-
-#include "base/logging.h"
-
-namespace content {
-
-// A circular buffer allocator.
-//
-// We keep track of the starting offset (alloc_start_) and the ending offset
-// (alloc_end_). There are two layouts to keep in mind:
-//
-// #1:
-// ------------[XXXXXXXXXXXXXXXXXXXXXXX]----
-// ^ ^
-// start end
-//
-// #2:
-// XXXXXXXXXX]---------------------[XXXXXXXX
-// ^ ^
-// end start
-//
-// If end <= start, then we have the buffer wraparound case (depicted second).
-// If the buffer is empty, then start and end will be set to -1.
-//
-// Allocations are always contiguous.
-
-ResourceBuffer::ResourceBuffer()
- : buf_size_(0),
- min_alloc_size_(0),
- max_alloc_size_(0),
- alloc_start_(-1),
- alloc_end_(-1) {
-}
-
-ResourceBuffer::~ResourceBuffer() {
-}
-
-bool ResourceBuffer::Initialize(int buffer_size,
- int min_allocation_size,
- int max_allocation_size) {
- CHECK(!IsInitialized());
-
- // It would be wasteful if these are not multiples of min_allocation_size.
- CHECK_EQ(0, buffer_size % min_allocation_size);
- CHECK_EQ(0, max_allocation_size % min_allocation_size);
-
- buf_size_ = buffer_size;
- min_alloc_size_ = min_allocation_size;
- max_alloc_size_ = max_allocation_size;
-
- return shared_mem_.CreateAndMapAnonymous(buf_size_);
-}
-
-bool ResourceBuffer::IsInitialized() const {
- return shared_mem_.memory() != nullptr;
-}
-
-base::SharedMemory& ResourceBuffer::GetSharedMemory() {
- CHECK(IsInitialized());
- return shared_mem_;
-}
-
-bool ResourceBuffer::CanAllocate() const {
- CHECK(IsInitialized());
-
- if (alloc_start_ == -1)
- return true;
-
- int diff = alloc_end_ - alloc_start_;
- if (diff > 0)
- return (buf_size_ - diff) >= min_alloc_size_;
-
- return -diff >= min_alloc_size_;
-}
-
-char* ResourceBuffer::Allocate(int* size) {
- CHECK(CanAllocate());
-
- int alloc_offset = 0;
- int alloc_size;
-
- if (alloc_start_ == -1) {
- // This is the first allocation.
- alloc_start_ = 0;
- alloc_end_ = buf_size_;
- alloc_size = buf_size_;
- } else if (alloc_start_ < alloc_end_) {
- // Append the next allocation if it fits. Otherwise, wraparound.
- //
- // NOTE: We could look to see if a larger allocation is possible by
- // wrapping around sooner, but instead we just look to fill the space at
- // the end of the buffer provided that meets the min_alloc_size_
- // requirement.
- //
- if ((buf_size_ - alloc_end_) >= min_alloc_size_) {
- alloc_offset = alloc_end_;
- alloc_size = buf_size_ - alloc_end_;
- alloc_end_ = buf_size_;
- } else {
- // It must be possible to allocate a least min_alloc_size_.
- CHECK(alloc_start_ >= min_alloc_size_);
- alloc_size = alloc_start_;
- alloc_end_ = alloc_start_;
- }
- } else {
- // This is the wraparound case.
- CHECK(alloc_end_ < alloc_start_);
- alloc_offset = alloc_end_;
- alloc_size = alloc_start_ - alloc_end_;
- alloc_end_ = alloc_start_;
- }
-
- // Make sure alloc_size does not exceed max_alloc_size_. We store the
- // current value of alloc_size, so that we can use ShrinkLastAllocation to
- // trim it back. This allows us to reuse the alloc_end_ adjustment logic.
-
- alloc_sizes_.push(alloc_size);
-
- if (alloc_size > max_alloc_size_) {
- alloc_size = max_alloc_size_;
- ShrinkLastAllocation(alloc_size);
- }
-
- *size = alloc_size;
- return static_cast<char*>(shared_mem_.memory()) + alloc_offset;
-}
-
-int ResourceBuffer::GetLastAllocationOffset() const {
- CHECK(!alloc_sizes_.empty());
- CHECK(alloc_end_ >= alloc_sizes_.back());
- return alloc_end_ - alloc_sizes_.back();
-}
-
-void ResourceBuffer::ShrinkLastAllocation(int new_size) {
- CHECK(!alloc_sizes_.empty());
-
- int aligned_size = (new_size / min_alloc_size_) * min_alloc_size_;
- if (aligned_size < new_size)
- aligned_size += min_alloc_size_;
-
- CHECK_LE(new_size, aligned_size);
- CHECK_GE(alloc_sizes_.back(), aligned_size);
-
- int* last_allocation_size = &alloc_sizes_.back();
- alloc_end_ -= (*last_allocation_size - aligned_size);
- *last_allocation_size = aligned_size;
-}
-
-void ResourceBuffer::RecycleLeastRecentlyAllocated() {
- CHECK(!alloc_sizes_.empty());
- int allocation_size = alloc_sizes_.front();
- alloc_sizes_.pop();
-
- alloc_start_ += allocation_size;
- CHECK(alloc_start_ <= buf_size_);
-
- if (alloc_start_ == alloc_end_) {
- CHECK(alloc_sizes_.empty());
- alloc_start_ = -1;
- alloc_end_ = -1;
- } else if (alloc_start_ == buf_size_) {
- CHECK(!alloc_sizes_.empty());
- alloc_start_ = 0;
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/resource_buffer.h b/chromium/content/browser/loader/resource_buffer.h
deleted file mode 100644
index 85354c4a1c7..00000000000
--- a/chromium/content/browser/loader/resource_buffer.h
+++ /dev/null
@@ -1,122 +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_RESOURCE_BUFFER_H_
-#define CONTENT_BROWSER_LOADER_RESOURCE_BUFFER_H_
-
-#include "base/containers/queue.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/shared_memory.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// ResourceBuffer implements a simple "circular buffer" allocation strategy.
-// Allocations are recycled in FIFO order.
-//
-// You can think of the ResourceBuffer as a FIFO. The Allocate method reserves
-// space in the buffer. Allocate may be called multiple times until the buffer
-// is fully reserved (at which point CanAllocate returns false). Allocations
-// are freed in FIFO order via a call to RecycleLeastRecentlyAllocated.
-//
-// ResourceBuffer is reference-counted for the benefit of consumers, who need
-// to ensure that ResourceBuffer stays alive while they are using its memory.
-//
-// EXAMPLE USAGE:
-//
-// // Writes data into the ResourceBuffer, and returns the location (byte
-// // offset and count) of the bytes written into the ResourceBuffer's shared
-// // memory buffer.
-// void WriteToBuffer(ResourceBuffer* buf, int* offset, int* count) {
-// DCHECK(buf->CanAllocate());
-//
-// *offset = -1;
-// *count = 0;
-//
-// int size;
-// char* ptr = buf->Allocate(&size);
-// if (!ptr) { /* handle error */ }
-//
-// int bytes_read = static_cast<int>(fread(ptr, 1, size, file_pointer_));
-// if (!bytes_read) { /* handle error */ }
-//
-// if (bytes_read < size)
-// buf->ShrinkLastAllocation(bytes_read);
-//
-// *offset = buf->GetLastAllocationOffset();
-// *count = bytes_read;
-// }
-//
-// NOTE: As the above example illustrates, the ResourceBuffer keeps track of
-// the last allocation made. Calling ShrinkLastAllocation is optional, as it
-// just helps the ResourceBuffer optimize storage and be more aggressive about
-// returning larger allocations from the Allocate method.
-//
-class CONTENT_EXPORT ResourceBuffer
- : public base::RefCountedThreadSafe<ResourceBuffer> {
- public:
- ResourceBuffer();
-
- // Initialize the shared memory buffer. It will be buffer_size bytes in
- // length. The min/max_allocation_size parameters control the behavior of
- // the Allocate method. It will prefer to return segments that are
- // max_allocation_size in length, but will return segments less than that if
- // space is limited. It will not return allocations smaller than
- // min_allocation_size.
- bool Initialize(int buffer_size,
- int min_allocation_size,
- int max_allocation_size);
- bool IsInitialized() const;
-
- // Returns a reference to the underlying shared memory.
- base::SharedMemory& GetSharedMemory();
-
- // Returns true if Allocate will succeed.
- bool CanAllocate() const;
-
- // Returns a pointer into the shared memory buffer or NULL if the buffer is
- // already fully allocated. The returned size will be max_allocation_size
- // unless the buffer is close to being full.
- char* Allocate(int* size);
-
- // Returns the offset into the shared memory buffer where the last allocation
- // returned by Allocate can be found.
- int GetLastAllocationOffset() const;
-
- // Called to reduce the size of the last allocation returned by Allocate. It
- // is OK for new_size to match the current size of the last allocation.
- void ShrinkLastAllocation(int new_size);
-
- // Called to allow reuse of memory that was previously allocated. See notes
- // above the class for more details about this method.
- void RecycleLeastRecentlyAllocated();
-
- private:
- friend class base::RefCountedThreadSafe<ResourceBuffer>;
- ~ResourceBuffer();
-
- base::SharedMemory shared_mem_;
-
- int buf_size_;
- int min_alloc_size_;
- int max_alloc_size_;
-
- // These point to the range of the shared memory that is currently allocated.
- // If alloc_start_ is -1, then the range is empty and nothing is allocated.
- // Otherwise, alloc_start_ points to the start of the allocated range, and
- // alloc_end_ points just beyond the end of the previous allocation. In the
- // wraparound case, alloc_end_ <= alloc_start_. See resource_buffer.cc for
- // more details about these members.
- int alloc_start_;
- int alloc_end_;
-
- base::queue<int> alloc_sizes_;
-
- DISALLOW_COPY_AND_ASSIGN(ResourceBuffer);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_RESOURCE_BUFFER_H_
diff --git a/chromium/content/browser/loader/resource_buffer_unittest.cc b/chromium/content/browser/loader/resource_buffer_unittest.cc
deleted file mode 100644
index a9e90431544..00000000000
--- a/chromium/content/browser/loader/resource_buffer_unittest.cc
+++ /dev/null
@@ -1,137 +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/resource_buffer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-TEST(ResourceBufferTest, BasicAllocations) {
- scoped_refptr<ResourceBuffer> buf = new ResourceBuffer();
- EXPECT_TRUE(buf->Initialize(100, 5, 10));
- EXPECT_TRUE(buf->CanAllocate());
-
- // First allocation
- {
- int size;
- char* ptr = buf->Allocate(&size);
- EXPECT_TRUE(ptr);
- EXPECT_EQ(10, size);
- EXPECT_TRUE(buf->CanAllocate());
-
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
-
- buf->ShrinkLastAllocation(2); // Less than our min allocation size.
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
- EXPECT_TRUE(buf->CanAllocate());
- }
-
- // Second allocation
- {
- int size;
- char* ptr = buf->Allocate(&size);
- EXPECT_TRUE(ptr);
- EXPECT_EQ(10, size);
- EXPECT_TRUE(buf->CanAllocate());
-
- EXPECT_EQ(5, buf->GetLastAllocationOffset());
-
- buf->ShrinkLastAllocation(4);
- EXPECT_EQ(5, buf->GetLastAllocationOffset());
-
- EXPECT_TRUE(buf->CanAllocate());
- }
-}
-
-TEST(ResourceBufferTest, AllocateAndRecycle) {
- scoped_refptr<ResourceBuffer> buf = new ResourceBuffer();
- EXPECT_TRUE(buf->Initialize(100, 5, 10));
-
- int size;
-
- buf->Allocate(&size);
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
-
- buf->RecycleLeastRecentlyAllocated();
-
- // Offset should again be 0.
- buf->Allocate(&size);
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
-}
-
-TEST(ResourceBufferTest, WrapAround) {
- scoped_refptr<ResourceBuffer> buf = new ResourceBuffer();
- EXPECT_TRUE(buf->Initialize(20, 10, 10));
-
- int size;
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- // Create hole at the beginnning. Next allocation should go there.
- buf->RecycleLeastRecentlyAllocated();
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
-}
-
-TEST(ResourceBufferTest, WrapAround2) {
- scoped_refptr<ResourceBuffer> buf = new ResourceBuffer();
- EXPECT_TRUE(buf->Initialize(30, 10, 10));
-
- int size;
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- EXPECT_FALSE(buf->CanAllocate());
-
- // Create holes at first and second slots.
- buf->RecycleLeastRecentlyAllocated();
- buf->RecycleLeastRecentlyAllocated();
-
- EXPECT_TRUE(buf->CanAllocate());
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
- EXPECT_EQ(10, buf->GetLastAllocationOffset());
-
- EXPECT_FALSE(buf->CanAllocate());
-}
-
-TEST(ResourceBufferTest, Full) {
- scoped_refptr<ResourceBuffer> buf = new ResourceBuffer();
- EXPECT_TRUE(buf->Initialize(20, 10, 10));
-
- int size;
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- // Full.
- EXPECT_FALSE(buf->CanAllocate());
-
- // Still full, even if there is a small hole at the end.
- buf->ShrinkLastAllocation(5);
- EXPECT_FALSE(buf->CanAllocate());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/resource_controller.h b/chromium/content/browser/loader/resource_controller.h
index 82785346fef..55ecd8c28a5 100644
--- a/chromium/content/browser/loader/resource_controller.h
+++ b/chromium/content/browser/loader/resource_controller.h
@@ -5,8 +5,13 @@
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_CONTROLLER_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_CONTROLLER_H_
+#include "base/optional.h"
#include "content/common/content_export.h"
+namespace net {
+class HttpRequestHeaders;
+};
+
namespace content {
// Used to either resume a deferred resource load or cancel a resource load at
@@ -25,6 +30,12 @@ class CONTENT_EXPORT ResourceController {
// deferred. Guaranteed not to call back into the ResourceHandler, or destroy
// it, synchronously.
virtual void Resume() = 0;
+
+ // Similar to |Resume()| but can only be called if the request was previously
+ // redirected. |modified_request_headers| are changes applied to the request
+ // headers after updating them for the redirect.
+ virtual void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) = 0;
};
} // 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 1c1fb59e02c..061ad189c46 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -47,7 +47,6 @@
#include "content/browser/loader/mime_sniffing_resource_handler.h"
#include "content/browser/loader/mojo_async_resource_handler.h"
#include "content/browser/loader/null_resource_controller.h"
-#include "content/browser/loader/redirect_to_file_resource_handler.h"
#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -55,7 +54,6 @@
#include "content/browser/loader/stream_resource_handler.h"
#include "content/browser/loader/throttling_resource_handler.h"
#include "content/browser/loader/upload_data_stream_builder.h"
-#include "content/browser/loader/wake_lock_resource_throttle.h"
#include "content/browser/resource_context_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
@@ -112,11 +110,11 @@
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "services/network/resource_scheduler.h"
+#include "services/network/throttling/scoped_throttling_token.h"
#include "services/network/url_loader_factory.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/blob_url_request_job_factory.h"
-#include "storage/browser/blob/shareable_file_reference.h"
#include "storage/browser/fileapi/file_permission_policy.h"
#include "storage/browser/fileapi/file_system_context.h"
#include "url/third_party/mozilla/url_parse.h"
@@ -171,12 +169,6 @@ void AbortRequestBeforeItStarts(
url_loader_client->OnComplete(status);
}
-void RemoveDownloadFileFromChildSecurityPolicy(int child_id,
- const base::FilePath& path) {
- ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile(
- child_id, path);
-}
-
bool IsValidatedSCT(
const net::SignedCertificateTimestampAndStatus& sct_status) {
return sct_status.status == net::ct::SCT_STATUS_OK;
@@ -193,6 +185,7 @@ PreviewsState DetermineEnabledPreviews(PreviewsState previews_to_allow,
net::URLRequest* request,
ResourceContext* resource_context,
bool is_main_frame) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
// If previews have already been turned off, or we are inheriting values on a
// sub-frame, don't check any further.
if (previews_to_allow & PREVIEWS_OFF ||
@@ -324,8 +317,6 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl(
max_num_in_flight_requests_ * kMaxRequestsPerProcessRatio)),
max_outstanding_requests_cost_per_process_(
kMaxOutstandingRequestsCostPerProcess),
- largest_outstanding_request_count_seen_(0),
- largest_outstanding_request_per_process_count_seen_(0),
delegate_(nullptr),
loader_delegate_(nullptr),
allow_cross_origin_auth_prompt_(false),
@@ -557,7 +548,8 @@ scoped_refptr<LoginDelegate> ResourceDispatcherHostImpl::CreateLoginDelegate(
scoped_refptr<LoginDelegate> login_delegate =
GetContentClient()->browser()->CreateLoginDelegate(
auth_info, resource_request_info->GetWebContentsGetterForRequest(),
- is_request_for_main_frame, url,
+ request_id, is_request_for_main_frame, url,
+ request->response_headers(),
resource_request_info->first_auth_attempt(),
base::BindOnce(&ResourceDispatcherHostImpl::RunAuthRequiredCallback,
base::Unretained(this), request_id));
@@ -606,13 +598,6 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(
network::ResourceResponse* response) {
ResourceRequestInfoImpl* info = loader->GetRequestInfo();
net::URLRequest* request = loader->request();
- if (request->was_fetched_via_proxy() &&
- request->was_fetched_via_spdy() &&
- request->url().SchemeIs(url::kHttpScheme)) {
- scheduler_->OnReceivedSpdyProxiedHttpResponse(
- info->GetChildID(), info->GetRouteID());
- }
-
if (delegate_)
delegate_->OnResponseStarted(request, info->GetContext(), response);
}
@@ -620,39 +605,9 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(
void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
ResourceRequestInfoImpl* info = loader->GetRequestInfo();
- base::TimeDelta request_loading_time(base::TimeTicks::Now() -
- loader->request()->creation_time());
-
// Record final result of all resource loads.
if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME) {
- // This enumeration has "3" appended to its name to distinguish it from
- // older versions.
- base::UmaHistogramSparse("Net.ErrorCodesForMainFrame3",
- -loader->request()->status().error());
- if (loader->request()->status().error() == net::OK) {
- UMA_HISTOGRAM_LONG_TIMES("Net.RequestTime2Success.MainFrame",
- request_loading_time);
- }
- if (loader->request()->status().error() == 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);
- }
-
if (loader->request()->url().SchemeIsCryptographic()) {
- if (loader->request()->url().host_piece() == "www.google.com") {
- base::UmaHistogramSparse("Net.ErrorCodesForHTTPSGoogleMainFrame2",
- -loader->request()->status().error());
- }
-
- if (net::IsTLS13ExperimentHost(loader->request()->url().host_piece())) {
- base::UmaHistogramSparse("Net.ErrorCodesForTLS13ExperimentMainFrame",
- -loader->request()->status().error());
- }
-
int num_valid_scts = std::count_if(
loader->request()->ssl_info().signed_certificate_timestamps.begin(),
loader->request()->ssl_info().signed_certificate_timestamps.end(),
@@ -660,18 +615,6 @@ void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
UMA_HISTOGRAM_COUNTS_100(
"Net.CertificateTransparency.MainFrameValidSCTCount", num_valid_scts);
}
- } else {
- if (loader->request()->status().error() == net::OK) {
- UMA_HISTOGRAM_LONG_TIMES("Net.RequestTime2Success.Subresource",
- request_loading_time);
- }
- if (info->GetResourceType() == RESOURCE_TYPE_IMAGE) {
- base::UmaHistogramSparse("Net.ErrorCodesForImages",
- -loader->request()->status().error());
- }
- // This enumeration has "2" appended to distinguish it from older versions.
- base::UmaHistogramSparse("Net.ErrorCodesForSubresources2",
- -loader->request()->status().error());
}
if (delegate_)
@@ -725,6 +668,7 @@ void ResourceDispatcherHostImpl::OnRequestResourceInternal(
int request_id,
bool is_sync_load,
const network::ResourceRequest& request_data,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
@@ -732,7 +676,7 @@ void ResourceDispatcherHostImpl::OnRequestResourceInternal(
requester_info->IsNavigationPreload() ||
requester_info->IsCertificateFetcherForSignedExchange());
BeginRequest(requester_info, request_id, request_data, is_sync_load,
- routing_id, std::move(mojo_request),
+ routing_id, url_loader_options, std::move(mojo_request),
std::move(url_loader_client), traffic_annotation);
}
@@ -756,6 +700,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
const network::ResourceRequest& request_data,
bool is_sync_load,
int route_id,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
@@ -862,7 +807,8 @@ void ResourceDispatcherHostImpl::BeginRequest(
&ResourceDispatcherHostImpl::ContinuePendingBeginRequest,
base::Unretained(this), base::WrapRefCounted(requester_info),
request_id, request_data, is_sync_load, route_id,
- request_data.headers, base::Passed(std::move(mojo_request)),
+ request_data.headers, url_loader_options,
+ base::Passed(std::move(mojo_request)),
base::Passed(std::move(url_loader_client)),
base::Passed(std::move(blob_handles)), traffic_annotation));
return;
@@ -871,7 +817,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
}
ContinuePendingBeginRequest(
requester_info, request_id, request_data, is_sync_load, route_id,
- request_data.headers, std::move(mojo_request),
+ request_data.headers, url_loader_options, std::move(mojo_request),
std::move(url_loader_client), std::move(blob_handles), traffic_annotation,
HeaderInterceptorResult::CONTINUE);
}
@@ -883,6 +829,7 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
bool is_sync_load,
int route_id,
const net::HttpRequestHeaders& headers,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
BlobHandles blob_handles,
@@ -948,6 +895,7 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
new_request->set_site_for_cookies(request_data.site_for_cookies);
new_request->set_attach_same_site_cookies(
request_data.attach_same_site_cookies);
+ new_request->set_upgrade_if_insecure(request_data.upgrade_if_insecure);
// The initiator should normally be present, unless this is a navigation.
// Browser-initiated navigations don't have an initiator document, the
@@ -967,6 +915,11 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
new_request->SetExtraRequestHeaders(headers);
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token =
+ network::ScopedThrottlingToken::MaybeCreate(
+ new_request->net_log().source().id,
+ request_data.throttling_profile_id);
+
blob_context = GetBlobStorageContext(requester_info->blob_storage_context());
// Resolve elements from request_body and prepare upload data.
if (request_data.request_body.get()) {
@@ -1096,7 +1049,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
std::unique_ptr<ResourceHandler> handler = CreateResourceHandler(
requester_info.get(), new_request.get(), request_data, route_id, child_id,
- resource_context, std::move(mojo_request), std::move(url_loader_client));
+ resource_context, url_loader_options, std::move(mojo_request),
+ std::move(url_loader_client));
if (handler) {
RecordFetchRequestMode(request_data.url, request_data.method,
@@ -1104,7 +1058,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
const bool is_initiated_by_fetch_api =
request_data.fetch_request_context_type == REQUEST_CONTEXT_TYPE_FETCH;
BeginRequestInternal(std::move(new_request), std::move(handler),
- is_initiated_by_fetch_api);
+ is_initiated_by_fetch_api,
+ std::move(throttling_token));
}
}
@@ -1116,6 +1071,7 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
int route_id,
int child_id,
ResourceContext* resource_context,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client) {
DCHECK(requester_info->IsRenderer() ||
@@ -1124,15 +1080,10 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
// Construct the IPC resource handler.
std::unique_ptr<ResourceHandler> handler;
handler = CreateBaseResourceHandler(
- request, std::move(mojo_request), std::move(url_loader_client),
+ request, url_loader_options, std::move(mojo_request),
+ std::move(url_loader_client),
static_cast<ResourceType>(request_data.resource_type));
- // The RedirectToFileResourceHandler depends on being next in the chain.
- if (request_data.download_to_file) {
- handler.reset(
- new RedirectToFileResourceHandler(std::move(handler), request));
- }
-
// Prefetches outlive their child process.
if (request_data.resource_type == RESOURCE_TYPE_PREFETCH) {
auto detachable_handler = std::make_unique<DetachableResourceHandler>(
@@ -1153,13 +1104,14 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
std::unique_ptr<ResourceHandler>
ResourceDispatcherHostImpl::CreateBaseResourceHandler(
net::URLRequest* request,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
ResourceType resource_type) {
std::unique_ptr<ResourceHandler> handler;
handler.reset(new MojoAsyncResourceHandler(
request, this, std::move(mojo_request), std::move(url_loader_client),
- resource_type, network::mojom::kURLLoadOptionNone));
+ resource_type, url_loader_options));
return handler;
}
@@ -1191,12 +1143,6 @@ ResourceDispatcherHostImpl::AddStandardHandlers(
&throttles);
}
- if (request->has_upload()) {
- // Request wake lock while uploading data.
- throttles.push_back(
- std::make_unique<WakeLockResourceThrottle>(request->url().host()));
- }
-
// The Clear-Site-Data throttle.
std::unique_ptr<ResourceThrottle> clear_site_data_throttle =
ClearSiteDataThrottle::MaybeCreateThrottleForRequest(request);
@@ -1255,41 +1201,6 @@ ResourceDispatcherHostImpl::AddStandardHandlers(
return handler;
}
-void ResourceDispatcherHostImpl::RegisterDownloadedTempFile(
- int child_id, int request_id, const base::FilePath& file_path) {
- scoped_refptr<ShareableFileReference> reference =
- ShareableFileReference::Get(file_path);
- DCHECK(reference.get());
-
- registered_temp_files_[child_id][request_id] = reference;
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
- child_id, reference->path());
-
- // When the temp file is deleted, revoke permissions that the renderer has
- // to that file. This covers an edge case where the file is deleted and then
- // the same name is re-used for some other purpose, we don't want the old
- // renderer to still have access to it.
- //
- // We do this when the file is deleted because the renderer can take a blob
- // reference to the temp file that outlives the url loaded that it was
- // loaded with to keep the file (and permissions) alive.
- reference->AddFinalReleaseCallback(
- base::BindOnce(&RemoveDownloadFileFromChildSecurityPolicy, child_id));
-}
-
-void ResourceDispatcherHostImpl::UnregisterDownloadedTempFile(
- int child_id, int request_id) {
- DeletableFilesMap& map = registered_temp_files_[child_id];
- DeletableFilesMap::iterator found = map.find(request_id);
- if (found == map.end())
- return;
-
- map.erase(found);
-
- // Note that we don't remove the security bits here. This will be done
- // when all file refs are deleted (see RegisterDownloadedTempFile).
-}
-
ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
int child_id,
int render_view_route_id,
@@ -1353,7 +1264,6 @@ void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) {
const auto& map = keepalive_statistics_recorder_.per_process_records();
if (map.find(child_id) != map.end())
keepalive_statistics_recorder_.Unregister(child_id);
- registered_temp_files_.erase(child_id);
}
void ResourceDispatcherHostImpl::CancelRequestsForRoute(
@@ -1523,21 +1433,6 @@ ResourceDispatcherHostImpl::IncrementOutstandingRequestsCount(
DCHECK_GE(stats.num_requests, 0);
UpdateOutstandingRequestsStats(*info, stats);
- if (num_in_flight_requests_ > largest_outstanding_request_count_seen_) {
- largest_outstanding_request_count_seen_ = num_in_flight_requests_;
- UMA_HISTOGRAM_COUNTS_1M(
- "Net.ResourceDispatcherHost.OutstandingRequests.Total",
- largest_outstanding_request_count_seen_);
- }
-
- if (stats.num_requests >
- largest_outstanding_request_per_process_count_seen_) {
- largest_outstanding_request_per_process_count_seen_ = stats.num_requests;
- UMA_HISTOGRAM_COUNTS_1M(
- "Net.ResourceDispatcherHost.OutstandingRequests.PerProcess",
- largest_outstanding_request_per_process_count_seen_);
- }
-
return stats;
}
@@ -1571,11 +1466,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
ServiceWorkerNavigationHandleCore* service_worker_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
uint32_t url_loader_options,
- GlobalRequestID* global_request_id) {
- // PlzNavigate: BeginNavigationRequest currently should only be used for the
- // browser-side navigations project.
- CHECK(IsBrowserSideNavigationEnabled());
-
+ const GlobalRequestID& global_request_id) {
DCHECK(url_loader_client.is_bound());
DCHECK(url_loader_request.is_pending());
@@ -1623,11 +1514,16 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
new_request->set_method(info.common_params.method);
new_request->set_site_for_cookies(info.site_for_cookies);
new_request->set_initiator(info.begin_params->initiator_origin);
+ new_request->set_upgrade_if_insecure(info.upgrade_if_insecure);
if (info.is_main_frame) {
new_request->set_first_party_url_policy(
net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT);
}
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token =
+ network::ScopedThrottlingToken::MaybeCreate(
+ new_request->net_log().source().id, info.devtools_frame_token);
+
Referrer::SetReferrerForRequest(new_request.get(),
info.common_params.referrer);
@@ -1684,7 +1580,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
-1, // route_id
info.frame_tree_node_id,
ChildProcessHost::kInvalidUniqueID, // plugin_child_id
- MakeRequestID(),
+ global_request_id.request_id,
-1, // request_data.render_frame_id,
info.is_main_frame, resource_type, info.common_params.transition,
false, // is download
@@ -1713,8 +1609,6 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
// Request takes ownership.
extra_info->AssociateWithRequest(new_request.get());
- *global_request_id = extra_info->GetGlobalRequestID();
-
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.
@@ -1760,7 +1654,8 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
RecordFetchRequestMode(new_request->url(), new_request->method(),
network::mojom::FetchRequestMode::kNavigate);
BeginRequestInternal(std::move(new_request), std::move(handler),
- false /* is_initiated_by_fetch_api */);
+ false /* is_initiated_by_fetch_api */,
+ std::move(throttling_token));
}
void ResourceDispatcherHostImpl::SetLoaderDelegate(
@@ -1782,8 +1677,6 @@ void ResourceDispatcherHostImpl::OnRequestResourceWithMojo(
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
- DCHECK_EQ(network::mojom::kURLLoadOptionNone,
- options & ~network::mojom::kURLLoadOptionSynchronous);
if (!url_loader_client) {
VLOG(1) << "Killed renderer for null client";
bad_message::ReceivedBadMessage(requester_info->filter(),
@@ -1792,7 +1685,8 @@ void ResourceDispatcherHostImpl::OnRequestResourceWithMojo(
}
bool is_sync_load = options & network::mojom::kURLLoadOptionSynchronous;
OnRequestResourceInternal(requester_info, routing_id, request_id,
- is_sync_load, request, std::move(mojo_request),
+ is_sync_load, request, options,
+ std::move(mojo_request),
std::move(url_loader_client), traffic_annotation);
}
@@ -1819,7 +1713,8 @@ int ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(
void ResourceDispatcherHostImpl::BeginRequestInternal(
std::unique_ptr<net::URLRequest> request,
std::unique_ptr<ResourceHandler> handler,
- bool is_initiated_by_fetch_api) {
+ bool is_initiated_by_fetch_api,
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token) {
DCHECK(!request->is_pending());
ResourceRequestInfoImpl* info =
ResourceRequestInfoImpl::ForRequest(request.get());
@@ -1895,8 +1790,9 @@ void ResourceDispatcherHostImpl::BeginRequestInternal(
}
ResourceContext* resource_context = info->GetContext();
- std::unique_ptr<ResourceLoader> loader(new ResourceLoader(
- std::move(request), std::move(handler), this, resource_context));
+ std::unique_ptr<ResourceLoader> loader(
+ new ResourceLoader(std::move(request), std::move(handler), this,
+ resource_context, std::move(throttling_token)));
GlobalFrameRoutingId id(info->GetChildID(), info->GetRenderFrameID());
BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.find(id);
@@ -1966,7 +1862,8 @@ void ResourceDispatcherHostImpl::BeginURLRequest(
true /* force_download */, true /* is_new_request */);
}
BeginRequestInternal(std::move(request), std::move(handler),
- false /* is_initiated_by_fetch_api */);
+ false /* is_initiated_by_fetch_api */,
+ nullptr /* throttling_token */);
}
int ResourceDispatcherHostImpl::MakeRequestID() {
@@ -1974,6 +1871,10 @@ int ResourceDispatcherHostImpl::MakeRequestID() {
return --request_id_;
}
+GlobalRequestID ResourceDispatcherHostImpl::MakeGlobalRequestID() {
+ return GlobalRequestID(ChildProcessHost::kInvalidUniqueID, MakeRequestID());
+}
+
void ResourceDispatcherHostImpl::CancelRequestFromRenderer(
GlobalRequestID request_id) {
ResourceLoader* loader = GetLoader(request_id);
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index 388f7f84a00..b8a81809fff 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -47,7 +47,6 @@
#include "url/gurl.h"
namespace base {
-class FilePath;
class OneShotTimer;
}
@@ -59,11 +58,11 @@ class URLRequestContextGetter;
namespace network {
class ResourceScheduler;
+class ScopedThrottlingToken;
} // namespace network
namespace storage {
class FileSystemContext;
-class ShareableFileReference;
}
namespace content {
@@ -182,15 +181,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void CancelBlockedRequestsForRoute(
const GlobalFrameRoutingId& global_routing_id);
- // Maintains a collection of temp files created in support of
- // the download_to_file capability. Used to grant access to the
- // child process and to defer deletion of the file until it's
- // no longer needed.
- void RegisterDownloadedTempFile(
- int child_id, int request_id,
- const base::FilePath& file_path);
- void UnregisterDownloadedTempFile(int child_id, int request_id);
-
// Indicates whether third-party sub-content can pop-up HTTP basic auth
// dialog boxes.
bool allow_cross_origin_auth_prompt();
@@ -240,9 +230,8 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void FinishedWithResourcesForRequest(net::URLRequest* request);
// PlzNavigate: Begins a request for NavigationURLLoader. |loader| is the
- // loader to attach to the leaf resource handler.
- // After calling this function, |global_request_id| will contains the
- // request's global id.
+ // loader to attach to the leaf resource handler. |global_request_id| needs to
+ // be created by MakeGlobalRequestID() before calling this method.
void BeginNavigationRequest(
ResourceContext* resource_context,
net::URLRequestContext* request_context,
@@ -254,7 +243,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
ServiceWorkerNavigationHandleCore* service_worker_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
uint32_t url_loader_options,
- GlobalRequestID* global_request_id);
+ const GlobalRequestID& global_request_id);
int num_in_flight_requests_for_testing() const {
return num_in_flight_requests_;
@@ -311,6 +300,11 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// of |request_id_| for the details. Must be called on the IO thread.
int MakeRequestID();
+ // Creates a new global request ID for browser initiated requests. The ID
+ // is consistent with the request id created by MakeRequestID(). Must be
+ // called on the IO thread.
+ GlobalRequestID MakeGlobalRequestID();
+
// Cancels a request as requested by a renderer. This function is called when
// a mojo connection is lost.
// Note that this cancel is subtly different from the other CancelRequest
@@ -420,9 +414,11 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void OnShutdown();
// Helper function for URL requests.
- void BeginRequestInternal(std::unique_ptr<net::URLRequest> request,
- std::unique_ptr<ResourceHandler> handler,
- bool is_initiated_by_fetch_api);
+ void BeginRequestInternal(
+ std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceHandler> handler,
+ bool is_initiated_by_fetch_api,
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token);
void StartLoading(ResourceRequestInfoImpl* info,
std::unique_ptr<ResourceLoader> loader);
@@ -539,6 +535,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int request_id,
bool is_sync_load,
const network::ResourceRequest& request_data,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
@@ -550,6 +547,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
const network::ResourceRequest& request_data,
bool is_sync_load,
int route_id,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
@@ -569,6 +567,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
bool is_sync_load,
int route_id,
const net::HttpRequestHeaders& headers,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
BlobHandles blob_handles,
@@ -584,12 +583,14 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int route_id,
int child_id,
ResourceContext* resource_context,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client);
// Creates either MojoAsyncResourceHandler or AsyncResourceHandler.
std::unique_ptr<ResourceHandler> CreateBaseResourceHandler(
net::URLRequest* request,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
ResourceType resource_type);
@@ -667,15 +668,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
LoaderMap pending_loaders_;
- // Collection of temp files downloaded for child processes via
- // the download_to_file mechanism. We avoid deleting them until
- // the client no longer needs them.
- typedef std::map<int, scoped_refptr<storage::ShareableFileReference> >
- DeletableFilesMap; // key is request id
- typedef std::map<int, DeletableFilesMap>
- RegisteredTempFiles; // key is child process id
- RegisteredTempFiles registered_temp_files_;
-
// A timer that periodically calls UpdateLoadInfo while |pending_loaders_| is
// not empty, at least one RenderViewHost is loading, and not waiting on an
// ACK from the UI thread for the last sent LoadInfoList.
@@ -733,12 +725,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// kAvgBytesPerOutstandingRequest)
int max_outstanding_requests_cost_per_process_;
- // Largest number of outstanding requests seen so far across all processes.
- int largest_outstanding_request_count_seen_;
-
- // Largest number of outstanding requests seen so far in any single process.
- int largest_outstanding_request_per_process_count_seen_;
-
// Time of the last user gesture. Stored so that we can add a load
// flag to requests occurring soon after a gesture to indicate they
// may be because of explicit user action.
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index e576ad75157..d8d744e64ff 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -27,7 +27,6 @@
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/detachable_resource_handler.h"
-#include "content/browser/loader/downloaded_temp_file_impl.h"
#include "content/browser/loader/navigation_url_loader.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_loader.h"
@@ -78,6 +77,8 @@
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/public/cpp/resource_request.h"
+#include "services/network/resource_scheduler.h"
+#include "services/network/resource_scheduler_params_manager.h"
#include "services/network/test/test_url_loader_client.h"
#include "storage/browser/blob/shareable_file_reference.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -104,7 +105,6 @@ static network::ResourceRequest CreateResourceRequest(const char* method,
request.plugin_child_id = -1;
request.resource_type = type;
request.appcache_host_id = kAppCacheNoHostId;
- request.download_to_file = false;
request.should_reset_appcache = false;
request.is_main_frame = true;
request.transition_type = ui::PAGE_TRANSITION_LINK;
@@ -818,7 +818,9 @@ class ResourceDispatcherHostTest : public testing::Test {
std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo(common_params, std::move(begin_params), url,
true, false, false, -1, false, false, false,
- nullptr, base::UnguessableToken::Create()));
+ false, nullptr,
+ base::UnguessableToken::Create(),
+ base::UnguessableToken::Create()));
std::unique_ptr<NavigationURLLoader> test_loader =
NavigationURLLoader::Create(
browser_context_->GetResourceContext(),
@@ -838,6 +840,18 @@ class ResourceDispatcherHostTest : public testing::Test {
request_info->detachable_handler()->is_detached();
}
+ void SetMaxDelayableRequests(size_t max_delayable_requests) {
+ network::ResourceSchedulerParamsManager::ParamsForNetworkQualityContainer c;
+ for (int i = 0; i != net::EFFECTIVE_CONNECTION_TYPE_LAST; ++i) {
+ auto type = static_cast<net::EffectiveConnectionType>(i);
+ c[type] =
+ network::ResourceSchedulerParamsManager::ParamsForNetworkQuality(
+ max_delayable_requests, 0.0, false);
+ }
+ host_.scheduler()->SetResourceSchedulerParamsManagerForTests(
+ network::ResourceSchedulerParamsManager(c));
+ }
+
content::TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<TestBrowserContext> browser_context_;
std::unique_ptr<TestURLRequestJobFactory> job_factory_;
@@ -1467,6 +1481,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsOnRenderFrameDeleted) {
host_.SetDelegate(&delegate);
host_.OnRenderViewHostCreated(filter_->child_id(), 0,
request_context_getter_.get());
+ SetMaxDelayableRequests(1);
// One RenderView issues a high priority request and a low priority one. Both
// should be started.
@@ -2208,138 +2223,6 @@ TEST_F(ResourceDispatcherHostTest, DataSentBeforeDetach) {
EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
}
-// Tests the dispatcher host's temporary file management in the mojo-enabled
-// loading.
-TEST_F(ResourceDispatcherHostTest, RegisterDownloadedTempFileWithMojo) {
- const int kRequestID = 1;
-
- // Create a temporary file.
- base::FilePath file_path;
- ASSERT_TRUE(base::CreateTemporaryFile(&file_path));
- EXPECT_TRUE(base::PathExists(file_path));
- scoped_refptr<ShareableFileReference> deletable_file =
- ShareableFileReference::GetOrCreate(
- file_path, ShareableFileReference::DELETE_ON_FINAL_RELEASE,
- base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()})
- .get());
-
- // Not readable.
- EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
-
- // Register it for a resource request.
- auto downloaded_file =
- DownloadedTempFileImpl::Create(filter_->child_id(), kRequestID);
- network::mojom::DownloadedTempFilePtr downloaded_file_ptr =
- DownloadedTempFileImpl::Create(filter_->child_id(), kRequestID);
- host_.RegisterDownloadedTempFile(filter_->child_id(), kRequestID, file_path);
-
- // Should be readable now.
- EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
-
- // The child releases from the request.
- downloaded_file_ptr = nullptr;
- content::RunAllTasksUntilIdle();
-
- // Still readable because there is another reference to the file. (The child
- // may take additional blob references.)
- EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
-
- // Release extra references and wait for the file to be deleted. (This relies
- // on the delete happening on the FILE thread which is mapped to main thread
- // in this test.)
- deletable_file = nullptr;
- content::RunAllTasksUntilIdle();
-
- // The file is no longer readable to the child and has been deleted.
- EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
- EXPECT_FALSE(base::PathExists(file_path));
-}
-
-// Tests that temporary files held on behalf of child processes are released
-// when the child process dies.
-TEST_F(ResourceDispatcherHostTest, ReleaseTemporiesOnProcessExit) {
- const int kRequestID = 1;
-
- // Create a temporary file.
- base::FilePath file_path;
- ASSERT_TRUE(base::CreateTemporaryFile(&file_path));
- scoped_refptr<ShareableFileReference> deletable_file =
- ShareableFileReference::GetOrCreate(
- file_path, ShareableFileReference::DELETE_ON_FINAL_RELEASE,
- base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()})
- .get());
-
- // Register it for a resource request.
- host_.RegisterDownloadedTempFile(filter_->child_id(), kRequestID, file_path);
- deletable_file = nullptr;
-
- // Should be readable now.
- EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
-
- // Let the process die.
- filter_->OnChannelClosing();
- content::RunAllTasksUntilIdle();
-
- // The file is no longer readable to the child and has been deleted.
- EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
- EXPECT_FALSE(base::PathExists(file_path));
-}
-
-TEST_F(ResourceDispatcherHostTest, DownloadToFile) {
- // Make a request which downloads to file.
- network::mojom::URLLoaderPtr loader;
- network::TestURLLoaderClient client;
- network::ResourceRequest request = CreateResourceRequest(
- "GET", RESOURCE_TYPE_SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
- request.download_to_file = true;
- filter_->CreateLoaderAndStart(
- mojo::MakeRequest(&loader), 0, 1, network::mojom::kURLLoadOptionNone,
- request, client.CreateInterfacePtr(),
- net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
- content::RunAllTasksUntilIdle();
-
- // The request should contain the following messages:
- // ReceivedResponse (indicates headers received and filename)
- // DataDownloaded* (bytes downloaded and total length)
- // RequestComplete (request is done)
- client.RunUntilComplete();
- EXPECT_FALSE(client.response_head().download_file_path.empty());
- EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(),
- static_cast<size_t>(client.download_data_length()));
- EXPECT_EQ(net::OK, client.completion_status().error_code);
-
- // Verify that the data ended up in the temporary file.
- std::string contents;
- ASSERT_TRUE(base::ReadFileToString(client.response_head().download_file_path,
- &contents));
- EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents);
-
- // The file should be readable by the child.
- EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), client.response_head().download_file_path));
-
- // When the renderer releases the file, it should be deleted.
- // RunUntilIdle doesn't work because base::WorkerPool is involved.
- ShareableFileReleaseWaiter waiter(client.response_head().download_file_path);
- client.TakeDownloadedTempFile();
- content::RunAllTasksUntilIdle();
- waiter.Wait();
- // The release callback runs before the delete is scheduled, so pump the
- // message loop for the delete itself. (This relies on the delete happening on
- // the FILE thread which is mapped to main thread in this test.)
- content::RunAllTasksUntilIdle();
-
- EXPECT_FALSE(base::PathExists(client.response_head().download_file_path));
- EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), client.response_head().download_file_path));
-}
-
WebContents* WebContentsBinder(WebContents* rv) { return rv; }
// Tests GetLoadInfoForAllRoutes when there are 3 requests from the same
diff --git a/chromium/content/browser/loader/resource_handler.cc b/chromium/content/browser/loader/resource_handler.cc
index a507567e950..c58d7641e4d 100644
--- a/chromium/content/browser/loader/resource_handler.cc
+++ b/chromium/content/browser/loader/resource_handler.cc
@@ -44,6 +44,11 @@ void ResourceHandler::Resume() {
ReleaseController()->Resume();
}
+void ResourceHandler::ResumeForRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
+ ReleaseController()->ResumeForRedirect(modified_request_headers);
+}
+
void ResourceHandler::Cancel() {
ReleaseController()->Cancel();
}
diff --git a/chromium/content/browser/loader/resource_handler.h b/chromium/content/browser/loader/resource_handler.h
index b9b6ebf554d..bb60dbe0d97 100644
--- a/chromium/content/browser/loader/resource_handler.h
+++ b/chromium/content/browser/loader/resource_handler.h
@@ -138,12 +138,6 @@ class CONTENT_EXPORT ResourceHandler {
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) = 0;
- // This notification is synthesized by the RedirectToFileResourceHandler
- // to indicate progress of 'download_to_file' requests. OnReadCompleted
- // calls are consumed by the RedirectToFileResourceHandler and replaced
- // with OnDataDownloaded calls.
- virtual void OnDataDownloaded(int bytes_downloaded) = 0;
-
protected:
explicit ResourceHandler(net::URLRequest* request);
@@ -165,6 +159,8 @@ class CONTENT_EXPORT ResourceHandler {
// These call the corresponding methods on the ResourceController previously
// passed to HoldController and then destroy it.
void Resume();
+ void ResumeForRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers);
void Cancel();
void CancelWithError(int error_code);
diff --git a/chromium/content/browser/loader/resource_hints_impl.cc b/chromium/content/browser/loader/resource_hints_impl.cc
index 6365bc19995..3ebe0570196 100644
--- a/chromium/content/browser/loader/resource_hints_impl.cc
+++ b/chromium/content/browser/loader/resource_hints_impl.cc
@@ -6,11 +6,10 @@
#include "base/memory/ref_counted.h"
#include "base/trace_event/trace_event.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_hints.h"
#include "net/base/address_list.h"
#include "net/base/load_flags.h"
-#include "net/dns/host_resolver.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_info.h"
#include "net/http/http_stream_factory.h"
@@ -24,18 +23,7 @@ namespace content {
namespace {
-class RequestHolder {
- public:
- std::unique_ptr<net::HostResolver::Request>* GetRequest() {
- return &request_;
- }
-
- private:
- std::unique_ptr<net::HostResolver::Request> request_;
-};
-
-void OnResolveComplete(std::unique_ptr<RequestHolder> request_holder,
- std::unique_ptr<net::AddressList> addresses,
+void OnResolveComplete(std::unique_ptr<net::AddressList> addresses,
const net::CompletionCallback& callback,
int result) {
// Plumb the resolution result into the callback if future consumers want
@@ -50,9 +38,7 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
const GURL& site_for_cookies,
int count,
bool allow_credentials) {
- DCHECK(ResourceDispatcherHostImpl::Get()
- ->io_thread_task_runner()
- ->BelongsToCurrentThread());
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(getter);
TRACE_EVENT2("net", "PreconnectUrl", "url", url.spec(), "count", count);
@@ -74,6 +60,9 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
user_agent);
net::NetworkDelegate* delegate = request_context->network_delegate();
+ // NetworkDelegate is not set in tests.
+ if (!delegate)
+ return;
if (delegate->CanEnablePrivacyMode(url, site_for_cookies))
request_info.privacy_mode = net::PRIVACY_MODE_ENABLED;
@@ -93,10 +82,9 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
int PreresolveUrl(net::URLRequestContextGetter* getter,
const GURL& url,
- const net::CompletionCallback& callback) {
- DCHECK(ResourceDispatcherHostImpl::Get()
- ->io_thread_task_runner()
- ->BelongsToCurrentThread());
+ const net::CompletionCallback& callback,
+ std::unique_ptr<net::HostResolver::Request>* out_request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(getter);
TRACE_EVENT1("net", "PreresolveUrl", "url", url.spec());
@@ -104,21 +92,17 @@ int PreresolveUrl(net::URLRequestContextGetter* getter,
if (!request_context)
return net::ERR_CONTEXT_SHUT_DOWN;
- auto request_holder = std::make_unique<RequestHolder>();
auto addresses = std::make_unique<net::AddressList>();
- // Save raw pointers before the unique_ptr is invalidated by base::Passed.
+ // Save raw pointers before the unique_ptr is invalidated by base::Passed().
net::AddressList* raw_addresses = addresses.get();
- std::unique_ptr<net::HostResolver::Request>* out_request =
- request_holder->GetRequest();
net::HostResolver* resolver = request_context->host_resolver();
net::HostResolver::RequestInfo resolve_info(net::HostPortPair::FromURL(url));
resolve_info.set_is_speculative(true);
return resolver->Resolve(
resolve_info, net::IDLE, raw_addresses,
- base::Bind(&OnResolveComplete, base::Passed(&request_holder),
- base::Passed(&addresses), callback),
+ base::Bind(&OnResolveComplete, base::Passed(&addresses), callback),
out_request, net::NetLogWithSource());
}
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index c06232582ab..2435233851b 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -43,6 +43,7 @@
#include "net/url_request/url_request_status.h"
#include "services/network/loader_util.h"
#include "services/network/public/cpp/resource_response.h"
+#include "services/network/throttling/scoped_throttling_token.h"
#include "url/url_constants.h"
using base::TimeDelta;
@@ -84,6 +85,8 @@ void PopulateResourceResponse(
response->head.socket_address = response_info.socket_address;
response->head.was_fetched_via_proxy = request->was_fetched_via_proxy();
response->head.network_accessed = response_info.network_accessed;
+ response->head.async_revalidation_requested =
+ response_info.async_revalidation_requested;
const content::ResourceRequestInfo* request_info =
content::ResourceRequestInfo::ForRequest(request);
if (request_info) {
@@ -152,7 +155,15 @@ class ResourceLoader::Controller : public ResourceController {
// ResourceController implementation:
void Resume() override {
MarkAsUsed();
- resource_loader_->Resume(true /* called_from_resource_controller */);
+ resource_loader_->Resume(true /* called_from_resource_controller */,
+ base::nullopt);
+ }
+
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ MarkAsUsed();
+ resource_loader_->Resume(true /* called_from_resource_controller */,
+ modified_request_headers);
}
void Cancel() override {
@@ -209,7 +220,8 @@ class ResourceLoader::ScopedDeferral {
// If Resume() was called, it just advanced the state without doing
// anything. Go ahead and resume the request now.
if (old_deferred_stage == DEFERRED_NONE)
- resource_loader_->Resume(false /* called_from_resource_controller */);
+ resource_loader_->Resume(false /* called_from_resource_controller */,
+ base::nullopt);
}
private:
@@ -219,10 +231,12 @@ class ResourceLoader::ScopedDeferral {
DISALLOW_COPY_AND_ASSIGN(ScopedDeferral);
};
-ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request,
- std::unique_ptr<ResourceHandler> handler,
- ResourceLoaderDelegate* delegate,
- ResourceContext* resource_context)
+ResourceLoader::ResourceLoader(
+ std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceHandler> handler,
+ ResourceLoaderDelegate* delegate,
+ ResourceContext* resource_context,
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token)
: deferred_stage_(DEFERRED_NONE),
request_(std::move(request)),
handler_(std::move(handler)),
@@ -231,6 +245,7 @@ ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request,
started_request_(false),
times_cancelled_after_request_start_(0),
resource_context_(resource_context),
+ throttling_token_(std::move(throttling_token)),
weak_ptr_factory_(this) {
request_->set_delegate(this);
handler_->SetDelegate(this);
@@ -515,9 +530,13 @@ void ResourceLoader::CancelCertificateSelection() {
request_->CancelWithError(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
}
-void ResourceLoader::Resume(bool called_from_resource_controller) {
+void ResourceLoader::Resume(
+ bool called_from_resource_controller,
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DeferredStage stage = deferred_stage_;
deferred_stage_ = DEFERRED_NONE;
+ DCHECK(!modified_request_headers.has_value() || stage == DEFERRED_REDIRECT)
+ << "modified_request_headers can only be used with redirects";
switch (stage) {
case DEFERRED_NONE:
NOTREACHED();
@@ -536,7 +555,7 @@ void ResourceLoader::Resume(bool called_from_resource_controller) {
// URLRequest::Start completes asynchronously, so starting the request now
// won't result in synchronously calling into a ResourceHandler, if this
// was called from Resume().
- FollowDeferredRedirectInternal();
+ FollowDeferredRedirectInternal(modified_request_headers);
break;
case DEFERRED_ON_WILL_READ:
// Always post a task, as synchronous resumes don't go through this
@@ -611,8 +630,6 @@ void ResourceLoader::StartRequestInternal() {
request_->SetResponseHeadersCallback(base::Bind(
&ResourceLoader::SetRawResponseHeaders, base::Unretained(this)));
}
- UMA_HISTOGRAM_TIMES("Net.ResourceLoader.TimeToURLRequestStart",
- base::TimeTicks::Now() - request_->creation_time());
request_->Start();
delegate_->DidStartRequest(this);
@@ -664,14 +681,18 @@ void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
}
}
-void ResourceLoader::FollowDeferredRedirectInternal() {
+void ResourceLoader::FollowDeferredRedirectInternal(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DCHECK(!deferred_redirect_url_.is_empty());
GURL redirect_url = deferred_redirect_url_;
deferred_redirect_url_ = GURL();
if (delegate_->HandleExternalProtocol(this, redirect_url)) {
+ DCHECK(!modified_request_headers.has_value())
+ << "ResourceLoaderDelegate::HandleExternalProtocol() with modified "
+ "headers was not supported yet. crbug.com/845683";
Cancel();
} else {
- request_->FollowDeferredRedirect();
+ request_->FollowDeferredRedirect(modified_request_headers);
}
}
@@ -797,7 +818,6 @@ void ResourceLoader::ResponseCompleted() {
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
DVLOG(1) << "ResponseCompleted: " << request_->url().spec();
- RecordHistograms();
ScopedDeferral scoped_deferral(this, DEFERRED_FINISH);
handler_->OnResponseCompleted(request_->status(),
@@ -810,71 +830,6 @@ void ResourceLoader::CallDidFinishLoading() {
delegate_->DidFinishLoading(this);
}
-void ResourceLoader::RecordHistograms() {
- ResourceRequestInfoImpl* info = GetRequestInfo();
- if (request_->response_info().network_accessed) {
- if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME) {
- UMA_HISTOGRAM_ENUMERATION("Net.HttpResponseInfo.ConnectionInfo.MainFrame",
- request_->response_info().connection_info,
- net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS);
- } else {
- UMA_HISTOGRAM_ENUMERATION(
- "Net.HttpResponseInfo.ConnectionInfo.SubResource",
- request_->response_info().connection_info,
- net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS);
- }
- }
-
- if (request_->load_flags() & net::LOAD_PREFETCH) {
- // Note that RESOURCE_TYPE_PREFETCH requests are a subset of
- // net::LOAD_PREFETCH requests. In the histograms below, "Prefetch" means
- // RESOURCE_TYPE_PREFETCH and "LoadPrefetch" means net::LOAD_PREFETCH.
- bool is_resource_type_prefetch =
- info->GetResourceType() == RESOURCE_TYPE_PREFETCH;
- PrefetchStatus prefetch_status = STATUS_UNDEFINED;
- TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
-
- switch (request_->status().status()) {
- case net::URLRequestStatus::SUCCESS:
- if (request_->was_cached()) {
- prefetch_status = request_->response_info().unused_since_prefetch
- ? STATUS_SUCCESS_ALREADY_PREFETCHED
- : STATUS_SUCCESS_FROM_CACHE;
- if (is_resource_type_prefetch) {
- UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromCache",
- total_time);
- }
- } else {
- prefetch_status = STATUS_SUCCESS_FROM_NETWORK;
- if (is_resource_type_prefetch) {
- UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromNetwork",
- total_time);
- }
- }
- break;
- case net::URLRequestStatus::CANCELED:
- prefetch_status = STATUS_CANCELED;
- if (is_resource_type_prefetch)
- UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeBeforeCancel", total_time);
- break;
- case net::URLRequestStatus::IO_PENDING:
- case net::URLRequestStatus::FAILED:
- prefetch_status = STATUS_UNDEFINED;
- break;
- }
-
- UMA_HISTOGRAM_ENUMERATION("Net.LoadPrefetch.Pattern", prefetch_status,
- STATUS_MAX);
- if (is_resource_type_prefetch) {
- UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", prefetch_status,
- STATUS_MAX);
- }
- } else if (request_->response_info().unused_since_prefetch) {
- TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
- UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentOnPrefetchHit", total_time);
- }
-}
-
void ResourceLoader::SetRawResponseHeaders(
scoped_refptr<const net::HttpResponseHeaders> headers) {
raw_response_headers_ = headers;
diff --git a/chromium/content/browser/loader/resource_loader.h b/chromium/content/browser/loader/resource_loader.h
index 93ea0021af1..bbd241e28ed 100644
--- a/chromium/content/browser/loader/resource_loader.h
+++ b/chromium/content/browser/loader/resource_loader.h
@@ -25,6 +25,10 @@ class HttpResponseHeaders;
class X509Certificate;
}
+namespace network {
+class ScopedThrottlingToken;
+}
+
namespace content {
class LoginDelegate;
class ResourceHandler;
@@ -39,10 +43,12 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
public SSLClientAuthHandler::Delegate,
public ResourceHandler::Delegate {
public:
- ResourceLoader(std::unique_ptr<net::URLRequest> request,
- std::unique_ptr<ResourceHandler> handler,
- ResourceLoaderDelegate* delegate,
- ResourceContext* resource_context);
+ ResourceLoader(
+ std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceHandler> handler,
+ ResourceLoaderDelegate* delegate,
+ ResourceContext* resource_context,
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token);
~ResourceLoader() override;
void StartRequest();
@@ -92,14 +98,17 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
// |called_from_resource_controller| is true if called directly from a
// ResourceController, in which case |resource_handler_| must not be invoked
// or destroyed synchronously to avoid re-entrancy issues, and false
- // otherwise.
- void Resume(bool called_from_resource_controller);
+ // otherwise. |modified_request_headers| is used for redirects only.
+ void Resume(
+ bool called_from_resource_controller,
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers);
void Cancel();
void CancelWithError(int error_code);
void StartRequestInternal();
void CancelRequestInternal(int error, bool from_renderer);
- void FollowDeferredRedirectInternal();
+ void FollowDeferredRedirectInternal(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers);
void CompleteResponseStarted();
// If |handle_result_async| is true, the result of the following read will be
// handled asynchronously if it completes synchronously, unless it's EOF or an
@@ -112,7 +121,6 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
void CompleteRead(int bytes_read);
void ResponseCompleted();
void CallDidFinishLoading();
- void RecordHistograms();
void SetRawResponseHeaders(
scoped_refptr<const net::HttpResponseHeaders> headers);
@@ -177,6 +185,8 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
ResourceContext* resource_context_;
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token_;
+
bool should_pause_reading_body_ = false;
// The request is not deferred (i.e., DEFERRED_NONE) and is ready to read more
// response body data. However, reading is paused because of
diff --git a/chromium/content/browser/loader/resource_loader_unittest.cc b/chromium/content/browser/loader/resource_loader_unittest.cc
index 469e35d26be..aeae17a85e5 100644
--- a/chromium/content/browser/loader/resource_loader_unittest.cc
+++ b/chromium/content/browser/loader/resource_loader_unittest.cc
@@ -59,6 +59,7 @@
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/public/cpp/resource_response.h"
+#include "services/network/throttling/scoped_throttling_token.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -453,7 +454,7 @@ class ResourceLoaderTest : public testing::Test,
loader_.reset(new ResourceLoader(
std::move(request),
WrapResourceHandler(std::move(resource_handler), raw_ptr_to_request_),
- this, &resource_context_));
+ this, &resource_context_, nullptr /* throttling_token */));
}
void SetUpResourceLoaderForUrl(const GURL& test_url) {
diff --git a/chromium/content/browser/loader/resource_message_filter.cc b/chromium/content/browser/loader/resource_message_filter.cc
index 4a82566e296..2f531f5ae08 100644
--- a/chromium/content/browser/loader/resource_message_filter.cc
+++ b/chromium/content/browser/loader/resource_message_filter.cc
@@ -4,7 +4,7 @@
#include "content/browser/loader/resource_message_filter.h"
-#include "base/feature_list.h"
+#include "base/command_line.h"
#include "base/logging.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
@@ -18,9 +18,8 @@
#include "content/common/resource_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
-#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
#include "services/network/cors/cors_url_loader_factory.h"
-#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "storage/browser/fileapi/file_system_context.h"
@@ -146,6 +145,10 @@ void ResourceMessageFilter::CreateLoaderAndStart(
void ResourceMessageFilter::Clone(
network::mojom::URLLoaderFactoryRequest request) {
+ if (!url_loader_factory_) {
+ queued_clone_requests_.emplace_back(std::move(request));
+ return;
+ }
url_loader_factory_->Clone(std::move(request));
}
@@ -175,15 +178,19 @@ void ResourceMessageFilter::InitializeOnIOThread() {
// The WeakPtr of the filter must be created on the IO thread. So sets the
// WeakPtr of |requester_info_| now.
requester_info_->set_filter(GetWeakPtr());
- url_loader_factory_ = std::make_unique<URLLoaderFactoryImpl>(requester_info_);
-
- if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS)) {
- url_loader_factory_ = std::make_unique<network::cors::CORSURLLoaderFactory>(
- std::move(url_loader_factory_),
- base::BindRepeating(&ResourceDispatcherHostImpl::CancelRequest,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- requester_info_->child_id()));
- }
+ url_loader_factory_ = std::make_unique<network::cors::CORSURLLoaderFactory>(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity),
+ std::make_unique<URLLoaderFactoryImpl>(requester_info_),
+ base::BindRepeating(&ResourceDispatcherHostImpl::CancelRequest,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ requester_info_->child_id()));
+
+ std::vector<network::mojom::URLLoaderFactoryRequest> requests =
+ std::move(queued_clone_requests_);
+ for (auto& request : requests)
+ Clone(std::move(request));
+ queued_clone_requests_.clear();
}
} // namespace content
diff --git a/chromium/content/browser/loader/resource_message_filter.h b/chromium/content/browser/loader/resource_message_filter.h
index c8f2748aa4c..a0a5a0dc3cb 100644
--- a/chromium/content/browser/loader/resource_message_filter.h
+++ b/chromium/content/browser/loader/resource_message_filter.h
@@ -81,6 +81,7 @@ class CONTENT_EXPORT ResourceMessageFilter
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override;
+ // |request| could be queued when the channel has not been connected yet.
void Clone(network::mojom::URLLoaderFactoryRequest request) override;
int child_id() const;
@@ -116,6 +117,7 @@ class CONTENT_EXPORT ResourceMessageFilter
scoped_refptr<ResourceRequesterInfo> requester_info_;
std::unique_ptr<network::mojom::URLLoaderFactory> url_loader_factory_;
+ std::vector<network::mojom::URLLoaderFactoryRequest> queued_clone_requests_;
scoped_refptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index 651bf20c2c3..3db8fd33813 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -36,6 +36,11 @@ const void* const kResourceRequestInfoImplKey = &kResourceRequestInfoImplKey;
// ResourceRequestInfo
// static
+ResourceRequestInfo* ResourceRequestInfo::ForRequest(net::URLRequest* request) {
+ return ResourceRequestInfoImpl::ForRequest(request);
+}
+
+// static
const ResourceRequestInfo* ResourceRequestInfo::ForRequest(
const net::URLRequest* request) {
return ResourceRequestInfoImpl::ForRequest(request);
@@ -184,7 +189,8 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
previews_state_(previews_state),
body_(body),
initiated_in_secure_context_(initiated_in_secure_context),
- blocked_cross_site_document_(false),
+ blocked_response_from_reaching_renderer_(false),
+ should_report_corb_blocking_(false),
first_auth_attempt_(true) {}
ResourceRequestInfoImpl::~ResourceRequestInfoImpl() {
@@ -308,14 +314,6 @@ PreviewsState ResourceRequestInfoImpl::GetPreviewsState() const {
return previews_state_;
}
-bool ResourceRequestInfoImpl::ShouldReportRawHeaders() const {
- return report_raw_headers_;
-}
-
-bool ResourceRequestInfoImpl::ShouldReportSecurityInfo() const {
- return report_security_info_;
-}
-
NavigationUIData* ResourceRequestInfoImpl::GetNavigationUIData() const {
return navigation_ui_data_.get();
}
@@ -325,6 +323,11 @@ ResourceRequestInfo::DevToolsStatus ResourceRequestInfoImpl::GetDevToolsStatus()
return devtools_status_;
}
+void ResourceRequestInfoImpl::SetResourceRequestBlockedReason(
+ blink::ResourceRequestBlockedReason reason) {
+ resource_request_blocked_reason_ = reason;
+}
+
base::Optional<blink::ResourceRequestBlockedReason>
ResourceRequestInfoImpl::GetResourceRequestBlockedReason() const {
return resource_request_blocked_reason_;
@@ -353,6 +356,14 @@ GlobalRoutingID ResourceRequestInfoImpl::GetGlobalRoutingID() const {
return GlobalRoutingID(GetChildID(), route_id_);
}
+bool ResourceRequestInfoImpl::ShouldReportRawHeaders() const {
+ return report_raw_headers_;
+}
+
+bool ResourceRequestInfoImpl::ShouldReportSecurityInfo() const {
+ return report_security_info_;
+}
+
void ResourceRequestInfoImpl::ResetBody() {
body_ = nullptr;
}
diff --git a/chromium/content/browser/loader/resource_request_info_impl.h b/chromium/content/browser/loader/resource_request_info_impl.h
index 0b65d8c115b..0bc8ea93804 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -96,14 +96,12 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool IsDownload() const override;
// Returns a bitmask of potentially several Previews optimizations.
PreviewsState GetPreviewsState() const override;
- bool ShouldReportRawHeaders() const;
- bool ShouldReportSecurityInfo() const;
NavigationUIData* GetNavigationUIData() const override;
DevToolsStatus GetDevToolsStatus() const override;
-
+ void SetResourceRequestBlockedReason(
+ blink::ResourceRequestBlockedReason reason) override;
base::Optional<blink::ResourceRequestBlockedReason>
GetResourceRequestBlockedReason() const override;
-
base::StringPiece GetCustomCancelReason() const override;
CONTENT_EXPORT void AssociateWithRequest(net::URLRequest* request);
@@ -111,6 +109,14 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
CONTENT_EXPORT int GetRequestID() const;
GlobalRoutingID GetGlobalRoutingID() const;
+ // Returns true if raw response headers (including sensitive data such as
+ // cookies) should be included with the response.
+ bool ShouldReportRawHeaders() const;
+
+ // Returns true if security details (SSL/TLS connection parameters and
+ // certificate chain) should be included with the response.
+ bool ShouldReportSecurityInfo() const;
+
// PlzNavigate
// The id of the FrameTreeNode that initiated this request (for a navigation
// request).
@@ -184,18 +190,19 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
devtools_status_ = devtools_status;
}
- void set_resource_request_blocked_reason(
- base::Optional<blink::ResourceRequestBlockedReason> reason) {
- resource_request_blocked_reason_ = reason;
- }
-
void SetBlobHandles(BlobHandles blob_handles);
- bool blocked_cross_site_document() const {
- return blocked_cross_site_document_;
+ bool blocked_response_from_reaching_renderer() const {
+ return blocked_response_from_reaching_renderer_;
+ }
+ void set_blocked_response_from_reaching_renderer(bool value) {
+ blocked_response_from_reaching_renderer_ = value;
}
- void set_blocked_cross_site_document(bool value) {
- blocked_cross_site_document_ = value;
+ bool should_report_corb_blocking() const {
+ return should_report_corb_blocking_;
+ }
+ void set_should_report_corb_blocking(bool value) {
+ should_report_corb_blocking_ = value;
}
void set_custom_cancel_reason(base::StringPiece reason) {
@@ -248,7 +255,13 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
scoped_refptr<network::ResourceRequestBody> body_;
bool initiated_in_secure_context_;
std::unique_ptr<NavigationUIData> navigation_ui_data_;
- bool blocked_cross_site_document_;
+
+ // Whether response details (response headers, timing information, metadata)
+ // have been blocked from reaching the renderer process (e.g. by Cross-Origin
+ // Read Blocking).
+ bool blocked_response_from_reaching_renderer_;
+
+ bool should_report_corb_blocking_;
bool first_auth_attempt_;
// Keeps upload body blobs alive for the duration of the request.
diff --git a/chromium/content/browser/loader/resource_scheduler_filter.cc b/chromium/content/browser/loader/resource_scheduler_filter.cc
index 3b3da1ed38c..0667df77d25 100644
--- a/chromium/content/browser/loader/resource_scheduler_filter.cc
+++ b/chromium/content/browser/loader/resource_scheduler_filter.cc
@@ -5,8 +5,6 @@
#include "content/browser/loader/resource_scheduler_filter.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/common/frame_messages.h"
-#include "ipc/ipc_message_macros.h"
#include "services/network/resource_scheduler.h"
namespace content {
@@ -18,18 +16,6 @@ network::ResourceScheduler* GetResourceSchedulerOrNullptr() {
return ResourceDispatcherHostImpl::Get()->scheduler();
}
-ResourceSchedulerFilter::ResourceSchedulerFilter(int child_id)
- : BrowserMessageFilter(FrameMsgStart), child_id_(child_id) {}
-
-ResourceSchedulerFilter::~ResourceSchedulerFilter() {}
-
-bool ResourceSchedulerFilter::OnMessageReceived(const IPC::Message& message) {
- IPC_BEGIN_MESSAGE_MAP(ResourceSchedulerFilter, message)
- IPC_MESSAGE_HANDLER(FrameHostMsg_WillInsertBody, OnWillInsertBody)
- IPC_END_MESSAGE_MAP()
- return false;
-}
-
// static
void ResourceSchedulerFilter::OnDidCommitMainframeNavigation(
int render_process_id,
@@ -39,10 +25,4 @@ void ResourceSchedulerFilter::OnDidCommitMainframeNavigation(
scheduler->DeprecatedOnNavigate(render_process_id, render_view_routing_id);
}
-void ResourceSchedulerFilter::OnWillInsertBody(int render_view_routing_id) {
- auto* scheduler = GetResourceSchedulerOrNullptr();
- if (scheduler)
- scheduler->DeprecatedOnWillInsertBody(child_id_, render_view_routing_id);
-}
-
} // namespace content
diff --git a/chromium/content/browser/loader/resource_scheduler_filter.h b/chromium/content/browser/loader/resource_scheduler_filter.h
index 71a7b009809..573d27acd09 100644
--- a/chromium/content/browser/loader/resource_scheduler_filter.h
+++ b/chromium/content/browser/loader/resource_scheduler_filter.h
@@ -6,33 +6,20 @@
#define CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_FILTER_H_
#include "base/macros.h"
-#include "content/public/browser/browser_message_filter.h"
namespace content {
-// This class listens for incoming ViewHostMsgs that are applicable to the
-// ResourceScheduler and invokes the appropriate notifications. It must be
-// inserted before the RenderMessageFilter, because the ResourceScheduler runs
-// on the IO thread and we want to see the messages before the view messages are
-// bounced to the UI thread.
-class ResourceSchedulerFilter : public BrowserMessageFilter {
+// This class is used to send a signal to ResourceScheduler. This class used
+// to be a ResourceMessageFilter, but is not any more.
+class ResourceSchedulerFilter {
public:
- explicit ResourceSchedulerFilter(int child_id);
-
// Informs the ResourceScheduler that a main-frame, non-same-document
// navigation has just committed.
static void OnDidCommitMainframeNavigation(int render_process_id,
int render_view_routing_id);
-
- // BrowserMessageFilter:
- bool OnMessageReceived(const IPC::Message& message) override;
-
private:
- ~ResourceSchedulerFilter() override;
-
- void OnWillInsertBody(int render_view_routing_id);
-
- int child_id_;
+ ResourceSchedulerFilter() = delete;
+ ~ResourceSchedulerFilter() = delete;
DISALLOW_COPY_AND_ASSIGN(ResourceSchedulerFilter);
};
diff --git a/chromium/content/browser/loader/stream_resource_handler.cc b/chromium/content/browser/loader/stream_resource_handler.cc
index b1337ca2e17..9a487904ac1 100644
--- a/chromium/content/browser/loader/stream_resource_handler.cc
+++ b/chromium/content/browser/loader/stream_resource_handler.cc
@@ -73,8 +73,4 @@ void StreamResourceHandler::OnResponseCompleted(
controller->Resume();
}
-void StreamResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- NOTREACHED();
-}
-
} // namespace content
diff --git a/chromium/content/browser/loader/stream_resource_handler.h b/chromium/content/browser/loader/stream_resource_handler.h
index cb8a2d58d6b..b6f51bba48c 100644
--- a/chromium/content/browser/loader/stream_resource_handler.h
+++ b/chromium/content/browser/loader/stream_resource_handler.h
@@ -59,8 +59,6 @@ class StreamResourceHandler : public ResourceHandler {
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- void OnDataDownloaded(int bytes_downloaded) override;
-
Stream* stream() { return writer_.stream(); }
private:
diff --git a/chromium/content/browser/loader/temporary_file_stream.cc b/chromium/content/browser/loader/temporary_file_stream.cc
deleted file mode 100644
index 2f1c784f5e0..00000000000
--- a/chromium/content/browser/loader/temporary_file_stream.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/temporary_file_stream.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/files/file_proxy.h"
-#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
-#include "base/task_scheduler/post_task.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/base/file_stream.h"
-#include "storage/browser/blob/shareable_file_reference.h"
-
-using storage::ShareableFileReference;
-
-namespace content {
-
-namespace {
-
-void DidCreateTemporaryFile(
- const CreateTemporaryFileStreamCallback& callback,
- std::unique_ptr<base::FileProxy> file_proxy,
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- base::File::Error error_code,
- const base::FilePath& file_path) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (!file_proxy->IsValid()) {
- callback.Run(error_code, std::unique_ptr<net::FileStream>(), NULL);
- return;
- }
-
- // Cancelled or not, create the deletable_file so the temporary is cleaned up.
- scoped_refptr<ShareableFileReference> deletable_file =
- ShareableFileReference::GetOrCreate(
- file_path,
- ShareableFileReference::DELETE_ON_FINAL_RELEASE,
- task_runner.get());
-
- std::unique_ptr<net::FileStream> file_stream(
- new net::FileStream(file_proxy->TakeFile(), task_runner));
-
- callback.Run(error_code, std::move(file_stream), deletable_file.get());
-}
-
-} // namespace
-
-void CreateTemporaryFileStream(
- const CreateTemporaryFileStreamCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- scoped_refptr<base::SequencedTaskRunner> task_runner =
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
-
- std::unique_ptr<base::FileProxy> file_proxy(
- new base::FileProxy(task_runner.get()));
- base::FileProxy* proxy = file_proxy.get();
- proxy->CreateTemporary(
- base::File::FLAG_ASYNC,
- base::BindOnce(&DidCreateTemporaryFile, callback, std::move(file_proxy),
- std::move(task_runner)));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/temporary_file_stream.h b/chromium/content/browser/loader/temporary_file_stream.h
deleted file mode 100644
index 406fcc445ee..00000000000
--- a/chromium/content/browser/loader/temporary_file_stream.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_TEMPORARY_FILE_STREAM_H_
-#define CONTENT_BROWSER_LOADER_TEMPORARY_FILE_STREAM_H_
-
-#include <memory>
-
-#include "base/callback_forward.h"
-#include "base/files/file.h"
-#include "content/common/content_export.h"
-
-namespace net {
-class FileStream;
-}
-
-namespace storage {
-class ShareableFileReference;
-}
-
-namespace content {
-
-typedef base::Callback<void(base::File::Error,
- std::unique_ptr<net::FileStream>,
- storage::ShareableFileReference*)>
- CreateTemporaryFileStreamCallback;
-
-// Creates a temporary file and asynchronously calls |callback| with a
-// net::FileStream and storage::ShareableFileReference. The file is deleted
-// when the storage::ShareableFileReference is deleted. Note it is the
-// consumer's responsibility to ensure the storage::ShareableFileReference
-// stays in scope until net::FileStream has finished closing the file. On error,
-// |callback| is called with an error in the first parameter.
-//
-// This function may only be called on the IO thread.
-//
-// TODO(davidben): Juggling the net::FileStream and
-// storage::ShareableFileReference lifetimes is a nuisance. The two should
-// be tied together so the consumer need not deal with it.
-CONTENT_EXPORT void CreateTemporaryFileStream(
- const CreateTemporaryFileStreamCallback& callback);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_TEMPORARY_FILE_STREAM_H_
diff --git a/chromium/content/browser/loader/temporary_file_stream_unittest.cc b/chromium/content/browser/loader/temporary_file_stream_unittest.cc
deleted file mode 100644
index e32ae5b2a6b..00000000000
--- a/chromium/content/browser/loader/temporary_file_stream_unittest.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/temporary_file_stream.h"
-
-#include <string.h>
-#include <string>
-#include <utility>
-
-#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 "content/public/test/test_utils.h"
-#include "net/base/file_stream.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
-#include "storage/browser/blob/shareable_file_reference.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using storage::ShareableFileReference;
-
-namespace content {
-
-namespace {
-
-const char kTestData[] = "0123456789";
-const int kTestDataSize = arraysize(kTestData) - 1;
-
-class WaitForFileStream {
- public:
- base::File::Error error() const { return error_; }
- net::FileStream* file_stream() const { return file_stream_.get(); }
- ShareableFileReference* deletable_file() const {
- return deletable_file_.get();
- }
-
- void OnFileStreamCreated(base::File::Error error,
- std::unique_ptr<net::FileStream> file_stream,
- ShareableFileReference* deletable_file) {
- error_ = error;
- file_stream_ = std::move(file_stream);
- deletable_file_ = deletable_file;
- loop_.Quit();
- }
-
- void Wait() {
- loop_.Run();
- }
-
- void Release() {
- file_stream_.reset(nullptr);
- deletable_file_ = nullptr;
- }
- private:
- base::RunLoop loop_;
- base::File::Error error_;
- std::unique_ptr<net::FileStream> file_stream_;
- scoped_refptr<ShareableFileReference> deletable_file_;
-};
-
-} // namespace
-
-TEST(TemporaryFileStreamTest, Basic) {
- TestBrowserThreadBundle thread_bundle(TestBrowserThreadBundle::IO_MAINLOOP);
-
- // Create a temporary.
- WaitForFileStream file_stream_waiter;
- CreateTemporaryFileStream(base::Bind(&WaitForFileStream::OnFileStreamCreated,
- base::Unretained(&file_stream_waiter)));
- file_stream_waiter.Wait();
-
- // The temporary should exist.
- EXPECT_EQ(base::File::FILE_OK, file_stream_waiter.error());
- base::FilePath file_path = file_stream_waiter.deletable_file()->path();
- EXPECT_TRUE(base::PathExists(file_path));
-
- // Write some data to the temporary.
- int bytes_written = 0;
- scoped_refptr<net::IOBufferWithSize> buf =
- new net::IOBufferWithSize(kTestDataSize);
- memcpy(buf->data(), kTestData, kTestDataSize);
- scoped_refptr<net::DrainableIOBuffer> drainable =
- new net::DrainableIOBuffer(buf.get(), buf->size());
- while (bytes_written != kTestDataSize) {
- net::TestCompletionCallback write_callback;
- int rv = file_stream_waiter.file_stream()->Write(
- drainable.get(), drainable->BytesRemaining(),
- write_callback.callback());
- if (rv == net::ERR_IO_PENDING)
- rv = write_callback.WaitForResult();
- ASSERT_LT(0, rv);
- drainable->DidConsume(rv);
- bytes_written += rv;
- }
-
- // Verify the data matches.
- std::string contents;
- ASSERT_TRUE(base::ReadFileToString(file_path, &contents));
- EXPECT_EQ(kTestData, contents);
-
- // Close the file.
- net::TestCompletionCallback close_callback;
- int rv = file_stream_waiter.file_stream()->Close(close_callback.callback());
- if (rv == net::ERR_IO_PENDING)
- rv = close_callback.WaitForResult();
- EXPECT_EQ(net::OK, rv);
-
- // Release everything. The file should be gone now.
- file_stream_waiter.Release();
- content::RunAllTasksUntilIdle();
-
- // The temporary should be gone now.
- EXPECT_FALSE(base::PathExists(file_path));
-}
-
-} // content
diff --git a/chromium/content/browser/loader/test_resource_handler.cc b/chromium/content/browser/loader/test_resource_handler.cc
index b4c9f869b52..0fbeb2706a9 100644
--- a/chromium/content/browser/loader/test_resource_handler.cc
+++ b/chromium/content/browser/loader/test_resource_handler.cc
@@ -147,7 +147,6 @@ void TestResourceHandler::OnWillRead(
int* buf_size,
std::unique_ptr<ResourceController> controller) {
EXPECT_FALSE(canceled_);
- EXPECT_FALSE(expect_on_data_downloaded_);
EXPECT_EQ(0, on_response_completed_called_);
// Only create a ScopedCallDepthTracker if not called re-entrantly, as
// OnWillRead may be called synchronously in response to a Resume(), but
@@ -182,7 +181,6 @@ void TestResourceHandler::OnReadCompleted(
int bytes_read,
std::unique_ptr<ResourceController> controller) {
EXPECT_FALSE(canceled_);
- EXPECT_FALSE(expect_on_data_downloaded_);
EXPECT_EQ(1, on_will_start_called_);
EXPECT_EQ(1, on_response_started_called_);
EXPECT_EQ(0, on_response_completed_called_);
@@ -225,7 +223,7 @@ void TestResourceHandler::OnResponseCompleted(
parent_read_buffer_size_ = nullptr;
EXPECT_EQ(0, on_response_completed_called_);
- if (status.is_success() && !expect_on_data_downloaded_ && expect_eof_read_)
+ if (status.is_success() && expect_eof_read_)
EXPECT_EQ(1, on_read_eof_called_);
++on_response_completed_called_;
@@ -248,15 +246,6 @@ void TestResourceHandler::OnResponseCompleted(
controller->Resume();
}
-void TestResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- EXPECT_TRUE(expect_on_data_downloaded_);
- EXPECT_EQ(1, on_will_start_called_);
- EXPECT_EQ(1, on_response_started_called_);
- EXPECT_EQ(0, on_response_completed_called_);
-
- total_bytes_downloaded_ += bytes_downloaded;
-}
-
void TestResourceHandler::Resume() {
ScopedCallDepthTracker call_depth_tracker(&call_depth_);
diff --git a/chromium/content/browser/loader/test_resource_handler.h b/chromium/content/browser/loader/test_resource_handler.h
index f109fce1a6d..d99196a1128 100644
--- a/chromium/content/browser/loader/test_resource_handler.h
+++ b/chromium/content/browser/loader/test_resource_handler.h
@@ -63,7 +63,6 @@ class TestResourceHandler : public ResourceHandler {
void OnResponseCompleted(
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- void OnDataDownloaded(int bytes_downloaded) override;
void Resume();
void CancelWithError(net::Error error_code);
@@ -122,12 +121,6 @@ class TestResourceHandler : public ResourceHandler {
defer_on_response_completed_ = defer_on_response_completed;
}
- // Set if OnDataDownloaded calls are expected instead of
- // OnWillRead/OnReadCompleted.
- void set_expect_on_data_downloaded(bool expect_on_data_downloaded) {
- expect_on_data_downloaded_ = expect_on_data_downloaded;
- }
-
// Sets whether to expect a final 0-byte read on success. Defaults to true.
void set_expect_eof_read(bool expect_eof_read) {
expect_eof_read_ = expect_eof_read;
@@ -154,8 +147,6 @@ class TestResourceHandler : public ResourceHandler {
return resource_response_.get();
};
- int total_bytes_downloaded() const { return total_bytes_downloaded_; }
-
const std::string& body() const { return body_; }
net::URLRequestStatus final_status() const { return final_status_; }
@@ -197,8 +188,6 @@ class TestResourceHandler : public ResourceHandler {
bool defer_on_read_eof_ = false;
bool defer_on_response_completed_ = false;
- bool expect_on_data_downloaded_ = false;
-
bool expect_eof_read_ = true;
int on_will_start_called_ = 0;
@@ -211,7 +200,6 @@ class TestResourceHandler : public ResourceHandler {
GURL start_url_;
scoped_refptr<network::ResourceResponse> resource_response_;
- int total_bytes_downloaded_ = 0;
std::string body_;
net::URLRequestStatus final_status_ =
net::URLRequestStatus::FromError(net::ERR_UNEXPECTED);
diff --git a/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc b/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
index e6ede61511d..9385955b5c5 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
+++ b/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
@@ -203,8 +203,8 @@ TEST_P(URLLoaderFactoryImplTest, GetResponse) {
client.completion_status().encoded_data_length);
EXPECT_EQ(static_cast<int64_t>(expected.size()),
client.completion_status().encoded_body_length);
- // OnTransferSizeUpdated is not dispatched as report_raw_headers is not set.
- EXPECT_EQ(0, client.body_transfer_size());
+ EXPECT_EQ(static_cast<int64_t>(expected.size()), client.body_transfer_size());
+ EXPECT_GT(client.body_transfer_size(), 0);
EXPECT_GT(client.response_head().encoded_data_length, 0);
EXPECT_GT(client.completion_status().encoded_data_length, 0);
}
@@ -322,133 +322,6 @@ TEST_P(URLLoaderFactoryImplTest, ShouldNotRequestURL) {
EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
}
-TEST_P(URLLoaderFactoryImplTest, DownloadToFile) {
- constexpr int32_t kRoutingId = 1;
- constexpr int32_t kRequestId = 2;
-
- network::mojom::URLLoaderPtr loader;
- base::FilePath root;
- base::PathService::Get(DIR_TEST_DATA, &root);
- net::URLRequestMockHTTPJob::AddUrlHandlers(root);
-
- network::ResourceRequest request;
- network::TestURLLoaderClient client;
- request.url = net::URLRequestMockHTTPJob::GetMockUrl("hello.html");
- request.method = "GET";
- request.resource_type = RESOURCE_TYPE_XHR;
- request.download_to_file = true;
- request.request_initiator = url::Origin::Create(request.url);
- factory_->CreateLoaderAndStart(
- mojo::MakeRequest(&loader), kRoutingId, kRequestId, 0, request,
- client.CreateInterfacePtr(),
- net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
- ASSERT_FALSE(client.has_received_response());
- ASSERT_FALSE(client.has_data_downloaded());
- ASSERT_FALSE(client.has_received_completion());
-
- client.RunUntilResponseReceived();
-
- net::URLRequest* url_request =
- rdh_.GetURLRequest(GlobalRequestID(kChildId, kRequestId));
- ASSERT_TRUE(url_request);
- ResourceRequestInfoImpl* request_info =
- ResourceRequestInfoImpl::ForRequest(url_request);
- ASSERT_TRUE(request_info);
- EXPECT_EQ(kChildId, request_info->GetChildID());
- EXPECT_EQ(kRoutingId, request_info->GetRouteID());
- EXPECT_EQ(kRequestId, request_info->GetRequestID());
-
- ASSERT_FALSE(client.has_received_completion());
-
- client.RunUntilComplete();
- ASSERT_TRUE(client.has_data_downloaded());
- ASSERT_TRUE(client.has_received_completion());
-
- EXPECT_EQ(200, client.response_head().headers->response_code());
- std::string content_type;
- client.response_head().headers->GetNormalizedHeader("content-type",
- &content_type);
- EXPECT_EQ("text/html", content_type);
- EXPECT_EQ(0, client.completion_status().error_code);
-
- std::string contents;
- base::ReadFileToString(client.response_head().download_file_path, &contents);
-
- EXPECT_EQ(static_cast<int64_t>(contents.size()),
- client.download_data_length());
- EXPECT_EQ(static_cast<int64_t>(contents.size()),
- client.encoded_download_data_length());
-
- std::string expected;
- base::ReadFileToString(
- root.Append(base::FilePath(FILE_PATH_LITERAL("hello.html"))), &expected);
- EXPECT_EQ(expected, contents);
- EXPECT_EQ(static_cast<int64_t>(expected.size()) +
- client.response_head().encoded_data_length,
- client.completion_status().encoded_data_length);
- EXPECT_EQ(static_cast<int64_t>(expected.size()),
- client.completion_status().encoded_body_length);
-}
-
-TEST_P(URLLoaderFactoryImplTest, DownloadToFileFailure) {
- constexpr int32_t kRoutingId = 1;
- constexpr int32_t kRequestId = 2;
-
- network::mojom::URLLoaderPtr loader;
- base::FilePath root;
- base::PathService::Get(DIR_TEST_DATA, &root);
- net::URLRequestSlowDownloadJob::AddUrlHandler();
-
- network::ResourceRequest request;
- network::TestURLLoaderClient client;
- request.url = GURL(net::URLRequestSlowDownloadJob::kKnownSizeUrl);
- request.method = "GET";
- request.resource_type = RESOURCE_TYPE_XHR;
- request.download_to_file = true;
- request.request_initiator = url::Origin::Create(request.url);
- factory_->CreateLoaderAndStart(
- mojo::MakeRequest(&loader), kRoutingId, kRequestId, 0, request,
- client.CreateInterfacePtr(),
- net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
- ASSERT_FALSE(client.has_received_response());
- ASSERT_FALSE(client.has_data_downloaded());
- ASSERT_FALSE(client.has_received_completion());
-
- client.RunUntilResponseReceived();
-
- net::URLRequest* url_request =
- rdh_.GetURLRequest(GlobalRequestID(kChildId, kRequestId));
- ASSERT_TRUE(url_request);
- ResourceRequestInfoImpl* request_info =
- ResourceRequestInfoImpl::ForRequest(url_request);
- ASSERT_TRUE(request_info);
- EXPECT_EQ(kChildId, request_info->GetChildID());
- EXPECT_EQ(kRoutingId, request_info->GetRouteID());
- EXPECT_EQ(kRequestId, request_info->GetRequestID());
-
- ASSERT_FALSE(client.has_received_completion());
-
- client.RunUntilDataDownloaded();
- ASSERT_TRUE(client.has_data_downloaded());
- ASSERT_FALSE(client.has_received_completion());
- EXPECT_LT(0, client.download_data_length());
- EXPECT_GE(
- static_cast<int64_t>(net::URLRequestSlowDownloadJob::kFirstDownloadSize),
- client.download_data_length());
- EXPECT_LT(0, client.encoded_download_data_length());
- EXPECT_GE(
- static_cast<int64_t>(net::URLRequestSlowDownloadJob::kFirstDownloadSize),
- client.encoded_download_data_length());
-
- url_request->Cancel();
- client.RunUntilComplete();
-
- ASSERT_TRUE(client.has_received_completion());
-
- EXPECT_EQ(200, client.response_head().headers->response_code());
- EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
-}
-
TEST_P(URLLoaderFactoryImplTest, OnTransferSizeUpdated) {
constexpr int32_t kRoutingId = 81;
constexpr int32_t kRequestId = 28;
diff --git a/chromium/content/browser/loader/wake_lock_resource_throttle.cc b/chromium/content/browser/loader/wake_lock_resource_throttle.cc
deleted file mode 100644
index 9ba1bd0da64..00000000000
--- a/chromium/content/browser/loader/wake_lock_resource_throttle.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2013 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/wake_lock_resource_throttle.h"
-
-#include "content/browser/service_manager/service_manager_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/device/public/mojom/constants.mojom.h"
-#include "services/device/public/mojom/wake_lock_provider.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-namespace content {
-
-namespace {
-
-const int kWakeLockDelaySeconds = 30;
-
-} // namespace
-
-WakeLockResourceThrottle::WakeLockResourceThrottle(const std::string& host)
- : host_(host) {}
-
-WakeLockResourceThrottle::~WakeLockResourceThrottle() {}
-
-void WakeLockResourceThrottle::WillStartRequest(bool* defer) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Delay wake lock request to dismiss small requests.
- timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kWakeLockDelaySeconds),
- this, &WakeLockResourceThrottle::RequestWakeLock);
-}
-
-void WakeLockResourceThrottle::WillProcessResponse(bool* defer) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Cancel wake lock after request finishes.
- if (wake_lock_)
- wake_lock_->CancelWakeLock();
-
- timer_.Stop();
-}
-
-const char* WakeLockResourceThrottle::GetNameForLogging() const {
- return "WakeLockResourceThrottle";
-}
-
-void WakeLockResourceThrottle::RequestWakeLock() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!wake_lock_);
-
- service_manager::Connector* connector =
- ServiceManagerContext::GetConnectorForIOThread();
- // |connector| might be nullptr in some testing contexts, in which the
- // service manager connection isn't initialized.
- if (connector) {
- device::mojom::WakeLockProviderPtr wake_lock_provider;
- connector->BindInterface(device::mojom::kServiceName,
- mojo::MakeRequest(&wake_lock_provider));
- wake_lock_provider->GetWakeLockWithoutContext(
- device::mojom::WakeLockType::kPreventAppSuspension,
- device::mojom::WakeLockReason::kOther, "Uploading data to " + host_,
- mojo::MakeRequest(&wake_lock_));
-
- wake_lock_->RequestWakeLock();
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/wake_lock_resource_throttle.h b/chromium/content/browser/loader/wake_lock_resource_throttle.h
deleted file mode 100644
index 986b566aa86..00000000000
--- a/chromium/content/browser/loader/wake_lock_resource_throttle.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2013 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_WAKE_LOCK_RESOURCE_THROTTLE_H_
-#define CONTENT_BROWSER_LOADER_WAKE_LOCK_RESOURCE_THROTTLE_H_
-
-#include <memory>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/timer/timer.h"
-#include "content/public/browser/resource_throttle.h"
-#include "services/device/public/mojom/wake_lock.mojom.h"
-
-namespace content {
-
-// This ResourceThrottle holds wake lock until large upload request finishes.
-class WakeLockResourceThrottle : public ResourceThrottle {
- public:
- WakeLockResourceThrottle(const std::string& host);
- ~WakeLockResourceThrottle() override;
-
- // ResourceThrottle overrides:
- void WillStartRequest(bool* defer) override;
- void WillProcessResponse(bool* defer) override;
- const char* GetNameForLogging() const override;
-
- private:
- void RequestWakeLock();
-
- const std::string host_;
- base::OneShotTimer timer_;
-
- // Destruction of wake_lock_ will trigger
- // WakeLock::OnConnectionError on the service side, so there is no
- // need to call CancelWakeLock() in the destructor.
- device::mojom::WakeLockPtr wake_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(WakeLockResourceThrottle);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_WAKE_LOCK_RESOURCE_THROTTLE_H_