diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/content/browser/net | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/content/browser/net')
5 files changed, 449 insertions, 8 deletions
diff --git a/chromium/content/browser/net/cookie_store_factory.cc b/chromium/content/browser/net/cookie_store_factory.cc index 1f23008c71b..c4743b67066 100644 --- a/chromium/content/browser/net/cookie_store_factory.cc +++ b/chromium/content/browser/net/cookie_store_factory.cc @@ -10,7 +10,6 @@ #include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/sequenced_task_runner.h" -#include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -57,8 +56,7 @@ std::unique_ptr<net::CookieStore> CreateCookieStore( config.background_task_runner; if (!client_task_runner.get()) { - client_task_runner = - base::CreateSingleThreadTaskRunner({BrowserThread::IO}); + client_task_runner = GetIOThreadTaskRunner({}); } if (!background_task_runner.get()) { diff --git a/chromium/content/browser/net/cross_origin_opener_policy_reporter.cc b/chromium/content/browser/net/cross_origin_opener_policy_reporter.cc new file mode 100644 index 00000000000..59b0278c737 --- /dev/null +++ b/chromium/content/browser/net/cross_origin_opener_policy_reporter.cc @@ -0,0 +1,190 @@ +// Copyright 2020 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/net/cross_origin_opener_policy_reporter.h" + +#include "base/values.h" +#include "content/browser/frame_host/frame_tree_node.h" +#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/public/browser/storage_partition.h" +#include "services/network/public/mojom/network_context.mojom.h" + +namespace content { + +namespace { + +constexpr char kUnsafeNone[] = "unsafe-none"; +constexpr char kSameOrigin[] = "same-origin"; +constexpr char kSameOriginPlusCoep[] = "same-origin-plus-coep"; +constexpr char kSameOriginAllowPopups[] = "same-origin-allow-popups"; + +constexpr char kDisposition[] = "disposition"; +constexpr char kDispositionEnforce[] = "enforce"; +constexpr char kDispositionReporting[] = "reporting"; +constexpr char kDocumentURI[] = "document-uri"; +constexpr char kNavigationURI[] = "navigation-uri"; +constexpr char kViolationType[] = "violation-type"; +constexpr char kViolationTypeFromDocument[] = "navigation-from-document"; +constexpr char kViolationTypeToDocument[] = "navigation-to-document"; +constexpr char kEffectivePolicy[] = "effective-policy"; + +std::string CoopValueToString( + network::mojom::CrossOriginOpenerPolicyValue coop_value, + network::mojom::CrossOriginEmbedderPolicyValue coep_value, + network::mojom::CrossOriginEmbedderPolicyValue report_only_coep_value) { + switch (coop_value) { + case network::mojom::CrossOriginOpenerPolicyValue::kUnsafeNone: + return kUnsafeNone; + case network::mojom::CrossOriginOpenerPolicyValue::kSameOrigin: + if ((coep_value == + network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp) || + (report_only_coep_value == + network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp)) { + return kSameOriginPlusCoep; + } + return kSameOrigin; + case network::mojom::CrossOriginOpenerPolicyValue::kSameOriginAllowPopups: + return kSameOriginAllowPopups; + } +} + +RenderFrameHostImpl* GetSourceRfhForCoopReporting( + RenderFrameHostImpl* current_rfh) { + CHECK(current_rfh); + + // If this is a fresh popup we would consider the source RFH to be + // our opener. + // TODO(arthursonzogni): There seems to be no guarantee that opener() is + // always set, do we need to be more cautious here? + if (!current_rfh->has_committed_any_navigation()) + return current_rfh->frame_tree_node()->opener()->current_frame_host(); + + // Otherwise this is simply the current RFH. + return current_rfh; +} + +} // namespace + +CrossOriginOpenerPolicyReporter::CrossOriginOpenerPolicyReporter( + StoragePartition* storage_partition, + RenderFrameHostImpl* current_rfh, + const GURL& context_url, + const network::CrossOriginOpenerPolicy& coop, + const network::CrossOriginEmbedderPolicy& coep) + : storage_partition_(storage_partition), + context_url_(context_url), + coop_(coop), + coep_(coep) { + DCHECK(storage_partition_); + RenderFrameHostImpl* source_rfh = GetSourceRfhForCoopReporting(current_rfh); + source_url_ = source_rfh->GetLastCommittedURL(); + source_routing_id_ = source_rfh->GetGlobalFrameRoutingId(); +} + +CrossOriginOpenerPolicyReporter::CrossOriginOpenerPolicyReporter( + StoragePartition* storage_partition, + const GURL& source_url, + const GlobalFrameRoutingId source_routing_id, + const GURL& context_url, + const network::CrossOriginOpenerPolicy& coop, + const network::CrossOriginEmbedderPolicy& coep) + : storage_partition_(storage_partition), + source_url_(source_url), + source_routing_id_(source_routing_id), + context_url_(context_url), + coop_(coop), + coep_(coep) { + DCHECK(storage_partition_); +} + +CrossOriginOpenerPolicyReporter::~CrossOriginOpenerPolicyReporter() = default; + +void CrossOriginOpenerPolicyReporter::QueueOpenerBreakageReport( + const GURL& other_url, + bool is_reported_from_document, + bool is_report_only) { + const base::Optional<std::string>& endpoint = + is_report_only ? coop_.report_only_reporting_endpoint + : coop_.reporting_endpoint; + DCHECK(endpoint); + + url::Replacements<char> replacements; + replacements.ClearUsername(); + replacements.ClearPassword(); + std::string sanitized_context_url = + context_url_.ReplaceComponents(replacements).spec(); + std::string sanitized_other_url = + other_url.ReplaceComponents(replacements).spec(); + base::DictionaryValue body; + body.SetString(kDisposition, + is_report_only ? kDispositionReporting : kDispositionEnforce); + body.SetString(kDocumentURI, sanitized_context_url); + body.SetString(kNavigationURI, sanitized_other_url); + body.SetString(kViolationType, is_reported_from_document + ? kViolationTypeFromDocument + : kViolationTypeToDocument); + body.SetString( + kEffectivePolicy, + CoopValueToString(is_report_only ? coop_.report_only_value : coop_.value, + coep_.value, coep_.report_only_value)); + storage_partition_->GetNetworkContext()->QueueReport( + "coop", *endpoint, context_url_, /*user_agent=*/base::nullopt, + std::move(body)); +} + +void CrossOriginOpenerPolicyReporter::Clone( + mojo::PendingReceiver<network::mojom::CrossOriginOpenerPolicyReporter> + receiver) { + receiver_set_.Add(this, std::move(receiver)); +} + +GURL CrossOriginOpenerPolicyReporter::GetPreviousDocumentUrlForReporting( + const std::vector<GURL>& redirect_chain, + const GURL& referrer_url) { + // If the current document and all its redirect chain are same-origin with + // the previous document, this is the previous document URL. + auto source_origin = url::Origin::Create(source_url_); + bool is_redirect_chain_same_origin = true; + for (auto& redirect_url : redirect_chain) { + auto redirect_origin = url::Origin::Create(redirect_url); + if (!redirect_origin.IsSameOriginWith(source_origin)) { + is_redirect_chain_same_origin = false; + break; + } + } + if (is_redirect_chain_same_origin) + return source_url_; + + // Otherwise, it's the referrer of the navigation. + return referrer_url; +} + +GURL CrossOriginOpenerPolicyReporter::GetNextDocumentUrlForReporting( + const std::vector<GURL>& redirect_chain, + const GlobalFrameRoutingId& initiator_routing_id) { + const url::Origin& source_origin = url::Origin::Create(source_url_); + + // If the next document and all its redirect chain are same-origin with the + // current document, this is the next document URL. + bool is_redirect_chain_same_origin = true; + for (auto& redirect_url : redirect_chain) { + auto redirect_origin = url::Origin::Create(redirect_url); + if (!redirect_origin.IsSameOriginWith(source_origin)) { + is_redirect_chain_same_origin = false; + break; + } + } + if (is_redirect_chain_same_origin) + return redirect_chain[redirect_chain.size() - 1]; + + // If the current document is the initiator of the navigation, then it's the + // initial navigation URL. + if (source_routing_id_ == initiator_routing_id) + return redirect_chain[0]; + + // Otherwise, it's the empty URL. + return GURL(); +} + +} // namespace content diff --git a/chromium/content/browser/net/cross_origin_opener_policy_reporter.h b/chromium/content/browser/net/cross_origin_opener_policy_reporter.h new file mode 100644 index 00000000000..db91781e89c --- /dev/null +++ b/chromium/content/browser/net/cross_origin_opener_policy_reporter.h @@ -0,0 +1,95 @@ +// Copyright 2020 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_NET_CROSS_ORIGIN_OPENER_POLICY_REPORTER_H_ +#define CONTENT_BROWSER_NET_CROSS_ORIGIN_OPENER_POLICY_REPORTER_H_ + +#include <string> + +#include "base/optional.h" +#include "content/common/content_export.h" +#include "content/public/browser/global_routing_id.h" +#include "mojo/public/cpp/bindings/receiver_set.h" +#include "services/network/public/mojom/cross_origin_embedder_policy.mojom.h" +#include "services/network/public/mojom/cross_origin_opener_policy.mojom.h" +#include "url/gurl.h" + +namespace content { + +class StoragePartition; +class RenderFrameHostImpl; + +// Used to report (potential) COOP breakages. +// A CrossOriginOpenerPolicyReporter lives in the browser process and is either +// held by the NavigationRequest during navigation or by the RenderFrameHostImpl +// after the document has committed. +// To make calls from other processes, create a mojo endpoint using Clone and +// pass the receiver to other processes. +// Any functions other than the destructor must not be called after the +// associated StoragePartition is destructed. +class CONTENT_EXPORT CrossOriginOpenerPolicyReporter final + : public network::mojom::CrossOriginOpenerPolicyReporter { + public: + CrossOriginOpenerPolicyReporter( + StoragePartition* storage_partition, + RenderFrameHostImpl* current_frame_host, + const GURL& context_url, + const network::CrossOriginOpenerPolicy& coop, + const network::CrossOriginEmbedderPolicy& coep); + ~CrossOriginOpenerPolicyReporter() override; + CrossOriginOpenerPolicyReporter(const CrossOriginOpenerPolicyReporter&) = + delete; + CrossOriginOpenerPolicyReporter& operator=( + const CrossOriginOpenerPolicyReporter&) = delete; + + // network::mojom::CrossOriginOpenerPolicyReporter implementation. + void QueueOpenerBreakageReport(const GURL& other_url, + bool is_reported_from_document, + bool is_report_only) override; + + // Returns the "previous" URL that is safe to expose. + // Reference, "Next document URL for reporting" section: + // https://github.com/camillelamy/explainers/blob/master/coop_reporting.md#safe-urls-for-reporting + GURL GetPreviousDocumentUrlForReporting( + const std::vector<GURL>& redirect_chain, + const GURL& referrer_url); + + // Returns the "next" URL that is safe to expose. + // Reference, "Next document URL for reporting" section: + // https://github.com/camillelamy/explainers/blob/master/coop_reporting.md#safe-urls-for-reporting + GURL GetNextDocumentUrlForReporting( + const std::vector<GURL>& redirect_chain, + const GlobalFrameRoutingId& initiator_routing_id); + + void Clone( + mojo::PendingReceiver<network::mojom::CrossOriginOpenerPolicyReporter> + receiver) override; + + private: + friend class CrossOriginOpenerPolicyReporterTest; + + // Used in unit_tests that do not have access to a RenderFrameHost. + CrossOriginOpenerPolicyReporter( + StoragePartition* storage_partition, + const GURL& source_url, + const GlobalFrameRoutingId source_routing_id, + const GURL& context_url, + const network::CrossOriginOpenerPolicy& coop, + const network::CrossOriginEmbedderPolicy& coep); + + // See the class comment. + StoragePartition* const storage_partition_; + GURL source_url_; + GlobalFrameRoutingId source_routing_id_; + const GURL context_url_; + network::CrossOriginOpenerPolicy coop_; + network::CrossOriginEmbedderPolicy coep_; + + mojo::ReceiverSet<network::mojom::CrossOriginOpenerPolicyReporter> + receiver_set_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_NET_CROSS_ORIGIN_OPENER_POLICY_REPORTER_H_ diff --git a/chromium/content/browser/net/cross_origin_opener_policy_reporter_unittest.cc b/chromium/content/browser/net/cross_origin_opener_policy_reporter_unittest.cc new file mode 100644 index 00000000000..b4e9bb3f13e --- /dev/null +++ b/chromium/content/browser/net/cross_origin_opener_policy_reporter_unittest.cc @@ -0,0 +1,159 @@ +// Copyright 2020 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/net/cross_origin_opener_policy_reporter.h" + +#include <memory> +#include <vector> + +#include "base/test/task_environment.h" +#include "base/values.h" +#include "content/public/test/test_storage_partition.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "services/network/test/test_network_context.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { +namespace { + +class TestNetworkContext : public network::TestNetworkContext { + public: + struct Report { + Report(const std::string& type, + const std::string& group, + const GURL& url, + base::Value body) + : type(type), group(group), url(url), body(std::move(body)) {} + + std::string type; + std::string group; + GURL url; + base::Value body; + }; + void QueueReport(const std::string& type, + const std::string& group, + const GURL& url, + const base::Optional<std::string>& user_agent, + base::Value body) override { + DCHECK(!user_agent); + reports_.emplace_back(Report(type, group, url, std::move(body))); + } + + const std::vector<Report>& reports() const { return reports_; } + + private: + std::vector<Report> reports_; +}; + +} // namespace + +class CrossOriginOpenerPolicyReporterTest : public testing::Test { + public: + using Report = TestNetworkContext::Report; + CrossOriginOpenerPolicyReporterTest() { + storage_partition_.set_network_context(&network_context_); + coop_.value = network::mojom::CrossOriginOpenerPolicyValue::kSameOrigin; + coep_.value = network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + coop_.reporting_endpoint = "e1"; + context_url_ = GURL("https://www1.example.com/x"); + } + + StoragePartition* storage_partition() { return &storage_partition_; } + const TestNetworkContext& network_context() const { return network_context_; } + const GURL& context_url() const { return context_url_; } + const network::CrossOriginOpenerPolicy& coop() const { return coop_; } + const network::CrossOriginEmbedderPolicy& coep() const { return coep_; } + + protected: + std::unique_ptr<CrossOriginOpenerPolicyReporter> GetReporter() { + return std::unique_ptr<CrossOriginOpenerPolicyReporter>( + new CrossOriginOpenerPolicyReporter(storage_partition(), GURL(), + GlobalFrameRoutingId(123, 456), + context_url(), coop(), coep())); + } + + private: + base::test::TaskEnvironment task_environment_; + TestNetworkContext network_context_; + TestStoragePartition storage_partition_; + GURL context_url_; + network::CrossOriginOpenerPolicy coop_; + network::CrossOriginEmbedderPolicy coep_; +}; + +TEST_F(CrossOriginOpenerPolicyReporterTest, Basic) { + auto reporter = GetReporter(); + + reporter->QueueOpenerBreakageReport( + GURL("https://www1.example.com/y#foo?bar=baz"), false, false); + reporter->QueueOpenerBreakageReport(GURL("http://www2.example.com:41/z"), + true, false); + + ASSERT_EQ(2u, network_context().reports().size()); + const Report& r1 = network_context().reports()[0]; + const Report& r2 = network_context().reports()[1]; + + EXPECT_EQ(r1.type, "coop"); + EXPECT_EQ(r1.body.FindKey("disposition")->GetString(), "enforce"); + EXPECT_EQ(r1.body.FindKey("document-uri")->GetString(), context_url()); + EXPECT_EQ(r1.body.FindKey("navigation-uri")->GetString(), + "https://www1.example.com/y#foo?bar=baz"); + EXPECT_EQ(r1.body.FindKey("violation-type")->GetString(), + "navigation-to-document"); + EXPECT_EQ(r1.body.FindKey("effective-policy")->GetString(), + "same-origin-plus-coep"); + + EXPECT_EQ(r2.type, "coop"); + EXPECT_EQ(r2.body.FindKey("disposition")->GetString(), "enforce"); + EXPECT_EQ(r2.body.FindKey("document-uri")->GetString(), context_url()); + EXPECT_EQ(r2.body.FindKey("navigation-uri")->GetString(), + "http://www2.example.com:41/z"); + EXPECT_EQ(r2.body.FindKey("violation-type")->GetString(), + "navigation-from-document"); + EXPECT_EQ(r2.body.FindKey("effective-policy")->GetString(), + "same-origin-plus-coep"); +} + +TEST_F(CrossOriginOpenerPolicyReporterTest, UserAndPassSanitization) { + auto reporter = GetReporter(); + + reporter->QueueOpenerBreakageReport(GURL("https://u:p@www2.example.com/x"), + false, false); + + ASSERT_EQ(1u, network_context().reports().size()); + const Report& r1 = network_context().reports()[0]; + + EXPECT_EQ(r1.type, "coop"); + EXPECT_EQ(r1.body.FindKey("document-uri")->GetString(), + "https://www1.example.com/x"); + EXPECT_EQ(r1.body.FindKey("navigation-uri")->GetString(), + "https://www2.example.com/x"); +} + +TEST_F(CrossOriginOpenerPolicyReporterTest, Clone) { + auto reporter = GetReporter(); + + mojo::Remote<network::mojom::CrossOriginOpenerPolicyReporter> remote; + reporter->Clone(remote.BindNewPipeAndPassReceiver()); + + remote->QueueOpenerBreakageReport(GURL("https://www1.example.com/y"), false, + false); + + remote.FlushForTesting(); + + ASSERT_EQ(1u, network_context().reports().size()); + const Report& r1 = network_context().reports()[0]; + + EXPECT_EQ(r1.type, "coop"); + EXPECT_EQ(r1.body.FindKey("disposition")->GetString(), "enforce"); + EXPECT_EQ(r1.body.FindKey("document-uri")->GetString(), context_url()); + EXPECT_EQ(r1.body.FindKey("navigation-uri")->GetString(), + "https://www1.example.com/y"); + EXPECT_EQ(r1.body.FindKey("violation-type")->GetString(), + "navigation-to-document"); + EXPECT_EQ(r1.body.FindKey("effective-policy")->GetString(), + "same-origin-plus-coep"); +} + +} // namespace content diff --git a/chromium/content/browser/net/network_errors_listing_ui.cc b/chromium/content/browser/net/network_errors_listing_ui.cc index b892365db3e..c34768990ae 100644 --- a/chromium/content/browser/net/network_errors_listing_ui.cc +++ b/chromium/content/browser/net/network_errors_listing_ui.cc @@ -29,13 +29,12 @@ namespace content { namespace { std::unique_ptr<base::ListValue> GetNetworkErrorData() { - std::unique_ptr<base::DictionaryValue> error_codes = net::GetNetConstants(); + base::Value error_codes = net::GetNetConstants(); const base::DictionaryValue* net_error_codes_dict = nullptr; - for (base::DictionaryValue::Iterator itr(*error_codes); !itr.IsAtEnd(); - itr.Advance()) { - if (itr.key() == kNetworkErrorKey) { - itr.value().GetAsDictionary(&net_error_codes_dict); + for (const auto& item : error_codes.DictItems()) { + if (item.first == kNetworkErrorKey) { + item.second.GetAsDictionary(&net_error_codes_dict); break; } } |