diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-03-12 09:13:00 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-03-16 09:58:26 +0000 |
commit | 03561cae90f1d99b5c54b1ef3be69f10e882b25e (patch) | |
tree | cc5f0958e823c044e7ae51cc0117fe51432abe5e /chromium/services | |
parent | fa98118a45f7e169f8846086dc2c22c49a8ba310 (diff) | |
download | qtwebengine-chromium-03561cae90f1d99b5c54b1ef3be69f10e882b25e.tar.gz |
BASELINE: Update Chromium to 88.0.4324.208
Change-Id: I3ae87d23e4eff4b4a469685658740a213600c667
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/services')
573 files changed, 11481 insertions, 5754 deletions
diff --git a/chromium/services/BUILD.gn b/chromium/services/BUILD.gn index 5eed24831da..9027402467c 100644 --- a/chromium/services/BUILD.gn +++ b/chromium/services/BUILD.gn @@ -25,7 +25,6 @@ test("services_unittests") { deps = [ "//services/cert_verifier:tests", "//services/cert_verifier/cert_net_url_loader:tests", - "//services/content:tests", "//services/metrics/public/cpp:tests", "//services/network:tests", "//services/network/public/cpp:tests", @@ -152,6 +151,7 @@ if (is_android) { "//skia/public/mojom:mojom_java", "//third_party/android_deps:androidx_test_monitor_java", "//third_party/android_deps:androidx_test_runner_java", + "//third_party/android_deps:chromium_play_services_availability_java", "//third_party/android_support_test_runner:runner_java", "//third_party/junit", "//ui/gfx/geometry/mojom:mojom_java", diff --git a/chromium/services/DIR_METADATA b/chromium/services/DIR_METADATA new file mode 100644 index 00000000000..52d36447a86 --- /dev/null +++ b/chromium/services/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Services" +}
\ No newline at end of file diff --git a/chromium/services/OWNERS b/chromium/services/OWNERS index 1bcc466452e..aa84af86091 100644 --- a/chromium/services/OWNERS +++ b/chromium/services/OWNERS @@ -1,5 +1,4 @@ blundell@chromium.org jam@chromium.org rockot@google.com -sky@chromium.org -# COMPONENT: Internals>Services +sky@chromium.org
\ No newline at end of file diff --git a/chromium/services/audio/BUILD.gn b/chromium/services/audio/BUILD.gn index 84b197a67f2..e8777a36cd3 100644 --- a/chromium/services/audio/BUILD.gn +++ b/chromium/services/audio/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/chromecast_build.gni") +import("//build/config/chromeos/ui_mode.gni") import("//testing/test.gni") source_set("audio") { @@ -64,6 +65,7 @@ source_set("audio") { deps = [ ":testing_api_support", "//build:chromecast_buildflags", + "//build:chromeos_buildflags", ] public_deps = [ @@ -151,6 +153,7 @@ source_set("tests") { deps = [ ":audio", "//base/test:test_support", + "//build:chromeos_buildflags", "//media:test_support", "//services/audio/public/cpp", "//services/audio/public/cpp:test_support", @@ -159,7 +162,7 @@ source_set("tests") { "//testing/gtest", ] - if (is_chromeos || is_chromecast) { + if (is_ash || is_chromecast) { sources += [ "public/cpp/sounds/audio_stream_handler_unittest.cc", "public/cpp/sounds/sounds_manager_unittest.cc", diff --git a/chromium/services/audio/DIR_METADATA b/chromium/services/audio/DIR_METADATA new file mode 100644 index 00000000000..99031e09f7e --- /dev/null +++ b/chromium/services/audio/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Media>Audio" +}
\ No newline at end of file diff --git a/chromium/services/audio/OWNERS b/chromium/services/audio/OWNERS index dfd776de26d..0d82a02f86f 100644 --- a/chromium/services/audio/OWNERS +++ b/chromium/services/audio/OWNERS @@ -3,5 +3,3 @@ dalecurtis@chromium.org miu@chromium.org per-file audio_sandbox_hook_linux.*=file://sandbox/linux/OWNERS - -# COMPONENT: Internals>Media>Audio diff --git a/chromium/services/audio/input_stream.cc b/chromium/services/audio/input_stream.cc index 8d852cb8df0..ee0cfd5c0d6 100644 --- a/chromium/services/audio/input_stream.cc +++ b/chromium/services/audio/input_stream.cc @@ -8,7 +8,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/strings/strcat.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" diff --git a/chromium/services/audio/input_stream_unittest.cc b/chromium/services/audio/input_stream_unittest.cc index 6f080d8c359..0e065d1897e 100644 --- a/chromium/services/audio/input_stream_unittest.cc +++ b/chromium/services/audio/input_stream_unittest.cc @@ -9,7 +9,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/test/task_environment.h" #include "media/audio/audio_io.h" diff --git a/chromium/services/audio/output_controller.cc b/chromium/services/audio/output_controller.cc index 3a84f463900..3992158ac21 100644 --- a/chromium/services/audio/output_controller.cc +++ b/chromium/services/audio/output_controller.cc @@ -12,7 +12,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" diff --git a/chromium/services/audio/output_controller_unittest.cc b/chromium/services/audio/output_controller_unittest.cc index a9b81c3e0e6..e47f8cb0bfc 100644 --- a/chromium/services/audio/output_controller_unittest.cc +++ b/chromium/services/audio/output_controller_unittest.cc @@ -11,7 +11,6 @@ #include "base/barrier_closure.h" #include "base/bind.h" -#include "base/bind_helpers.h" #include "base/callback_helpers.h" #include "base/check.h" #include "base/environment.h" diff --git a/chromium/services/audio/output_stream.cc b/chromium/services/audio/output_stream.cc index 716bfa05b18..4986bb13022 100644 --- a/chromium/services/audio/output_stream.cc +++ b/chromium/services/audio/output_stream.cc @@ -7,7 +7,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/strings/stringprintf.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/trace_event/trace_event.h" diff --git a/chromium/services/audio/output_stream_unittest.cc b/chromium/services/audio/output_stream_unittest.cc index 912fbddf9e5..95b5636cfd4 100644 --- a/chromium/services/audio/output_stream_unittest.cc +++ b/chromium/services/audio/output_stream_unittest.cc @@ -7,7 +7,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/test/mock_callback.h" #include "base/test/task_environment.h" #include "base/unguessable_token.h" diff --git a/chromium/services/audio/public/cpp/fake_system_info.cc b/chromium/services/audio/public/cpp/fake_system_info.cc index 1d7184bbc34..cbec5cabed0 100644 --- a/chromium/services/audio/public/cpp/fake_system_info.cc +++ b/chromium/services/audio/public/cpp/fake_system_info.cc @@ -5,7 +5,7 @@ #include "services/audio/public/cpp/fake_system_info.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "services/audio/service.h" namespace audio { diff --git a/chromium/services/audio/public/cpp/input_ipc.cc b/chromium/services/audio/public/cpp/input_ipc.cc index df06530eded..12f7ccf336f 100644 --- a/chromium/services/audio/public/cpp/input_ipc.cc +++ b/chromium/services/audio/public/cpp/input_ipc.cc @@ -7,7 +7,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/memory/read_only_shared_memory_region.h" #include "media/mojo/mojom/audio_data_pipe.mojom.h" #include "mojo/public/cpp/bindings/remote.h" diff --git a/chromium/services/audio/public/cpp/output_device_unittest.cc b/chromium/services/audio/public/cpp/output_device_unittest.cc index 1630b047df0..4463ba5953e 100644 --- a/chromium/services/audio/public/cpp/output_device_unittest.cc +++ b/chromium/services/audio/public/cpp/output_device_unittest.cc @@ -11,6 +11,7 @@ #include "base/run_loop.h" #include "base/test/task_environment.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "media/audio/audio_output_device.h" #include "media/base/audio_renderer_sink.h" #include "media/mojo/mojom/audio_data_pipe.mojom.h" @@ -203,7 +204,7 @@ TEST_F(AudioServiceOutputDeviceTest, CreatePlayPause) { } // Flaky on Linux Chromium OS ASan LSan (https://crbug.com/889845) -#if defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER) +#if BUILDFLAG(IS_ASH) && defined(ADDRESS_SANITIZER) #define MAYBE_VerifyDataFlow DISABLED_VerifyDataFlow #else #define MAYBE_VerifyDataFlow VerifyDataFlow diff --git a/chromium/services/audio/public/cpp/sounds/audio_stream_handler_unittest.cc b/chromium/services/audio/public/cpp/sounds/audio_stream_handler_unittest.cc index 493e552ea35..a0c04cd4786 100644 --- a/chromium/services/audio/public/cpp/sounds/audio_stream_handler_unittest.cc +++ b/chromium/services/audio/public/cpp/sounds/audio_stream_handler_unittest.cc @@ -8,7 +8,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/location.h" #include "base/run_loop.h" diff --git a/chromium/services/audio/public/cpp/sounds/sounds_manager_unittest.cc b/chromium/services/audio/public/cpp/sounds/sounds_manager_unittest.cc index d8aba0c3d63..c3253e5110e 100644 --- a/chromium/services/audio/public/cpp/sounds/sounds_manager_unittest.cc +++ b/chromium/services/audio/public/cpp/sounds/sounds_manager_unittest.cc @@ -6,7 +6,7 @@ #include <utility> #include <vector> -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/run_loop.h" #include "base/stl_util.h" diff --git a/chromium/services/audio/sync_reader.cc b/chromium/services/audio/sync_reader.cc index 3b7b5537f2c..d47cfdfa15b 100644 --- a/chromium/services/audio/sync_reader.cc +++ b/chromium/services/audio/sync_reader.cc @@ -17,6 +17,7 @@ #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "media/audio/audio_device_thread.h" #include "media/base/audio_parameters.h" #include "media/base/media_switches.h" @@ -54,7 +55,7 @@ SyncReader::SyncReader( renderer_callback_count_(0), renderer_missed_callback_count_(0), trailing_renderer_missed_callback_count_(0), -#if defined(OS_MAC) || defined(OS_CHROMEOS) +#if defined(OS_MAC) || BUILDFLAG(IS_ASH) maximum_wait_time_(params.GetBufferDuration() / 2), #else // TODO(dalecurtis): Investigate if we can reduce this on all platforms. diff --git a/chromium/services/cert_verifier/BUILD.gn b/chromium/services/cert_verifier/BUILD.gn index 65d56915897..32e9d54adb2 100644 --- a/chromium/services/cert_verifier/BUILD.gn +++ b/chromium/services/cert_verifier/BUILD.gn @@ -38,6 +38,7 @@ source_set("tests") { ":lib", "//base", "//base/test:test_support", + "//build:chromeos_buildflags", "//net", "//net:test_support", "//services/cert_verifier/cert_net_url_loader:cert_net_url_loader", diff --git a/chromium/services/cert_verifier/cert_verifier_service_factory_unittest.cc b/chromium/services/cert_verifier/cert_verifier_service_factory_unittest.cc index b19e5372239..d8dcc5cf3bc 100644 --- a/chromium/services/cert_verifier/cert_verifier_service_factory_unittest.cc +++ b/chromium/services/cert_verifier/cert_verifier_service_factory_unittest.cc @@ -13,7 +13,7 @@ #include "base/check_op.h" #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" diff --git a/chromium/services/cert_verifier/cert_verifier_service_unittest.cc b/chromium/services/cert_verifier/cert_verifier_service_unittest.cc index a4fca510610..446c96e42ca 100644 --- a/chromium/services/cert_verifier/cert_verifier_service_unittest.cc +++ b/chromium/services/cert_verifier/cert_verifier_service_unittest.cc @@ -9,13 +9,13 @@ #include <string> #include <tuple> -#include "base/bind_helpers.h" #include "base/callback_forward.h" +#include "base/callback_helpers.h" #include "base/memory/ptr_util.h" #include "base/memory/scoped_refptr.h" #include "base/no_destructor.h" #include "base/strings/string_number_conversions.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" diff --git a/chromium/services/cert_verifier/integration_tests/network_context_unittest.cc b/chromium/services/cert_verifier/integration_tests/network_context_unittest.cc index 98483552717..17988d8c738 100644 --- a/chromium/services/cert_verifier/integration_tests/network_context_unittest.cc +++ b/chromium/services/cert_verifier/integration_tests/network_context_unittest.cc @@ -135,7 +135,7 @@ std::unique_ptr<network::TestURLLoaderClient> FetchRequest( // NIK must be consistent with |site_for_cookies|. if (request.site_for_cookies.IsNull()) { params->isolation_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, + net::IsolationInfo::RequestType::kOther, url::Origin::Create(GURL("https://abc.invalid")), url::Origin::Create(GURL("https://xyz.invalid")), request.site_for_cookies); diff --git a/chromium/services/cert_verifier/integration_tests/network_service_unittest.cc b/chromium/services/cert_verifier/integration_tests/network_service_unittest.cc index 1ce0aa5c0aa..9b78d130d83 100644 --- a/chromium/services/cert_verifier/integration_tests/network_service_unittest.cc +++ b/chromium/services/cert_verifier/integration_tests/network_service_unittest.cc @@ -9,7 +9,7 @@ #include "base/run_loop.h" #include "base/sequenced_task_runner.h" #include "base/task/task_traits.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "build/build_config.h" diff --git a/chromium/services/content/BUILD.gn b/chromium/services/content/BUILD.gn deleted file mode 100644 index f61ba7358e0..00000000000 --- a/chromium/services/content/BUILD.gn +++ /dev/null @@ -1,69 +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. - -import("//build/config/ui.gni") - -source_set("impl") { - visibility = [ - ":tests", - "//content/browser", - ] - - public = [ - "navigable_contents_delegate.h", - "service.h", - "service_delegate.h", - ] - - sources = [ - "navigable_contents_factory_impl.cc", - "navigable_contents_factory_impl.h", - "navigable_contents_impl.cc", - "navigable_contents_impl.h", - "service.cc", - ] - - configs += [ "//build/config/compiler:wexit_time_destructors" ] - - public_deps = [ - "//base", - "//services/service_manager/public/cpp", - "//ui/gfx", - ] - - deps = [ - "//mojo/public/cpp/bindings", - "//services/content/public/cpp", - "//services/content/public/mojom", - ] - - if (toolkit_views && !is_chromecast) { - deps += [ - "//ui/base", - "//ui/views", - ] - - if (use_aura) { - deps += [ "//ui/aura" ] - } - } -} - -source_set("tests") { - testonly = true - - sources = [ "service_unittest.cc" ] - - deps = [ - ":impl", - "//base", - "//base/test:test_support", - "//services/content/public/cpp", - "//services/content/public/cpp/test:tests", - "//services/content/public/mojom", - "//services/service_manager/public/cpp/test:test_support", - "//testing/gtest", - "//url", - ] -} diff --git a/chromium/services/content/DEPS b/chromium/services/content/DEPS deleted file mode 100644 index f3ff2940ecd..00000000000 --- a/chromium/services/content/DEPS +++ /dev/null @@ -1,8 +0,0 @@ -include_rules = [ - "+services/network/public", - - "+ui/aura", - "+ui/base", - "+ui/gfx", - "+ui/views", -] diff --git a/chromium/services/content/DIR_METADATA b/chromium/services/content/DIR_METADATA new file mode 100644 index 00000000000..ac7f3a444c8 --- /dev/null +++ b/chromium/services/content/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Services>Content" +}
\ No newline at end of file diff --git a/chromium/services/content/OWNERS b/chromium/services/content/OWNERS deleted file mode 100644 index 672cb65e3c3..00000000000 --- a/chromium/services/content/OWNERS +++ /dev/null @@ -1,5 +0,0 @@ -alexmos@chromium.org -clamy@chromium.org -jam@chromium.org -rockot@google.com -# COMPONENT: Internals>Services>Content diff --git a/chromium/services/content/navigable_contents_delegate.h b/chromium/services/content/navigable_contents_delegate.h deleted file mode 100644 index a0486221622..00000000000 --- a/chromium/services/content/navigable_contents_delegate.h +++ /dev/null @@ -1,54 +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 SERVICES_CONTENT_NAVIGABLE_CONTENTS_DELEGATE_H_ -#define SERVICES_CONTENT_NAVIGABLE_CONTENTS_DELEGATE_H_ - -#include "services/content/public/mojom/navigable_contents.mojom.h" -#include "ui/gfx/native_widget_types.h" - -class GURL; - -namespace content { - -// A virtual interface which must be implemented as a backing for -// NavigableContentsImpl instances. -// -// This is the primary interface by which the Content Service delegates -// NavigableContentsImpl behavior out to WebContentsImpl in src/content. As such -// it is a transitional API which will be removed as soon as WebContentsImpl -// itself can be fully migrated into Content Service. -// -// Each instance of this interface is constructed by the ContentServiceDelegate -// implementation and owned by a NavigableContentsImpl. -class NavigableContentsDelegate { - public: - virtual ~NavigableContentsDelegate() {} - - // Returns a NativeView that can be embedded into a client application's - // window tree to display the web contents navigated by the delegate's - // NavigableContents. - virtual gfx::NativeView GetNativeView() = 0; - - // Navigates the content object to a new URL. - virtual void Navigate(const GURL& url, mojom::NavigateParamsPtr params) = 0; - - // Attempts to navigate the web contents back in its history stack. The - // supplied |callback| is run to indicate success/failure of the attempt. The - // navigation attempt will fail if the history stack is empty. - virtual void GoBack( - content::mojom::NavigableContents::GoBackCallback callback) = 0; - - // Attempts to transfer global input focus to the navigated contents if they - // have an active visual representation. - virtual void Focus() = 0; - - // Similar to above but for use specifically when UI element traversal is - // being done via Tab-key cycling or a similar mechanism. - virtual void FocusThroughTabTraversal(bool reverse) = 0; -}; - -} // namespace content - -#endif // SERVICES_CONTENT_NAVIGABLE_CONTENTS_DELEGATE_H_ diff --git a/chromium/services/content/navigable_contents_factory_impl.cc b/chromium/services/content/navigable_contents_factory_impl.cc deleted file mode 100644 index a22d9375df7..00000000000 --- a/chromium/services/content/navigable_contents_factory_impl.cc +++ /dev/null @@ -1,35 +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. - -#include "services/content/navigable_contents_factory_impl.h" - -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "services/content/navigable_contents_impl.h" -#include "services/content/service.h" - -namespace content { - -NavigableContentsFactoryImpl::NavigableContentsFactoryImpl( - Service* service, - mojo::PendingReceiver<mojom::NavigableContentsFactory> receiver) - : service_(service), receiver_(this, std::move(receiver)) { - receiver_.set_disconnect_handler( - base::BindOnce(&Service::RemoveNavigableContentsFactory, - base::Unretained(service_), this)); -} - -NavigableContentsFactoryImpl::~NavigableContentsFactoryImpl() = default; - -void NavigableContentsFactoryImpl::CreateContents( - mojom::NavigableContentsParamsPtr params, - mojo::PendingReceiver<mojom::NavigableContents> receiver, - mojo::PendingRemote<mojom::NavigableContentsClient> client) { - service_->AddNavigableContents(std::make_unique<NavigableContentsImpl>( - service_, std::move(params), std::move(receiver), std::move(client))); -} - -} // namespace content diff --git a/chromium/services/content/navigable_contents_factory_impl.h b/chromium/services/content/navigable_contents_factory_impl.h deleted file mode 100644 index ae17f216e8c..00000000000 --- a/chromium/services/content/navigable_contents_factory_impl.h +++ /dev/null @@ -1,46 +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 SERVICES_CONTENT_NAVIGABLE_CONTENTS_FACTORY_IMPL_H_ -#define SERVICES_CONTENT_NAVIGABLE_CONTENTS_FACTORY_IMPL_H_ - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "services/content/public/mojom/navigable_contents_factory.mojom.h" - -namespace content { - -class Service; - -// An implementation of the NavigableContentsFactory which backs every connected -// NavigableContentsFactory interface in a Content Service client. This creates -// instances of NavigableContentsImpl to fulfill |CreateContents()| requests. -// -// Instances of this class, and of the NavigableContentsImpls it creates, are -// all managed by the Service instance. -class NavigableContentsFactoryImpl : public mojom::NavigableContentsFactory { - public: - NavigableContentsFactoryImpl( - Service* service, - mojo::PendingReceiver<mojom::NavigableContentsFactory> receiver); - ~NavigableContentsFactoryImpl() override; - - private: - // mojom::NavigableContentsFactory: - void CreateContents( - mojom::NavigableContentsParamsPtr params, - mojo::PendingReceiver<mojom::NavigableContents> receiver, - mojo::PendingRemote<mojom::NavigableContentsClient> client) override; - - Service* const service_; - mojo::Receiver<mojom::NavigableContentsFactory> receiver_; - - DISALLOW_COPY_AND_ASSIGN(NavigableContentsFactoryImpl); -}; - -} // namespace content - -#endif // SERVICES_CONTENT_NAVIGABLE_CONTENTS_FACTORY_IMPL_H_ diff --git a/chromium/services/content/navigable_contents_impl.cc b/chromium/services/content/navigable_contents_impl.cc deleted file mode 100644 index a5761f8aa3b..00000000000 --- a/chromium/services/content/navigable_contents_impl.cc +++ /dev/null @@ -1,83 +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. - -#include "services/content/navigable_contents_impl.h" - -#include "base/bind.h" -#include "services/content/navigable_contents_delegate.h" -#include "services/content/public/cpp/navigable_contents_view.h" -#include "services/content/service.h" -#include "services/content/service_delegate.h" - -#if defined(USE_AURA) -#include "ui/aura/window.h" // nogncheck -#endif - -namespace content { - -NavigableContentsImpl::NavigableContentsImpl( - Service* service, - mojom::NavigableContentsParamsPtr params, - mojo::PendingReceiver<mojom::NavigableContents> receiver, - mojo::PendingRemote<mojom::NavigableContentsClient> client) - : service_(service), - receiver_(this, std::move(receiver)), - client_(std::move(client)), - delegate_( - service_->delegate()->CreateNavigableContentsDelegate(*params, - client_.get())), - native_content_view_(delegate_->GetNativeView()) { - receiver_.set_disconnect_handler(base::BindOnce( - &Service::RemoveNavigableContents, base::Unretained(service_), this)); -} - -NavigableContentsImpl::~NavigableContentsImpl() = default; - -void NavigableContentsImpl::Navigate(const GURL& url, - mojom::NavigateParamsPtr params) { - // Ignore non-HTTP/HTTPS/data requests for now. - if (!url.SchemeIsHTTPOrHTTPS() && !url.SchemeIs(url::kDataScheme)) - return; - - delegate_->Navigate(url, std::move(params)); -} - -void NavigableContentsImpl::GoBack( - mojom::NavigableContents::GoBackCallback callback) { - delegate_->GoBack(std::move(callback)); -} - -void NavigableContentsImpl::CreateView(CreateViewCallback callback) { - // Create and stash a new callback (indexed by token) which the in-process - // client library can use to establish an "embedding" of the contents' view. - auto token = base::UnguessableToken::Create(); - NavigableContentsView::RegisterInProcessEmbedCallback( - token, base::BindOnce(&NavigableContentsImpl::EmbedInProcessClientView, - weak_ptr_factory_.GetWeakPtr())); - std::move(callback).Run(token); -} - -void NavigableContentsImpl::Focus() { - delegate_->Focus(); -} - -void NavigableContentsImpl::FocusThroughTabTraversal(bool reverse) { - delegate_->FocusThroughTabTraversal(reverse); -} - -void NavigableContentsImpl::EmbedInProcessClientView( - NavigableContentsView* view) { - DCHECK(native_content_view_); -#if defined(TOOLKIT_VIEWS) && defined(USE_AURA) - view->native_view()->AddChild(native_content_view_); - native_content_view_->Show(); -#else - // TODO(https://crbug.com/855092): Support embedding of other native client - // views without Views + Aura. - NOTREACHED() - << "NavigableContents views are currently only supported on Views UI."; -#endif -} - -} // namespace content diff --git a/chromium/services/content/navigable_contents_impl.h b/chromium/services/content/navigable_contents_impl.h deleted file mode 100644 index 9ae581bcfaf..00000000000 --- a/chromium/services/content/navigable_contents_impl.h +++ /dev/null @@ -1,63 +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 SERVICES_CONTENT_NAVIGABLE_CONTENTS_IMPL_H_ -#define SERVICES_CONTENT_NAVIGABLE_CONTENTS_IMPL_H_ - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/unguessable_token.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "services/content/public/mojom/navigable_contents.mojom.h" -#include "services/content/public/mojom/navigable_contents_factory.mojom.h" -#include "ui/gfx/native_widget_types.h" - -namespace content { - -class Service; -class NavigableContentsDelegate; -class NavigableContentsView; - -// This is the state which backs an individual NavigableContents owned by some -// client of the Content Service. In terms of the classical Content API, this is -// roughly analogous to a WebContentsImpl. -class NavigableContentsImpl : public mojom::NavigableContents { - public: - NavigableContentsImpl( - Service* service, - mojom::NavigableContentsParamsPtr params, - mojo::PendingReceiver<mojom::NavigableContents> receiver, - mojo::PendingRemote<mojom::NavigableContentsClient> client); - ~NavigableContentsImpl() override; - - private: - // mojom::NavigableContents: - void Navigate(const GURL& url, mojom::NavigateParamsPtr params) override; - void GoBack(mojom::NavigableContents::GoBackCallback callback) override; - void CreateView(CreateViewCallback callback) override; - void Focus() override; - void FocusThroughTabTraversal(bool reverse) override; - - // Used (indirectly) by the client library when run in the same process as the - // service. See the |CreateView()| implementation for details. - void EmbedInProcessClientView(NavigableContentsView* view); - - Service* const service_; - - mojo::Receiver<mojom::NavigableContents> receiver_; - mojo::Remote<mojom::NavigableContentsClient> client_; - std::unique_ptr<NavigableContentsDelegate> delegate_; - gfx::NativeView native_content_view_; - - base::WeakPtrFactory<NavigableContentsImpl> weak_ptr_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(NavigableContentsImpl); -}; - -} // namespace content - -#endif // SERVICES_CONTENT_NAVIGABLE_CONTENTS_IMPL_H_ diff --git a/chromium/services/content/public/cpp/BUILD.gn b/chromium/services/content/public/cpp/BUILD.gn deleted file mode 100644 index 2e97408c4c9..00000000000 --- a/chromium/services/content/public/cpp/BUILD.gn +++ /dev/null @@ -1,45 +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. - -import("//build/config/ui.gni") - -component("cpp") { - output_name = "content_service_cpp" - - public = [ - "navigable_contents.h", - "navigable_contents_observer.h", - "navigable_contents_view.h", - ] - - sources = [ - "navigable_contents.cc", - "navigable_contents_view.cc", - ] - - configs += [ "//build/config/compiler:wexit_time_destructors" ] - - defines = [ "IS_CONTENT_SERVICE_CPP_IMPL" ] - - public_deps = [ - "//base", - "//net", - "//services/content/public/mojom", - "//ui/accessibility", - "//ui/accessibility/mojom", - "//ui/base", - "//ui/gfx:native_widget_types", - "//ui/gfx/geometry", - "//url", - ] - - deps = [] - if (toolkit_views && !is_chromecast) { - deps += [ "//ui/views" ] - } - - if (use_aura) { - deps += [ "//ui/aura" ] - } -} diff --git a/chromium/services/content/public/cpp/DEPS b/chromium/services/content/public/cpp/DEPS deleted file mode 100644 index b5413998f43..00000000000 --- a/chromium/services/content/public/cpp/DEPS +++ /dev/null @@ -1,6 +0,0 @@ -include_rules = [ - "+net/http/http_response_headers.h", - "+ui/accessibility", - "+ui/aura", - "+ui/views", -] diff --git a/chromium/services/content/public/cpp/navigable_contents.cc b/chromium/services/content/public/cpp/navigable_contents.cc deleted file mode 100644 index f34211ed266..00000000000 --- a/chromium/services/content/public/cpp/navigable_contents.cc +++ /dev/null @@ -1,122 +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. - -#include "services/content/public/cpp/navigable_contents.h" - -#include "base/bind.h" -#include "base/memory/ptr_util.h" -#include "services/content/public/cpp/navigable_contents_view.h" - -namespace content { - -NavigableContents::NavigableContents(mojom::NavigableContentsFactory* factory) - : NavigableContents(factory, mojom::NavigableContentsParams::New()) {} - -NavigableContents::NavigableContents(mojom::NavigableContentsFactory* factory, - mojom::NavigableContentsParamsPtr params) - : client_receiver_(this), content_ax_tree_id_(ui::AXTreeIDUnknown()) { - factory->CreateContents(std::move(params), - contents_.BindNewPipeAndPassReceiver(), - client_receiver_.BindNewPipeAndPassRemote()); -} - -NavigableContents::~NavigableContents() = default; - -void NavigableContents::AddObserver(NavigableContentsObserver* observer) { - observers_.AddObserver(observer); -} - -void NavigableContents::RemoveObserver(NavigableContentsObserver* observer) { - observers_.RemoveObserver(observer); -} - -NavigableContentsView* NavigableContents::GetView() { - if (!view_) { - view_ = base::WrapUnique(new NavigableContentsView(this)); - contents_->CreateView(base::BindOnce( - &NavigableContents::OnEmbedTokenReceived, base::Unretained(this))); - } - return view_.get(); -} - -void NavigableContents::Navigate(const GURL& url) { - NavigateWithParams(url, mojom::NavigateParams::New()); -} - -void NavigableContents::NavigateWithParams(const GURL& url, - mojom::NavigateParamsPtr params) { - contents_->Navigate(url, std::move(params)); -} - -void NavigableContents::GoBack( - content::mojom::NavigableContents::GoBackCallback callback) { - contents_->GoBack(std::move(callback)); -} - -void NavigableContents::Focus() { - contents_->Focus(); -} - -void NavigableContents::FocusThroughTabTraversal(bool reverse) { - contents_->FocusThroughTabTraversal(reverse); -} - -void NavigableContents::ClearViewFocus() { - if (view_) - view_->ClearNativeFocus(); -} - -void NavigableContents::DidFinishNavigation( - const GURL& url, - bool is_main_frame, - bool is_error_page, - const scoped_refptr<net::HttpResponseHeaders>& response_headers) { - for (auto& observer : observers_) { - observer.DidFinishNavigation(url, is_main_frame, is_error_page, - response_headers.get()); - } -} - -void NavigableContents::DidStopLoading() { - for (auto& observer : observers_) - observer.DidStopLoading(); -} - -void NavigableContents::DidAutoResizeView(const gfx::Size& new_size) { - for (auto& observer : observers_) - observer.DidAutoResizeView(new_size); -} - -void NavigableContents::DidSuppressNavigation(const GURL& url, - WindowOpenDisposition disposition, - bool from_user_gesture) { - for (auto& observer : observers_) - observer.DidSuppressNavigation(url, disposition, from_user_gesture); -} - -void NavigableContents::UpdateCanGoBack(bool can_go_back) { - for (auto& observer : observers_) - observer.UpdateCanGoBack(can_go_back); -} - -void NavigableContents::UpdateContentAXTree(const ui::AXTreeID& id) { - content_ax_tree_id_ = id; - if (view_) - view_->NotifyAccessibilityTreeChange(); -} - -void NavigableContents::FocusedNodeChanged( - bool is_editable_node, - const gfx::Rect& node_bounds_in_screen) { - for (auto& observer : observers_) - observer.FocusedNodeChanged(is_editable_node, node_bounds_in_screen); -} - -void NavigableContents::OnEmbedTokenReceived( - const base::UnguessableToken& token) { - DCHECK(view_); - view_->EmbedUsingToken(token); -} - -} // namespace content diff --git a/chromium/services/content/public/cpp/navigable_contents.h b/chromium/services/content/public/cpp/navigable_contents.h deleted file mode 100644 index da93017f041..00000000000 --- a/chromium/services/content/public/cpp/navigable_contents.h +++ /dev/null @@ -1,106 +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 SERVICES_CONTENT_PUBLIC_CPP_NAVIGABLE_CONTENTS_H_ -#define SERVICES_CONTENT_PUBLIC_CPP_NAVIGABLE_CONTENTS_H_ - -#include <memory> - -#include "base/callback.h" -#include "base/component_export.h" -#include "base/macros.h" -#include "base/observer_list.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "services/content/public/cpp/navigable_contents_observer.h" -#include "services/content/public/mojom/navigable_contents.mojom.h" -#include "services/content/public/mojom/navigable_contents_factory.mojom.h" -#include "ui/accessibility/ax_tree_id.h" - -namespace content { - -class NavigableContentsView; - -// A NavigableContents controls a single dedicated instance of a top-level, -// navigable content frame hosted by the Content Service. In addition to -// maintaining its own navigation state, a NavigableContents may be used to -// acquire an embeddable native UI object to display renderered content within a -// client application's own UI. -class COMPONENT_EXPORT(CONTENT_SERVICE_CPP) NavigableContents - : public mojom::NavigableContentsClient { - public: - // Constructs a new NavigableContents using |factory|. - explicit NavigableContents(mojom::NavigableContentsFactory* factory); - NavigableContents(mojom::NavigableContentsFactory* factory, - mojom::NavigableContentsParamsPtr params); - ~NavigableContents() override; - - // These methods NavigableContentsObservers registered on this object. - void AddObserver(NavigableContentsObserver* observer); - void RemoveObserver(NavigableContentsObserver* observer); - - // Returns a NavigableContentsView which renders this NavigableContents's - // currently navigated contents. This widget can be parented and displayed - // anywhere within the application's own window tree. - // - // Note that this NavigableContentsView is created lazily on first call, and - // by default NavigableContents does not otherwise create or manipulate UI - // objects. - NavigableContentsView* GetView(); - - // Returns the last known ID of the content area's accessibility tree, if any. - const ui::AXTreeID& content_ax_tree_id() const { return content_ax_tree_id_; } - - // Begins an attempt to asynchronously navigate this NavigableContents to - // |url|. - void Navigate(const GURL& url); - void NavigateWithParams(const GURL& url, mojom::NavigateParamsPtr params); - - // Attempts to navigate back in the web contents' history stack. The supplied - // |callback| is run to indicate success/failure of the navigation attempt. - // The navigation attempt will fail if the history stack is empty. - void GoBack(content::mojom::NavigableContents::GoBackCallback callback); - - // Attempts to transfer global input focus to the navigated contents if they - // have an active visual representation. - void Focus(); - - // Similar to above but for use specifically when UI element traversal is - // being done via Tab-key cycling or a similar mechanism. - void FocusThroughTabTraversal(bool reverse); - - private: - // mojom::NavigableContentsClient: - void ClearViewFocus() override; - void DidFinishNavigation( - const GURL& url, - bool is_main_frame, - bool is_error_page, - const scoped_refptr<net::HttpResponseHeaders>& response_headers) override; - void DidStopLoading() override; - void DidAutoResizeView(const gfx::Size& new_size) override; - void DidSuppressNavigation(const GURL& url, - WindowOpenDisposition disposition, - bool from_user_gesture) override; - void UpdateCanGoBack(bool can_go_back) override; - void UpdateContentAXTree(const ui::AXTreeID& id) override; - void FocusedNodeChanged(bool is_editable_node, - const gfx::Rect& node_bounds_in_screen) override; - - void OnEmbedTokenReceived(const base::UnguessableToken& token); - - mojo::Remote<mojom::NavigableContents> contents_; - mojo::Receiver<mojom::NavigableContentsClient> client_receiver_; - std::unique_ptr<NavigableContentsView> view_; - - base::ReentrantObserverList<NavigableContentsObserver> observers_; - - ui::AXTreeID content_ax_tree_id_; - - DISALLOW_COPY_AND_ASSIGN(NavigableContents); -}; - -} // namespace content - -#endif // SERVICES_CONTENT_PUBLIC_CPP_NAVIGABLE_CONTENTS_H_ diff --git a/chromium/services/content/public/cpp/navigable_contents_observer.h b/chromium/services/content/public/cpp/navigable_contents_observer.h deleted file mode 100644 index dd5f6133df7..00000000000 --- a/chromium/services/content/public/cpp/navigable_contents_observer.h +++ /dev/null @@ -1,38 +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 SERVICES_CONTENT_PUBLIC_CPP_NAVIGABLE_CONTENTS_OBSERVER_H_ -#define SERVICES_CONTENT_PUBLIC_CPP_NAVIGABLE_CONTENTS_OBSERVER_H_ - -#include "base/component_export.h" -#include "base/observer_list_types.h" -#include "net/http/http_response_headers.h" -#include "ui/base/window_open_disposition.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/size.h" -#include "url/gurl.h" - -namespace content { - -class COMPONENT_EXPORT(CONTENT_SERVICE_CPP) NavigableContentsObserver - : public base::CheckedObserver { - public: - virtual void DidFinishNavigation( - const GURL& url, - bool is_main_frame, - bool is_error_page, - const net::HttpResponseHeaders* response_headers) {} - virtual void DidStopLoading() {} - virtual void DidAutoResizeView(const gfx::Size& new_size) {} - virtual void DidSuppressNavigation(const GURL& url, - WindowOpenDisposition disposition, - bool from_user_gesture) {} - virtual void UpdateCanGoBack(bool can_go_back) {} - virtual void FocusedNodeChanged(bool is_editable_node, - const gfx::Rect& node_bounds_in_screen) {} -}; - -} // namespace content - -#endif // SERVICES_CONTENT_PUBLIC_CPP_NAVIGABLE_CONTENTS_OBSERVER_H_ diff --git a/chromium/services/content/public/cpp/navigable_contents_view.cc b/chromium/services/content/public/cpp/navigable_contents_view.cc deleted file mode 100644 index b2a150a9380..00000000000 --- a/chromium/services/content/public/cpp/navigable_contents_view.cc +++ /dev/null @@ -1,188 +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. - -#include "services/content/public/cpp/navigable_contents_view.h" - -#include <map> - -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/no_destructor.h" -#include "base/synchronization/atomic_flag.h" -#include "base/unguessable_token.h" -#include "services/content/public/cpp/navigable_contents.h" -#include "ui/accessibility/ax_enums.mojom.h" -#include "ui/accessibility/ax_node_data.h" - -#if defined(TOOLKIT_VIEWS) -#include "ui/views/focus/focus_manager.h" // nogncheck -#include "ui/views/layout/fill_layout.h" // nogncheck -#include "ui/views/view.h" // nogncheck -#endif // defined(TOOLKIT_VIEWS) - -#if defined(USE_AURA) -#include "ui/aura/layout_manager.h" // nogncheck -#include "ui/aura/window.h" // nogncheck -#endif - -namespace content { - -namespace { - -using InProcessEmbeddingMap = - std::map<base::UnguessableToken, - base::OnceCallback<void(NavigableContentsView*)>>; - -InProcessEmbeddingMap& GetInProcessEmbeddingMap() { - static base::NoDestructor<InProcessEmbeddingMap> embedding_map; - return *embedding_map; -} - -base::AtomicFlag& GetInServiceProcessFlag() { - static base::NoDestructor<base::AtomicFlag> in_service_process; - return *in_service_process; -} - -#if defined(TOOLKIT_VIEWS) && defined(USE_AURA) - -// Keeps child windows sized to the same bounds as the owning window. -class LocalWindowLayoutManager : public aura::LayoutManager { - public: - explicit LocalWindowLayoutManager(aura::Window* owner) : owner_(owner) {} - ~LocalWindowLayoutManager() override = default; - - // aura::LayoutManger: - void OnWindowResized() override { ResizeChildren(); } - void OnWindowAddedToLayout(aura::Window* child) override { ResizeChildren(); } - void OnWillRemoveWindowFromLayout(aura::Window* child) override {} - void OnWindowRemovedFromLayout(aura::Window* child) override {} - void OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) override {} - void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) override {} - - private: - void ResizeChildren() { - for (auto* child : owner_->children()) - SetChildBoundsDirect(child, gfx::Rect(owner_->bounds().size())); - } - - aura::Window* const owner_; - - DISALLOW_COPY_AND_ASSIGN(LocalWindowLayoutManager); -}; - -// Owns an Aura window which parents another Aura window in the same process, -// corresponding to a web contents view hosted in the process. -class LocalViewHost : public views::NativeViewHost { - public: - LocalViewHost(aura::Window* window, NavigableContents* contents) - : window_(window), contents_(contents) { - window_->SetLayoutManager(new LocalWindowLayoutManager(window_)); - } - - ~LocalViewHost() override = default; - - // views::View: - void AddedToWidget() override { - if (!native_view()) - Attach(window_); - } - - void GetAccessibleNodeData(ui::AXNodeData* node_data) override { - node_data->role = ax::mojom::Role::kWebView; - - // The document title is provided to the accessibility system by other - // means, so setting it here would be redundant. - node_data->SetNameExplicitlyEmpty(); - - if (contents_->content_ax_tree_id() != ui::AXTreeIDUnknown()) { - node_data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - contents_->content_ax_tree_id().ToString()); - } - } - - private: - aura::Window* const window_; - NavigableContents* const contents_; - - DISALLOW_COPY_AND_ASSIGN(LocalViewHost); -}; - -#endif // defined(TOOLKIT_VIEWS) && defined(USE_AURA) - -} // namespace - -NavigableContentsView::~NavigableContentsView() = default; - -// static -void NavigableContentsView::SetClientRunningInServiceProcess() { - GetInServiceProcessFlag().Set(); -} - -// static -bool NavigableContentsView::IsClientRunningInServiceProcess() { - return GetInServiceProcessFlag().IsSet(); -} - -void NavigableContentsView::ClearNativeFocus() { -#if defined(TOOLKIT_VIEWS) && defined(USE_AURA) - auto* focus_manager = view_->GetFocusManager(); - if (focus_manager) - focus_manager->ClearNativeFocus(); -#endif // defined(TOOLKIT_VIEWS) && defined(USE_AURA) -} - -void NavigableContentsView::NotifyAccessibilityTreeChange() { -#if defined(TOOLKIT_VIEWS) && defined(USE_AURA) - view_->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, false); -#endif -} - -NavigableContentsView::NavigableContentsView(NavigableContents* contents) - : contents_(contents) { -#if defined(TOOLKIT_VIEWS) && defined(USE_AURA) - window_ = std::make_unique<aura::Window>(nullptr); - window_->set_owned_by_parent(false); - window_->SetName("NavigableContentsViewWindow"); - window_->SetType(aura::client::WINDOW_TYPE_CONTROL); - window_->Init(ui::LAYER_NOT_DRAWN); - window_->Show(); - - view_ = std::make_unique<LocalViewHost>(window_.get(), contents_); - view_->set_owned_by_client(); -#endif // defined(TOOLKIT_VIEWS) && defined(USE_AURA) -} - -void NavigableContentsView::EmbedUsingToken( - const base::UnguessableToken& token) { -#if defined(TOOLKIT_VIEWS) - DCHECK(IsClientRunningInServiceProcess()); - - // |token| should already have an embed callback entry in the in-process - // callback map, injected by the in-process Content Service implementation. - auto& embeddings = GetInProcessEmbeddingMap(); - auto it = embeddings.find(token); - if (it == embeddings.end()) { - DLOG(ERROR) << "Unable to embed with unknown token " << token.ToString(); - return; - } - - // Invoke a callback provided by the Content Service's host environment. This - // should parent a web content view to our own |view()|, as well as set - // |native_view_| to the corresponding web contents' own NativeView. - auto callback = std::move(it->second); - embeddings.erase(it); - std::move(callback).Run(this); -#endif // defined(TOOLKIT_VIEWS) -} - -// static -void NavigableContentsView::RegisterInProcessEmbedCallback( - const base::UnguessableToken& token, - base::OnceCallback<void(NavigableContentsView*)> callback) { - GetInProcessEmbeddingMap()[token] = std::move(callback); -} - -} // namespace content diff --git a/chromium/services/content/public/cpp/navigable_contents_view.h b/chromium/services/content/public/cpp/navigable_contents_view.h deleted file mode 100644 index d78372cbf33..00000000000 --- a/chromium/services/content/public/cpp/navigable_contents_view.h +++ /dev/null @@ -1,93 +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 SERVICES_CONTENT_PUBLIC_CPP_NAVIGABLE_CONTENTS_VIEW_H_ -#define SERVICES_CONTENT_PUBLIC_CPP_NAVIGABLE_CONTENTS_VIEW_H_ - -#include <memory> - -#include "base/callback.h" -#include "base/component_export.h" -#include "base/unguessable_token.h" -#include "ui/gfx/native_widget_types.h" - -#if defined(TOOLKIT_VIEWS) && defined(USE_AURA) -#include "ui/views/controls/native/native_view_host.h" // nogncheck -#endif - -namespace aura { -class Window; -} - -namespace views { -class View; -class NativeViewHost; -} // namespace views - -namespace content { - -class NavigableContents; -class NavigableContentsImpl; - -// NavigableContentsView encapsulates cross-platform manipulation and -// presentation of a NavigableContents within a native application UI based on -// either Views, UIKit, AppKit, or the Android Framework. -// -// TODO(https://crbug.com/855092): Actually support UI frameworks other than -// Views UI on Aura. -class COMPONENT_EXPORT(CONTENT_SERVICE_CPP) NavigableContentsView { - public: - ~NavigableContentsView(); - - // Used to set/query whether the calling process is the same process in which - // all Content Service instances are running. This should be used sparingly, - // and in general is only here to support internal sanity checks when - // performing, e.g., UI embedding operations on platforms where remote - // NavigableContentsViews are not yet supported. - static void SetClientRunningInServiceProcess(); - static bool IsClientRunningInServiceProcess(); - -#if defined(TOOLKIT_VIEWS) && defined(USE_AURA) - views::View* view() const { return view_.get(); } - - gfx::NativeView native_view() const { return view_->native_view(); } -#endif // defined(TOOLKIT_VIEWS) && defined(USE_AURA) - - // Clears the native view having focus. See FocusManager::ClearNativeFocus. - void ClearNativeFocus(); - - // Has this view notify the UI subsystem of an accessibility tree change. - void NotifyAccessibilityTreeChange(); - - private: - friend class FakeNavigableContents; - friend class NavigableContents; - friend class NavigableContentsImpl; - - explicit NavigableContentsView(NavigableContents* contents_); - - // Establishes a hierarchical relationship between this view's native UI - // object and another native UI object within the Content Service. - void EmbedUsingToken(const base::UnguessableToken& token); - - // Used by the service directly when running in the same process. Establishes - // a way for an embed token to be used without the UI service. - static void RegisterInProcessEmbedCallback( - const base::UnguessableToken& token, - base::OnceCallback<void(NavigableContentsView*)> callback); - - NavigableContents* const contents_; - -#if defined(TOOLKIT_VIEWS) && defined(USE_AURA) - // This NavigableContents's Window and corresponding View. - std::unique_ptr<aura::Window> window_; - std::unique_ptr<views::NativeViewHost> view_; -#endif // defined(TOOLKIT_VIEWS) && defined(USE_AURA) - - DISALLOW_COPY_AND_ASSIGN(NavigableContentsView); -}; - -} // namespace content - -#endif // SERVICES_CONTENT_PUBLIC_CPP_NAVIGABLE_CONTENTS_VIEW_H_ diff --git a/chromium/services/content/public/cpp/test/BUILD.gn b/chromium/services/content/public/cpp/test/BUILD.gn deleted file mode 100644 index d89c0fbbd64..00000000000 --- a/chromium/services/content/public/cpp/test/BUILD.gn +++ /dev/null @@ -1,39 +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. - -source_set("test_support") { - testonly = true - - sources = [ - "fake_navigable_contents.cc", - "fake_navigable_contents.h", - "fake_navigable_contents_factory.cc", - "fake_navigable_contents_factory.h", - ] - - public_deps = [ - "//base", - "//base/test:test_support", - "//mojo/public/cpp/bindings", - "//services/content/public/cpp", - "//services/content/public/mojom", - ] -} - -source_set("tests") { - testonly = true - - sources = [ "fake_navigable_contents_factory_unittest.cc" ] - - deps = [ - ":test_support", - "//base", - "//base/test:test_support", - "//net", - "//services/content/public/cpp", - "//services/content/public/mojom", - "//testing/gtest", - "//url", - ] -} diff --git a/chromium/services/content/public/mojom/BUILD.gn b/chromium/services/content/public/mojom/BUILD.gn deleted file mode 100644 index 474f0012fd3..00000000000 --- a/chromium/services/content/public/mojom/BUILD.gn +++ /dev/null @@ -1,30 +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. - -import("//mojo/public/tools/bindings/mojom.gni") - -mojom_component("mojom") { - # We don't want Blink variants of these bindings to be generated, because they - # will end up having a dependency on KURL and thus be required to link into - # the same Blink component target. This should be removed once it's possible - # for a non-Blink target to depend on KURL. - disable_variants = true - - sources = [ - "navigable_contents.mojom", - "navigable_contents_factory.mojom", - ] - - public_deps = [ - "//mojo/public/mojom/base", - "//services/network/public/mojom:websocket_mojom", - "//ui/accessibility/mojom", - "//ui/base/mojom", - "//ui/gfx/geometry/mojom", - "//url/mojom:url_mojom_gurl", - ] - - output_prefix = "content_service_mojom" - macro_prefix = "CONTENT_SERVICE_MOJOM" -} diff --git a/chromium/services/content/public/mojom/OWNERS b/chromium/services/content/public/mojom/OWNERS deleted file mode 100644 index 08850f42120..00000000000 --- a/chromium/services/content/public/mojom/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS diff --git a/chromium/services/content/public/mojom/navigable_contents.mojom b/chromium/services/content/public/mojom/navigable_contents.mojom deleted file mode 100644 index 202d63e93ac..00000000000 --- a/chromium/services/content/public/mojom/navigable_contents.mojom +++ /dev/null @@ -1,93 +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. - -module content.mojom; - -import "services/network/public/mojom/network_param.mojom"; -import "ui/accessibility/mojom/ax_tree_id.mojom"; -import "ui/base/mojom/window_open_disposition.mojom"; -import "ui/gfx/geometry/mojom/geometry.mojom"; -import "mojo/public/mojom/base/unguessable_token.mojom"; -import "url/mojom/url.mojom"; - -// Parameters used to configure the behavior of |NavigableContents.Navigate|. -struct NavigateParams { - // Indicates that upon successful navigation, the session history should be - // cleared, resulting in the navigated page being the first and only entry in - // the session's history. - bool should_clear_session_history = false; -}; - -// The primary interface an application uses to drive a top-level, navigable -// content object. Typically this would correspond to e.g. a browser tab, but -// it is not strictly necessary that the contents have any graphical presence -// within the client application. -interface NavigableContents { - // Initiates a navigation to |url|. - Navigate(url.mojom.Url url, NavigateParams params); - - // Attempts to navigate the web contents back in its history stack. The - // supplied |callback| is run to indicate success/failure of the attempt. The - // navigation attempt will fail if the history stack is empty. - GoBack() => (bool success); - - // Creates a visual representation of the navigated contents, which is - // maintained by the Content Service. Responds with a |embed_token| which can - // be given to Mus in order to authorize embedding of that visual - // representation within the client application's own window tree. - CreateView() => (mojo_base.mojom.UnguessableToken embed_token); - - // Attempts to transfer global input focus to the navigated contents if they - // have an active visual representation. - Focus(); - - // Similar to above but for use specifically when UI traversal is being done - // via Tab-key cycling. - FocusThroughTabTraversal(bool reverse); -}; - -// A client interface used by the Content Service to push contents-scoped events -// back to the application. -interface NavigableContentsClient { - // Requests that the client relinquish focus from the content area's view. - ClearViewFocus(); - - // Notifies the client that a navigation has finished. - DidFinishNavigation(url.mojom.Url url, - bool is_main_frame, - bool is_error_page, - network.mojom.HttpResponseHeaders? response_headers); - - // Notifies the client that the NavigableContents has stopped loading - // resources pertaining to a prior navigation request. - DidStopLoading(); - - // Indicates that the navigated contents changed in such a way as to elicit - // automatic resizing of the containing view. Only fired if - // |NavigableContentsParams.enable_view_auto_resize| was set to |true| when - // creating the corresponding NavigableContents. The client may use this as a - // signal to, e.g., resize a UI element containing the content view. - DidAutoResizeView(gfx.mojom.Size new_size); - - // Notifies the client that a navigation was attempted by the contents (e.g. - // by user gesture or script behavior), but it was suppressed because - // |NavigableContentsParams.suppress_navigations| was set to |true| when the - // NavigableContents was created. See that flag's documentation for details - // regarding which types of navigations it can affect. - DidSuppressNavigation(url.mojom.Url url, - ui.mojom.WindowOpenDisposition disposition, - bool from_user_gesture); - - // Notifies the client whether the web contents can navigate back in its - // history stack. - UpdateCanGoBack(bool can_go_back); - - // Informs the client of the ID of the content area's accessibility tree - // whenever it changes. - UpdateContentAXTree(ax.mojom.AXTreeID id); - - // Informs the client that the focused DOM node has changed. - FocusedNodeChanged(bool is_editable_node, - gfx.mojom.Rect node_bounds_in_screen); -}; diff --git a/chromium/services/content/public/mojom/navigable_contents_factory.mojom b/chromium/services/content/public/mojom/navigable_contents_factory.mojom deleted file mode 100644 index 0cb86edb437..00000000000 --- a/chromium/services/content/public/mojom/navigable_contents_factory.mojom +++ /dev/null @@ -1,52 +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. - -module content.mojom; - -import "services/content/public/mojom/navigable_contents.mojom"; -import "ui/gfx/geometry/mojom/geometry.mojom"; - -// Parameters used to configure a newly created NavigableContents. -struct NavigableContentsParams { - // Enables auto-resizing of any view created for this NavigableContents. If - // |true|, the corresponding NavigableContentsClient will receive - // |DidAutoResizeView()| notifications whenever such resizing happens. - bool enable_view_auto_resize = false; - - // Specifies the minimum size for auto resizing. - // Defaults to (1, 1). - gfx.mojom.Size? auto_resize_min_size; - - // Specifies the maximum size for auto resizing. - // Defaults to (INT_MAX, INT_MAX). - gfx.mojom.Size? auto_resize_max_size; - - // Indicates that the client wants to control how navigation requests are - // handled within the created NavigableContents. Any attempt to navigate the - // NavigableContents by any means other than an explicit call to - // |NavigableContents.Navigate()| -- for example, link clicks or scripted - // location changes -- will be suppressed and will instead result in a - // |DidSuppressNavigation()| message being sent to the corresponding - // NavigableContentsClient. - bool suppress_navigations = false; - - // Background color of the content. Effective when |override_background_color| - // is true. - // TODO(https://crbug.com/657632): Numeric types are not nullable. - bool override_background_color = false; - uint32 background_color = 0xFFFFFFFF; // Opaque white. -}; - -// NavigableContentsFactory is the primary interface through which a new -// NavigableContents interface is bound to a new concrete navigable contents -// within the Content Service. -interface NavigableContentsFactory { - // Creates a new NavigableContents configured according to |params|. - // |receiver| is bound to a NavigableContents implementation, and |client| is - // used to push event notifications relevant to the state of that - // implementation throughout its lifetime. - CreateContents(NavigableContentsParams params, - pending_receiver<NavigableContents> receiver, - pending_remote<NavigableContentsClient> client); -}; diff --git a/chromium/services/content/service.cc b/chromium/services/content/service.cc deleted file mode 100644 index 5e295321992..00000000000 --- a/chromium/services/content/service.cc +++ /dev/null @@ -1,56 +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. - -#include "services/content/service.h" - -#include <utility> - -#include "services/content/navigable_contents_factory_impl.h" -#include "services/content/navigable_contents_impl.h" -#include "services/content/public/mojom/navigable_contents_factory.mojom.h" -#include "services/content/service_delegate.h" - -namespace content { - -Service::Service(ServiceDelegate* delegate) : delegate_(delegate) {} - -Service::~Service() { - delegate_->WillDestroyServiceInstance(this); -} - -void Service::BindNavigableContentsFactory( - mojo::PendingReceiver<mojom::NavigableContentsFactory> receiver) { - AddNavigableContentsFactory(std::make_unique<NavigableContentsFactoryImpl>( - this, std::move(receiver))); -} - -void Service::ForceQuit() { - // Ensure that all bound interfaces are disconnected and no further interface - // requests will be handled. - navigable_contents_factories_.clear(); - navigable_contents_.clear(); -} - -void Service::AddNavigableContentsFactory( - std::unique_ptr<NavigableContentsFactoryImpl> factory) { - auto* raw_factory = factory.get(); - navigable_contents_factories_.emplace(raw_factory, std::move(factory)); -} - -void Service::RemoveNavigableContentsFactory( - NavigableContentsFactoryImpl* factory) { - navigable_contents_factories_.erase(factory); -} - -void Service::AddNavigableContents( - std::unique_ptr<NavigableContentsImpl> contents) { - auto* raw_contents = contents.get(); - navigable_contents_.emplace(raw_contents, std::move(contents)); -} - -void Service::RemoveNavigableContents(NavigableContentsImpl* contents) { - navigable_contents_.erase(contents); -} - -} // namespace content diff --git a/chromium/services/content/service.h b/chromium/services/content/service.h deleted file mode 100644 index efc87cf69b4..00000000000 --- a/chromium/services/content/service.h +++ /dev/null @@ -1,67 +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 SERVICES_CONTENT_SERVICE_H_ -#define SERVICES_CONTENT_SERVICE_H_ - -#include <map> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "services/content/public/mojom/navigable_contents_factory.mojom.h" - -namespace content { - -class ServiceDelegate; -class NavigableContentsFactoryImpl; -class NavigableContentsImpl; - -// The core implementation of the Content Service. This takes responsibility for -// owning top-level state for an instance of the service, binding incoming -// interface requests, etc. -// -// NOTE: This type is exposed to ServiceDelegate implementations outside -// of private Content Service code. The public API surface of this class should -// therefore remain as minimal as possible. -class Service { - public: - // |delegate| is not owned and must outlive |this|. - explicit Service(ServiceDelegate* delegate); - ~Service(); - - ServiceDelegate* delegate() const { return delegate_; } - - void BindNavigableContentsFactory( - mojo::PendingReceiver<mojom::NavigableContentsFactory> receiver); - - // Forces this instance of the Service to be terminated. Useful if the - // delegate implementation encounters a scenario in which it can no longer - // operate correctly. May delete |this|. - void ForceQuit(); - - private: - friend class NavigableContentsFactoryImpl; - friend class NavigableContentsImpl; - - void AddNavigableContentsFactory( - std::unique_ptr<NavigableContentsFactoryImpl> factory); - void RemoveNavigableContentsFactory(NavigableContentsFactoryImpl* factory); - - void AddNavigableContents(std::unique_ptr<NavigableContentsImpl> contents); - void RemoveNavigableContents(NavigableContentsImpl* contents); - - ServiceDelegate* const delegate_; - - std::map<NavigableContentsFactoryImpl*, - std::unique_ptr<NavigableContentsFactoryImpl>> - navigable_contents_factories_; - std::map<NavigableContentsImpl*, std::unique_ptr<NavigableContentsImpl>> - navigable_contents_; - - DISALLOW_COPY_AND_ASSIGN(Service); -}; - -} // namespace content - -#endif // SERVICES_CONTENT_SERVICE_H_ diff --git a/chromium/services/content/service_delegate.h b/chromium/services/content/service_delegate.h deleted file mode 100644 index 363e21d9ef4..00000000000 --- a/chromium/services/content/service_delegate.h +++ /dev/null @@ -1,43 +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 SERVICES_CONTENT_SERVICE_DELEGATE_H_ -#define SERVICES_CONTENT_SERVICE_DELEGATE_H_ - -#include "services/content/public/mojom/navigable_contents.mojom.h" -#include "services/content/public/mojom/navigable_contents_factory.mojom.h" - -namespace content { - -class NavigableContentsDelegate; -class Service; - -// This is a delegate interface which allows the Content Service implementation -// to delegate out to private src/content code without a circular dependency -// between them. -// -// This interface is strictly intended to host transitional APIs for aiding in -// incremental conversion of src/content and its dependents into/onto the -// Content Service. As such, APIs should only be added here with a plan for -// eventual removal. -class ServiceDelegate { - public: - virtual ~ServiceDelegate() {} - - // Called when an instance of Service (specifically one using this - // delegate) is about to be destroyed. - virtual void WillDestroyServiceInstance(Service* service) = 0; - - // Constructs a new NavigableContentsDelegate implementation to back a new - // NavigableContentsImpl instance, servicing a client's NavigableContents. - // |client| is a NavigableContentsClient interface the implementation can use - // to communicate with the client of this contents. - virtual std::unique_ptr<NavigableContentsDelegate> - CreateNavigableContentsDelegate(const mojom::NavigableContentsParams& params, - mojom::NavigableContentsClient* client) = 0; -}; - -} // namespace content - -#endif // SERVICES_CONTENT_CONTENT_SERVICE_DELEGATE_H_ diff --git a/chromium/services/content/service_unittest.cc b/chromium/services/content/service_unittest.cc deleted file mode 100644 index cb927675179..00000000000 --- a/chromium/services/content/service_unittest.cc +++ /dev/null @@ -1,169 +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. - -#include "services/content/service.h" - -#include "base/bind.h" -#include "base/callback.h" -#include "base/macros.h" -#include "base/run_loop.h" -#include "base/test/bind_test_util.h" -#include "base/test/task_environment.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "services/content/navigable_contents_delegate.h" -#include "services/content/public/mojom/navigable_contents.mojom.h" -#include "services/content/public/mojom/navigable_contents_factory.mojom.h" -#include "services/content/service_delegate.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace content { -namespace { - -class TestNavigableContentsClient : public mojom::NavigableContentsClient { - public: - TestNavigableContentsClient() = default; - ~TestNavigableContentsClient() override = default; - - private: - // mojom::NavigableContentsClient: - void ClearViewFocus() override {} - void DidFinishNavigation(const GURL& url, - bool is_main_frame, - bool is_error_page, - const scoped_refptr<net::HttpResponseHeaders>& - response_headers) override {} - void DidStopLoading() override {} - void DidAutoResizeView(const gfx::Size& new_size) override {} - void DidSuppressNavigation(const GURL& url, - WindowOpenDisposition disposition, - bool from_user_gesture) override {} - void UpdateCanGoBack(bool can_go_back) override {} - void UpdateContentAXTree(const ui::AXTreeID& id) override {} - void FocusedNodeChanged(bool is_editable_node, - const gfx::Rect& node_bounds_in_screen) override {} - - DISALLOW_COPY_AND_ASSIGN(TestNavigableContentsClient); -}; - -class TestNavigableContentsDelegate : public NavigableContentsDelegate { - public: - TestNavigableContentsDelegate() = default; - ~TestNavigableContentsDelegate() override = default; - - const GURL& last_navigated_url() const { return last_navigated_url_; } - - void set_navigation_callback(base::RepeatingClosure callback) { - navigation_callback_ = std::move(callback); - } - - // NavigableContentsDelegate: - void Navigate(const GURL& url, mojom::NavigateParamsPtr params) override { - last_navigated_url_ = url; - if (navigation_callback_) - navigation_callback_.Run(); - } - - void GoBack( - content::mojom::NavigableContents::GoBackCallback callback) override { - std::move(callback).Run(false /* success */); - } - - void Focus() override {} - void FocusThroughTabTraversal(bool reverse) override {} - - gfx::NativeView GetNativeView() override { return nullptr; } - - private: - GURL last_navigated_url_; - base::RepeatingClosure navigation_callback_; - - DISALLOW_COPY_AND_ASSIGN(TestNavigableContentsDelegate); -}; - -class TestServiceDelegate : public ServiceDelegate { - public: - TestServiceDelegate() = default; - ~TestServiceDelegate() override = default; - - void set_navigable_contents_delegate_created_callback( - base::RepeatingCallback<void(TestNavigableContentsDelegate*)> callback) { - navigable_contents_delegate_created_callback_ = std::move(callback); - } - - // ServiceDelegate: - void WillDestroyServiceInstance(Service* service) override {} - - std::unique_ptr<NavigableContentsDelegate> CreateNavigableContentsDelegate( - const mojom::NavigableContentsParams& params, - mojom::NavigableContentsClient* client) override { - auto delegate = std::make_unique<TestNavigableContentsDelegate>(); - if (navigable_contents_delegate_created_callback_) - navigable_contents_delegate_created_callback_.Run(delegate.get()); - return delegate; - } - - private: - base::RepeatingCallback<void(TestNavigableContentsDelegate*)> - navigable_contents_delegate_created_callback_; - - DISALLOW_COPY_AND_ASSIGN(TestServiceDelegate); -}; - -class ContentServiceTest : public testing::Test { - public: - ContentServiceTest() : service_(&delegate_) {} - ~ContentServiceTest() override = default; - - protected: - TestServiceDelegate& delegate() { return delegate_; } - - Service& service() { return service_; } - - private: - base::test::TaskEnvironment task_environment_; - TestServiceDelegate delegate_; - Service service_; - - DISALLOW_COPY_AND_ASSIGN(ContentServiceTest); -}; - -TEST_F(ContentServiceTest, NavigableContentsCreation) { - mojo::Remote<mojom::NavigableContentsFactory> factory; - service().BindNavigableContentsFactory(factory.BindNewPipeAndPassReceiver()); - - base::RunLoop loop; - - TestNavigableContentsDelegate* navigable_contents_delegate = nullptr; - delegate().set_navigable_contents_delegate_created_callback( - base::BindLambdaForTesting([&](TestNavigableContentsDelegate* delegate) { - EXPECT_FALSE(navigable_contents_delegate); - navigable_contents_delegate = delegate; - loop.Quit(); - })); - - mojo::Remote<mojom::NavigableContents> contents; - TestNavigableContentsClient client_impl; - mojo::Receiver<mojom::NavigableContentsClient> client_receiver(&client_impl); - factory->CreateContents(mojom::NavigableContentsParams::New(), - contents.BindNewPipeAndPassReceiver(), - client_receiver.BindNewPipeAndPassRemote()); - loop.Run(); - - base::RunLoop navigation_loop; - ASSERT_TRUE(navigable_contents_delegate); - navigable_contents_delegate->set_navigation_callback( - navigation_loop.QuitClosure()); - - const GURL kTestUrl("https://example.com/"); - contents->Navigate(kTestUrl, mojom::NavigateParams::New()); - navigation_loop.Run(); - - EXPECT_EQ(kTestUrl, navigable_contents_delegate->last_navigated_url()); -} - -} // namespace -} // namespace content diff --git a/chromium/services/data_decoder/BUILD.gn b/chromium/services/data_decoder/BUILD.gn index adb398ed3ca..5dc96ddf947 100644 --- a/chromium/services/data_decoder/BUILD.gn +++ b/chromium/services/data_decoder/BUILD.gn @@ -2,12 +2,15 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//testing/libfuzzer/fuzzer_test.gni") source_set("lib") { sources = [ "data_decoder_service.cc", "data_decoder_service.h", + "gzipper.cc", + "gzipper.h", "json_parser_impl.cc", "json_parser_impl.h", "web_bundler.cc", @@ -16,7 +19,7 @@ source_set("lib") { "xml_parser.h", ] - if (is_chromeos) { + if (is_ash) { sources += [ "ble_scan_parser_impl.cc", "ble_scan_parser_impl.h", @@ -27,11 +30,13 @@ source_set("lib") { deps = [ "//base", + "//build:chromeos_buildflags", "//components/web_package", "//mojo/public/cpp/bindings", "//net", "//skia", "//third_party/libxml:xml_reader", + "//third_party/zlib/google:compression_utils", "//ui/gfx", "//ui/gfx/geometry", ] @@ -52,6 +57,7 @@ source_set("tests") { testonly = true sources = [ + "gzipper_unittest.cc", "public/cpp/data_decoder_unittest.cc", "public/cpp/json_sanitizer_unittest.cc", "public/cpp/safe_web_bundle_parser_unittest.cc", @@ -59,7 +65,7 @@ source_set("tests") { "xml_parser_unittest.cc", ] - if (is_chromeos) { + if (is_ash) { sources += [ "ble_scan_parser_impl_unittest.cc" ] } @@ -103,7 +109,7 @@ fuzzer_test("xml_parser_fuzzer") { seed_corpus = "//third_party/libxml/fuzz/seed_corpus" } -if (is_chromeos) { +if (is_ash) { fuzzer_test("ble_scan_parser_fuzzer") { sources = [ "ble_scan_parser_impl_fuzzer.cc" ] deps = [ ":lib" ] diff --git a/chromium/services/data_decoder/DEPS b/chromium/services/data_decoder/DEPS index bd2835402c1..3ff21a837ac 100644 --- a/chromium/services/data_decoder/DEPS +++ b/chromium/services/data_decoder/DEPS @@ -8,5 +8,6 @@ include_rules = [ "+third_party/libxml/chromium", "+third_party/blink/public", "+third_party/skia", + "+third_party/zlib", "+ui/gfx", ] diff --git a/chromium/services/data_decoder/DIR_METADATA b/chromium/services/data_decoder/DIR_METADATA new file mode 100644 index 00000000000..1af08c8f9de --- /dev/null +++ b/chromium/services/data_decoder/DIR_METADATA @@ -0,0 +1,12 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Mojo>Bindings" +} +team_email: "chrome-security@google.com"
\ No newline at end of file diff --git a/chromium/services/data_decoder/OWNERS b/chromium/services/data_decoder/OWNERS index 915d04e6886..e645ed54020 100644 --- a/chromium/services/data_decoder/OWNERS +++ b/chromium/services/data_decoder/OWNERS @@ -1,4 +1,2 @@ palmer@chromium.org -rsesek@chromium.org -# COMPONENT: Internals>Mojo>Bindings -# TEAM: chrome-security@google.com +rsesek@chromium.org
\ No newline at end of file diff --git a/chromium/services/data_decoder/README.md b/chromium/services/data_decoder/README.md index e84b2a13460..a99ab4a79c9 100644 --- a/chromium/services/data_decoder/README.md +++ b/chromium/services/data_decoder/README.md @@ -1,3 +1,5 @@ The data_decoder service exists to facilitate safe data decoding within an isolated sandboxed process. +NOTE: Protobuf is considered robust enough to decode untrusted input even +without sandboxing. So you won't find a protobuf decoder in this service. diff --git a/chromium/services/data_decoder/data_decoder_service.cc b/chromium/services/data_decoder/data_decoder_service.cc index 96f6a3aeb85..f9238bb5b8b 100644 --- a/chromium/services/data_decoder/data_decoder_service.cc +++ b/chromium/services/data_decoder/data_decoder_service.cc @@ -11,17 +11,19 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "components/web_package/web_bundle_parser_factory.h" #include "mojo/public/cpp/bindings/generic_pending_receiver.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" +#include "services/data_decoder/gzipper.h" #include "services/data_decoder/json_parser_impl.h" #include "services/data_decoder/public/mojom/image_decoder.mojom.h" #include "services/data_decoder/web_bundler.h" #include "services/data_decoder/xml_parser.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "services/data_decoder/ble_scan_parser_impl.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) #if !defined(OS_IOS) #include "services/data_decoder/image_decoder_impl.h" @@ -91,6 +93,11 @@ void DataDecoderService::BindWebBundler( } } +void DataDecoderService::BindGzipper( + mojo::PendingReceiver<mojom::Gzipper> receiver) { + mojo::MakeSelfOwnedReceiver(std::make_unique<Gzipper>(), std::move(receiver)); +} + #ifdef OS_CHROMEOS void DataDecoderService::BindBleScanParser( mojo::PendingReceiver<mojom::BleScanParser> receiver) { diff --git a/chromium/services/data_decoder/data_decoder_service.h b/chromium/services/data_decoder/data_decoder_service.h index 3e079b2a9f4..8bd5b771931 100644 --- a/chromium/services/data_decoder/data_decoder_service.h +++ b/chromium/services/data_decoder/data_decoder_service.h @@ -12,6 +12,7 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "services/data_decoder/public/mojom/data_decoder_service.mojom.h" +#include "services/data_decoder/public/mojom/gzipper.mojom.h" #include "services/data_decoder/public/mojom/image_decoder.mojom.h" #include "services/data_decoder/public/mojom/json_parser.mojom.h" #include "services/data_decoder/public/mojom/web_bundler.mojom.h" @@ -76,6 +77,7 @@ class DataDecoderService : public mojom::DataDecoderService { receiver) override; void BindWebBundler( mojo::PendingReceiver<mojom::WebBundler> receiver) override; + void BindGzipper(mojo::PendingReceiver<mojom::Gzipper> receiver) override; #ifdef OS_CHROMEOS void BindBleScanParser( diff --git a/chromium/services/data_decoder/gzipper.cc b/chromium/services/data_decoder/gzipper.cc new file mode 100644 index 00000000000..c5275c3f25e --- /dev/null +++ b/chromium/services/data_decoder/gzipper.cc @@ -0,0 +1,48 @@ +// 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 "services/data_decoder/gzipper.h" + +#include "base/containers/span.h" +#include "base/strings/string_piece_forward.h" +#include "mojo/public/cpp/base/big_buffer.h" +#include "third_party/zlib/google/compression_utils.h" + +namespace data_decoder { + +namespace { + +mojo_base::BigBuffer StringToBuffer(const std::string& string) { + return base::as_bytes(base::make_span(string)); +} + +} // namespace + +Gzipper::Gzipper() = default; +Gzipper::~Gzipper() = default; + +void Gzipper::Compress(mojo_base::BigBuffer data, CompressCallback callback) { + // mojo_base::BigBuffer does not support resizing the backing storage. Output + // the result into a std::string and copy its contents into a BigBuffer. + std::string output; + if (!compression::GzipCompress(data, &output)) { + std::move(callback).Run(base::nullopt); + return; + } + + std::move(callback).Run(StringToBuffer(output)); +} + +void Gzipper::Uncompress(mojo_base::BigBuffer compressed_data, + UncompressCallback callback) { + mojo_base::BigBuffer output( + compression::GetUncompressedSize(compressed_data)); + if (!compression::GzipUncompress(compressed_data, output)) { + std::move(callback).Run(base::nullopt); + return; + } + std::move(callback).Run(std::move(output)); +} + +} // namespace data_decoder diff --git a/chromium/services/data_decoder/gzipper.h b/chromium/services/data_decoder/gzipper.h new file mode 100644 index 00000000000..39e07bc470b --- /dev/null +++ b/chromium/services/data_decoder/gzipper.h @@ -0,0 +1,28 @@ +// 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 SERVICES_DATA_DECODER_GZIPPER_H_ +#define SERVICES_DATA_DECODER_GZIPPER_H_ + +#include "services/data_decoder/public/mojom/gzipper.mojom.h" + +namespace data_decoder { + +class Gzipper : public mojom::Gzipper { + public: + Gzipper(); + ~Gzipper() override; + Gzipper(const Gzipper&) = delete; + Gzipper operator=(const Gzipper&) = delete; + + public: + // mojom::Gzipper: + void Compress(mojo_base::BigBuffer data, CompressCallback callback) override; + void Uncompress(mojo_base::BigBuffer compressed_data, + UncompressCallback callback) override; +}; + +} // namespace data_decoder + +#endif // SERVICES_DATA_DECODER_GZIPPER_H_ diff --git a/chromium/services/data_decoder/gzipper_unittest.cc b/chromium/services/data_decoder/gzipper_unittest.cc new file mode 100644 index 00000000000..e6c08fb3150 --- /dev/null +++ b/chromium/services/data_decoder/gzipper_unittest.cc @@ -0,0 +1,44 @@ +// 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 "services/data_decoder/gzipper.h" + +#include "base/callback.h" +#include "base/optional.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace data_decoder { + +namespace { + +void CopyResultCallback(base::Optional<mojo_base::BigBuffer>& output_result, + base::Optional<mojo_base::BigBuffer> result) { + output_result = std::move(result); +} + +using GzipperTest = testing::Test; + +} // namespace + +TEST_F(GzipperTest, CompressAndUncompress) { + Gzipper gzipper; + std::vector<uint8_t> input = {0x01, 0x01, 0x01, 0x02, 0x02, 0x02}; + base::Optional<mojo_base::BigBuffer> compressed; + gzipper.Compress(input, + base::BindOnce(&CopyResultCallback, std::ref(compressed))); + ASSERT_TRUE(compressed.has_value()); + EXPECT_THAT(base::make_span(*compressed), + testing::Not(testing::ElementsAreArray(base::make_span(input)))); + + base::Optional<mojo_base::BigBuffer> uncompressed; + gzipper.Uncompress( + std::move(*compressed), + base::BindOnce(&CopyResultCallback, std::ref(uncompressed))); + ASSERT_TRUE(uncompressed.has_value()); + EXPECT_THAT(base::make_span(*uncompressed), + testing::ElementsAreArray(base::make_span(input))); +} + +} // namespace data_decoder diff --git a/chromium/services/data_decoder/image_decoder_impl.cc b/chromium/services/data_decoder/image_decoder_impl.cc index 16677c88c0e..7d4eb9a98eb 100644 --- a/chromium/services/data_decoder/image_decoder_impl.cc +++ b/chromium/services/data_decoder/image_decoder_impl.cc @@ -7,6 +7,7 @@ #include <string.h> #include <utility> +#include "build/chromeos_buildflags.h" #include "skia/ext/image_operations.h" #include "third_party/blink/public/platform/web_data.h" @@ -14,7 +15,7 @@ #include "third_party/blink/public/web/web_image.h" #include "third_party/skia/include/core/SkBitmap.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "ui/gfx/codec/png_codec.h" #endif @@ -59,7 +60,7 @@ ImageDecoderImpl::ImageDecoderImpl() = default; ImageDecoderImpl::~ImageDecoderImpl() = default; -void ImageDecoderImpl::DecodeImage(const std::vector<uint8_t>& encoded_data, +void ImageDecoderImpl::DecodeImage(mojo_base::BigBuffer encoded_data, mojom::ImageCodec codec, bool shrink_to_fit, int64_t max_size_in_bytes, @@ -71,7 +72,7 @@ void ImageDecoderImpl::DecodeImage(const std::vector<uint8_t>& encoded_data, } SkBitmap decoded_image; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) if (codec == mojom::ImageCodec::ROBUST_PNG) { // Our robust PNG decoding is using libpng. if (encoded_data.size()) { @@ -82,7 +83,7 @@ void ImageDecoderImpl::DecodeImage(const std::vector<uint8_t>& encoded_data, } } } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) if (codec == mojom::ImageCodec::DEFAULT) { decoded_image = blink::WebImage::FromData( blink::WebData(reinterpret_cast<const char*>(encoded_data.data()), @@ -96,7 +97,7 @@ void ImageDecoderImpl::DecodeImage(const std::vector<uint8_t>& encoded_data, std::move(callback).Run(decoded_image); } -void ImageDecoderImpl::DecodeAnimation(const std::vector<uint8_t>& encoded_data, +void ImageDecoderImpl::DecodeAnimation(mojo_base::BigBuffer encoded_data, bool shrink_to_fit, int64_t max_size_in_bytes, DecodeAnimationCallback callback) { diff --git a/chromium/services/data_decoder/image_decoder_impl.h b/chromium/services/data_decoder/image_decoder_impl.h index 7c43c170737..5ab5bd23ca5 100644 --- a/chromium/services/data_decoder/image_decoder_impl.h +++ b/chromium/services/data_decoder/image_decoder_impl.h @@ -19,13 +19,13 @@ class ImageDecoderImpl : public mojom::ImageDecoder { ~ImageDecoderImpl() override; // Overridden from mojom::ImageDecoder: - void DecodeImage(const std::vector<uint8_t>& encoded_data, + void DecodeImage(mojo_base::BigBuffer encoded_data, mojom::ImageCodec codec, bool shrink_to_fit, int64_t max_size_in_bytes, const gfx::Size& desired_image_frame_size, DecodeImageCallback callback) override; - void DecodeAnimation(const std::vector<uint8_t>& encoded_data, + void DecodeAnimation(mojo_base::BigBuffer encoded_data, bool shrink_to_fit, int64_t max_size_in_bytes, DecodeAnimationCallback callback) override; diff --git a/chromium/services/data_decoder/public/cpp/BUILD.gn b/chromium/services/data_decoder/public/cpp/BUILD.gn index b973d0969ad..df5d677e626 100644 --- a/chromium/services/data_decoder/public/cpp/BUILD.gn +++ b/chromium/services/data_decoder/public/cpp/BUILD.gn @@ -22,8 +22,6 @@ component("service_provider") { } source_set("cpp") { - set_sources_assignment_filter([]) - public = [ "data_decoder.h", "json_sanitizer.h", diff --git a/chromium/services/data_decoder/public/cpp/data_decoder.cc b/chromium/services/data_decoder/public/cpp/data_decoder.cc index ede4c5537a5..469459f9edd 100644 --- a/chromium/services/data_decoder/public/cpp/data_decoder.cc +++ b/chromium/services/data_decoder/public/cpp/data_decoder.cc @@ -4,11 +4,13 @@ #include "services/data_decoder/public/cpp/data_decoder.h" +#include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/no_destructor.h" #include "base/task/thread_pool.h" #include "base/time/time.h" #include "build/build_config.h" +#include "services/data_decoder/public/mojom/gzipper.mojom.h" #include "services/data_decoder/public/mojom/json_parser.mojom.h" #include "services/data_decoder/public/mojom/xml_parser.mojom.h" @@ -39,14 +41,14 @@ constexpr base::TimeDelta kServiceProcessIdleTimeoutDefault{ // *either* the successful response handler *or* the parsers's disconnection // handler. This also owns a Remote<T> which is kept alive for the duration of // the request. -template <typename T> -class ValueParseRequest : public base::RefCounted<ValueParseRequest<T>> { +template <typename T, typename V> +class ValueParseRequest : public base::RefCounted<ValueParseRequest<T, V>> { public: - explicit ValueParseRequest(DataDecoder::ValueParseCallback callback) + explicit ValueParseRequest(DataDecoder::ResultCallback<V> callback) : callback_(std::move(callback)) {} mojo::Remote<T>& remote() { return remote_; } - DataDecoder::ValueParseCallback& callback() { return callback_; } + DataDecoder::ResultCallback<V>& callback() { return callback_; } // Creates a pipe and binds it to the remote(), and sets up the // disconnect handler to invoke callback() with an error. @@ -57,13 +59,17 @@ class ValueParseRequest : public base::RefCounted<ValueParseRequest<T>> { return receiver; } + void OnServiceValue(base::Optional<V> value) { + OnServiceValueOrError(std::move(value), base::nullopt); + } + // Handles a successful parse from the service. - void OnServiceValueOrError(base::Optional<base::Value> value, + void OnServiceValueOrError(base::Optional<V> value, const base::Optional<std::string>& error) { if (!callback()) return; - DataDecoder::ValueOrError result; + DataDecoder::ResultOrError<V> result; if (value) result.value = std::move(value); else @@ -90,13 +96,13 @@ class ValueParseRequest : public base::RefCounted<ValueParseRequest<T>> { void OnRemoteDisconnected() { if (callback()) { std::move(callback()) - .Run(DataDecoder::ValueOrError::Error( + .Run(DataDecoder::ResultOrError<V>::Error( "Data Decoder terminated unexpectedly")); } } mojo::Remote<T> remote_; - DataDecoder::ValueParseCallback callback_; + DataDecoder::ResultCallback<V> callback_; DISALLOW_COPY_AND_ASSIGN(ValueParseRequest); }; @@ -120,26 +126,6 @@ void BindInProcessService( } // namespace -DataDecoder::ValueOrError::ValueOrError() = default; - -DataDecoder::ValueOrError::ValueOrError(ValueOrError&&) = default; - -DataDecoder::ValueOrError::~ValueOrError() = default; - -// static -DataDecoder::ValueOrError DataDecoder::ValueOrError::Value(base::Value value) { - ValueOrError result; - result.value = std::move(value); - return result; -} - -DataDecoder::ValueOrError DataDecoder::ValueOrError::Error( - const std::string& error) { - ValueOrError result; - result.error = error; - return result; -} - DataDecoder::DataDecoder() : idle_timeout_(kServiceProcessIdleTimeoutDefault) {} DataDecoder::DataDecoder(base::TimeDelta idle_timeout) @@ -197,13 +183,15 @@ void DataDecoder::ParseJson(const std::string& json, }, std::move(callback))); #else - auto request = base::MakeRefCounted<ValueParseRequest<mojom::JsonParser>>( - std::move(callback)); + auto request = + base::MakeRefCounted<ValueParseRequest<mojom::JsonParser, base::Value>>( + std::move(callback)); GetService()->BindJsonParser(request->BindRemote()); request->remote()->Parse( - json, base::BindOnce( - &ValueParseRequest<mojom::JsonParser>::OnServiceValueOrError, - request)); + json, + base::BindOnce(&ValueParseRequest<mojom::JsonParser, + base::Value>::OnServiceValueOrError, + request)); #endif } @@ -226,13 +214,15 @@ void DataDecoder::ParseJsonIsolated(const std::string& json, void DataDecoder::ParseXml(const std::string& xml, ValueParseCallback callback) { - auto request = base::MakeRefCounted<ValueParseRequest<mojom::XmlParser>>( - std::move(callback)); + auto request = + base::MakeRefCounted<ValueParseRequest<mojom::XmlParser, base::Value>>( + std::move(callback)); GetService()->BindXmlParser(request->BindRemote()); request->remote()->Parse( - xml, base::BindOnce( - &ValueParseRequest<mojom::XmlParser>::OnServiceValueOrError, - request)); + xml, + base::BindOnce(&ValueParseRequest<mojom::XmlParser, + base::Value>::OnServiceValueOrError, + request)); } // static @@ -252,4 +242,30 @@ void DataDecoder::ParseXmlIsolated(const std::string& xml, std::move(decoder), std::move(callback))); } +void DataDecoder::GzipCompress(base::span<const uint8_t> data, + GzipperCallback callback) { + auto request = base::MakeRefCounted< + ValueParseRequest<mojom::Gzipper, mojo_base::BigBuffer>>( + std::move(callback)); + GetService()->BindGzipper(request->BindRemote()); + request->remote()->Compress( + data, + base::BindOnce(&ValueParseRequest<mojom::Gzipper, + mojo_base::BigBuffer>::OnServiceValue, + request)); +} + +void DataDecoder::GzipUncompress(base::span<const uint8_t> data, + GzipperCallback callback) { + auto request = base::MakeRefCounted< + ValueParseRequest<mojom::Gzipper, mojo_base::BigBuffer>>( + std::move(callback)); + GetService()->BindGzipper(request->BindRemote()); + request->remote()->Uncompress( + data, + base::BindOnce(&ValueParseRequest<mojom::Gzipper, + mojo_base::BigBuffer>::OnServiceValue, + request)); +} + } // namespace data_decoder diff --git a/chromium/services/data_decoder/public/cpp/data_decoder.h b/chromium/services/data_decoder/public/cpp/data_decoder.h index c7da858a8f3..efae22099ef 100644 --- a/chromium/services/data_decoder/public/cpp/data_decoder.h +++ b/chromium/services/data_decoder/public/cpp/data_decoder.h @@ -7,7 +7,7 @@ #include <string> -#include "base/callback.h" +#include "base/callback_forward.h" #include "base/macros.h" #include "base/optional.h" #include "base/values.h" @@ -48,22 +48,37 @@ class DataDecoder { explicit DataDecoder(base::TimeDelta idle_timeout); ~DataDecoder(); - // The result of a Parse*() call that can return either a Value or an error - // string. Exactly one of either |value| or |error| will have a value when - // returned by either operation. - struct ValueOrError { - ValueOrError(); - ValueOrError(ValueOrError&&); - ~ValueOrError(); - - static ValueOrError Value(base::Value value); - static ValueOrError Error(const std::string& error); - - base::Optional<base::Value> value; + // The result of a service call that can return either a value of type T or an + // error string. Exactly one of either |value| or |error| will have a value + // when returned by either operation. + template <typename T> + struct ResultOrError { + ResultOrError() = default; + ResultOrError(ResultOrError&&) = default; + ~ResultOrError() = default; + + static ResultOrError Value(T value) { + ResultOrError<T> result; + result.value = std::move(value); + return result; + } + static ResultOrError Error(const std::string& error) { + ResultOrError<T> result; + result.error = error; + return result; + } + + base::Optional<T> value; base::Optional<std::string> error; }; + using ValueOrError = ResultOrError<base::Value>; + + template <typename T> + using ResultCallback = base::OnceCallback<void(ResultOrError<T>)>; using ValueParseCallback = base::OnceCallback<void(ValueOrError)>; + using GzipperCallback = + base::OnceCallback<void(ResultOrError<mojo_base::BigBuffer>)>; // Returns a raw interface to the service instance. This launches an instance // of the service process if possible on the current platform, or returns a @@ -101,6 +116,20 @@ class DataDecoder { static void ParseXmlIsolated(const std::string& xml, ValueParseCallback callback); + // Compresses potentially unsafe |data| using this DataDecoder's service + // instance. + // + // Note that |callback| will only be called if the parsing operation succeeds + // or fails before this DataDecoder is destroyed. + void GzipCompress(base::span<const uint8_t> data, GzipperCallback callback); + + // Uncompresses potentially unsafe |data| using this DataDecoder's service + // instance. + // + // Note that |callback| will only be called if the parsing operation succeeds + // or fails before this DataDecoder is destroyed. + void GzipUncompress(base::span<const uint8_t> data, GzipperCallback callback); + private: // The amount of idle time to tolerate on a DataDecoder instance. If the // instance is unused for this period of time, the underlying service process diff --git a/chromium/services/data_decoder/public/cpp/decode_image.cc b/chromium/services/data_decoder/public/cpp/decode_image.cc index 9b86c6bc1fc..e8cc70625a4 100644 --- a/chromium/services/data_decoder/public/cpp/decode_image.cc +++ b/chromium/services/data_decoder/public/cpp/decode_image.cc @@ -7,7 +7,6 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" #include "base/callback_helpers.h" #include "base/debug/dump_without_crashing.h" #include "mojo/public/cpp/bindings/remote.h" diff --git a/chromium/services/data_decoder/public/cpp/json_sanitizer_unittest.cc b/chromium/services/data_decoder/public/cpp/json_sanitizer_unittest.cc index cbc0d7da423..8eb8fab9bdc 100644 --- a/chromium/services/data_decoder/public/cpp/json_sanitizer_unittest.cc +++ b/chromium/services/data_decoder/public/cpp/json_sanitizer_unittest.cc @@ -10,7 +10,7 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/values.h" #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h" diff --git a/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser_unittest.cc b/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser_unittest.cc index c6877ede504..d7a0ae25f86 100644 --- a/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser_unittest.cc +++ b/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser_unittest.cc @@ -7,7 +7,7 @@ #include <memory> #include <string> -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/optional.h" diff --git a/chromium/services/data_decoder/public/cpp/safe_xml_parser_unittest.cc b/chromium/services/data_decoder/public/cpp/safe_xml_parser_unittest.cc index 3e992892a7e..0e094c0e167 100644 --- a/chromium/services/data_decoder/public/cpp/safe_xml_parser_unittest.cc +++ b/chromium/services/data_decoder/public/cpp/safe_xml_parser_unittest.cc @@ -7,7 +7,7 @@ #include <memory> #include "base/bind.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/values.h" #include "build/build_config.h" #include "services/data_decoder/xml_parser.h" diff --git a/chromium/services/data_decoder/public/mojom/BUILD.gn b/chromium/services/data_decoder/public/mojom/BUILD.gn index 59dac08b913..05eecfe8511 100644 --- a/chromium/services/data_decoder/public/mojom/BUILD.gn +++ b/chromium/services/data_decoder/public/mojom/BUILD.gn @@ -2,11 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//mojo/public/tools/bindings/mojom.gni") mojom("mojom") { sources = [ "data_decoder_service.mojom", + "gzipper.mojom", "image_decoder.mojom", "json_parser.mojom", "web_bundler.mojom", @@ -22,7 +24,7 @@ mojom("mojom") { "//url/mojom:url_mojom_gurl", ] - if (is_chromeos) { + if (is_ash) { sources += [ "ble_scan_parser.mojom" ] public_deps += [ "//device/bluetooth/public/mojom" ] } diff --git a/chromium/services/data_decoder/public/mojom/data_decoder_service.mojom b/chromium/services/data_decoder/public/mojom/data_decoder_service.mojom index 77f2f1d421e..9d86019ac4d 100644 --- a/chromium/services/data_decoder/public/mojom/data_decoder_service.mojom +++ b/chromium/services/data_decoder/public/mojom/data_decoder_service.mojom @@ -5,6 +5,7 @@ module data_decoder.mojom; import "components/web_package/mojom/web_bundle_parser.mojom"; +import "services/data_decoder/public/mojom/gzipper.mojom"; import "services/data_decoder/public/mojom/image_decoder.mojom"; import "services/data_decoder/public/mojom/json_parser.mojom"; import "services/data_decoder/public/mojom/web_bundler.mojom"; @@ -31,6 +32,10 @@ interface DataDecoderService { // Binds an interface which can be used to generate a Web Bundle. BindWebBundler(pending_receiver<WebBundler> receiver); + // Binds an interface which can be used to compress and decompress data using + // gzip. + BindGzipper(pending_receiver<Gzipper> receiver); + // Binds an interface which can be used to parse raw BLE advertising packet // data. [EnableIf=is_chromeos] diff --git a/chromium/services/data_decoder/public/mojom/gzipper.mojom b/chromium/services/data_decoder/public/mojom/gzipper.mojom new file mode 100644 index 00000000000..d03ba86df57 --- /dev/null +++ b/chromium/services/data_decoder/public/mojom/gzipper.mojom @@ -0,0 +1,20 @@ +// 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. + +module data_decoder.mojom; + +import "mojo/public/mojom/base/big_buffer.mojom"; + +// An interface that lets callers compress and uncompress data using gzip. +interface Gzipper { + // Compresses |data| using gzip and returns it as |compressed_data|. Returns + // null if compression fails. + Compress(mojo_base.mojom.BigBuffer data) + => (mojo_base.mojom.BigBuffer? compressed_data); + + // Uncompresses |compressed_data| using gzip and returns it as |data|. Returns + // null if uncompression fails. + Uncompress(mojo_base.mojom.BigBuffer compressed_data) + => (mojo_base.mojom.BigBuffer? data); +}; diff --git a/chromium/services/data_decoder/public/mojom/image_decoder.mojom b/chromium/services/data_decoder/public/mojom/image_decoder.mojom index 741e39c629f..f51ed52c7c8 100644 --- a/chromium/services/data_decoder/public/mojom/image_decoder.mojom +++ b/chromium/services/data_decoder/public/mojom/image_decoder.mojom @@ -4,6 +4,7 @@ module data_decoder.mojom; +import "mojo/public/mojom/base/big_buffer.mojom"; import "mojo/public/mojom/base/time.mojom"; import "skia/public/mojom/bitmap.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; @@ -30,8 +31,9 @@ interface ImageDecoder { // If the total size of the decoded image data in bytes exceeds // |max_size_in_bytes| and |shrink_to_fit| is false, this is treated as a // decoding failure and the |decoded_image| response is null. - DecodeImage(array<uint8> encoded_data, ImageCodec codec, bool shrink_to_fit, - int64 max_size_in_bytes, gfx.mojom.Size desired_image_frame_size) + DecodeImage(mojo_base.mojom.BigBuffer encoded_data, ImageCodec codec, + bool shrink_to_fit, int64 max_size_in_bytes, + gfx.mojom.Size desired_image_frame_size) => (skia.mojom.Bitmap? decoded_image); // Decodes the image in |encoded_data|. This will return all frames in the @@ -44,7 +46,7 @@ interface ImageDecoder { // If the total size of the decoded image data in bytes exceeds // |max_size_in_bytes| and |shrink_to_fit| is false, this is treated as a // decoding failure and the |decoded_image| response is null. - DecodeAnimation(array<uint8> encoded_data, bool shrink_to_fit, + DecodeAnimation(mojo_base.mojom.BigBuffer encoded_data, bool shrink_to_fit, int64 max_size_in_bytes) => (array<AnimationFrame> decoded_image); }; diff --git a/chromium/services/device/BUILD.gn b/chromium/services/device/BUILD.gn index 42661eeb373..30451f38302 100644 --- a/chromium/services/device/BUILD.gn +++ b/chromium/services/device/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") import("//testing/test.gni") @@ -9,13 +10,6 @@ if (is_android) { import("//build/config/android/rules.gni") } -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - is_serial_enabled_platform = is_win || ((is_linux || is_chromeos) && use_udev) || is_mac @@ -70,7 +64,7 @@ source_set("lib") { ] } - if (is_chromeos && use_dbus) { + if (is_ash && use_dbus) { deps += [ "//services/device/bluetooth:bluetooth_system", "//services/device/media_transfer_protocol", @@ -81,7 +75,7 @@ source_set("lib") { deps += [ "//services/device/serial" ] } - if (chromeos_is_browser_only) { + if (is_lacros) { deps += [ "//chromeos/crosapi/mojom", "//chromeos/lacros", @@ -109,8 +103,6 @@ component("binder_overrides") { defines = [ "IS_DEVICE_SERVICE_BINDER_OVERRIDES_IMPL" ] } -is_linux_without_udev = (is_linux || is_chromeos) && !use_udev - source_set("perftests") { testonly = true @@ -131,7 +123,6 @@ source_set("tests") { testonly = true sources = [ - "battery/battery_status_manager_win_unittest.cc", "battery/battery_status_service_unittest.cc", "generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer_unittest.cc", "generic_sensor/fake_platform_sensor_and_provider.cc", @@ -144,13 +135,10 @@ source_set("tests") { "generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles_unittest.cc", "generic_sensor/orientation_test_data.h", "generic_sensor/platform_sensor_and_provider_unittest.cc", - "generic_sensor/platform_sensor_and_provider_unittest_win.cc", "generic_sensor/platform_sensor_fusion_unittest.cc", - "generic_sensor/platform_sensor_provider_unittest_android.cc", "generic_sensor/platform_sensor_util_unittest.cc", "generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope_unittest.cc", "generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_unittest.cc", - "geolocation/core_location_provider_unittest.mm", "geolocation/geolocation_provider_impl_unittest.cc", "geolocation/geolocation_service_unittest.cc", "geolocation/location_arbitrator_unittest.cc", @@ -158,9 +146,7 @@ source_set("tests") { "geolocation/position_cache_impl_unittest.cc", "geolocation/public_ip_address_geolocator_unittest.cc", "geolocation/public_ip_address_location_notifier_unittest.cc", - "geolocation/wifi_data_provider_chromeos_unittest.cc", "geolocation/wifi_data_provider_common_unittest.cc", - "geolocation/wifi_data_provider_win_unittest.cc", "geolocation/wifi_polling_policy_unittest.cc", "power_monitor/power_monitor_message_broadcaster_unittest.cc", "public/cpp/power_monitor/power_monitor_broadcast_source_unittest.cc", @@ -174,6 +160,7 @@ source_set("tests") { "//base", "//base/test:test_support", "//base/third_party/dynamic_annotations", + "//build:chromeos_buildflags", "//device/base/synchronization", "//mojo/public/cpp/bindings", "//net", @@ -192,12 +179,28 @@ source_set("tests") { "//testing/gtest", ] - if (!is_linux_without_udev) { + if (is_android) { + sources += [ "generic_sensor/platform_sensor_provider_unittest_android.cc" ] + } + + if (is_ash) { + sources += [ "geolocation/wifi_data_provider_chromeos_unittest.cc" ] + } + + if (is_win) { + sources += [ + "battery/battery_status_manager_win_unittest.cc", + "generic_sensor/platform_sensor_and_provider_unittest_win.cc", + "geolocation/wifi_data_provider_win_unittest.cc", + ] + } + + if (is_linux && use_udev) { sources += [ "generic_sensor/platform_sensor_and_provider_unittest_linux.cc" ] } - if (is_linux && !is_chromeos && use_dbus) { + if ((is_linux || is_lacros) && use_dbus) { sources += [ "battery/battery_status_manager_linux_unittest.cc", "geolocation/wifi_data_provider_linux_unittest.cc", @@ -205,9 +208,15 @@ source_set("tests") { deps += [ "//dbus:test_support" ] } - if (is_chromeos) { - sources += [ "fingerprint/fingerprint_chromeos_unittest.cc" ] + if (is_ash) { + sources += [ + "fingerprint/fingerprint_chromeos_unittest.cc", + "generic_sensor/platform_sensor_chromeos_unittest.cc", + "generic_sensor/platform_sensor_provider_chromeos_unittest.cc", + ] deps += [ + "//chromeos/components/sensors:sensors", + "//chromeos/components/sensors:test_support", "//chromeos/dbus:test_support", "//chromeos/dbus/biod:test_support", "//chromeos/network:test_support", @@ -241,15 +250,17 @@ source_set("tests") { "//services/device/vibration", ] - if (!is_linux_without_udev) { + if ((!is_linux && !is_chromeos) || use_udev) { sources += [ "hid/hid_connection_impl_unittest.cc", - "hid/input_service_linux_unittest.cc", "hid/test_report_descriptors.cc", "hid/test_report_descriptors.h", "public/cpp/hid/hid_device_filter_unittest.cc", "public/cpp/hid/hid_report_descriptor_unittest.cc", ] + if (is_linux || is_chromeos) { + sources += [ "hid/input_service_linux_unittest.cc" ] + } if (!is_fuchsia) { # Fuchsia does not currently implement HidService. sources += [ "hid/hid_service_unittest.cc" ] @@ -268,12 +279,15 @@ source_set("tests") { if (is_serial_enabled_platform) { sources += [ "serial/bluetooth_serial_port_impl_unittest.cc", - "serial/serial_device_enumerator_linux_unittest.cc", "serial/serial_device_enumerator_unittest.cc", "serial/serial_port_impl_unittest.cc", "serial/serial_port_manager_impl_unittest.cc", ] + if (is_linux || is_chromeos) { + sources += [ "serial/serial_device_enumerator_linux_unittest.cc" ] + } + if (is_posix) { sources += [ "serial/serial_io_handler_posix_unittest.cc" ] } @@ -319,6 +333,10 @@ source_set("tests") { } } + if (is_mac) { + sources += [ "geolocation/core_location_provider_unittest.mm" ] + } + # UsbContext is a libusb-specific object. if (is_mac || is_win) { sources += [ "usb/usb_context_unittest.cc" ] diff --git a/chromium/services/device/DIR_METADATA b/chromium/services/device/DIR_METADATA new file mode 100644 index 00000000000..f4708701ba3 --- /dev/null +++ b/chromium/services/device/DIR_METADATA @@ -0,0 +1,12 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Services>Device" +} +team_email: "device-dev@chromium.org"
\ No newline at end of file diff --git a/chromium/services/device/OWNERS b/chromium/services/device/OWNERS index 84015199176..d78bf3cc594 100644 --- a/chromium/services/device/OWNERS +++ b/chromium/services/device/OWNERS @@ -1,8 +1,4 @@ -# TEAM: device-dev@chromium.org - blundell@chromium.org mattreynolds@chromium.org reillyg@chromium.org rockot@google.com - -# COMPONENT: Internals>Services>Device diff --git a/chromium/services/device/battery/BUILD.gn b/chromium/services/device/battery/BUILD.gn index a4b395df50e..ad135fd73f1 100644 --- a/chromium/services/device/battery/BUILD.gn +++ b/chromium/services/device/battery/BUILD.gn @@ -2,16 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") import("//mojo/public/tools/bindings/mojom.gni") -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - # On android, BatteryManager mojo interface is implemented directly in Java. if (!is_android) { source_set("battery") { @@ -24,14 +18,6 @@ if (!is_android) { "battery_monitor_impl.cc", "battery_monitor_impl.h", "battery_status_manager.h", - "battery_status_manager_chromeos.cc", - "battery_status_manager_default.cc", - "battery_status_manager_linux-inl.h", - "battery_status_manager_linux.cc", - "battery_status_manager_linux.h", - "battery_status_manager_mac.cc", - "battery_status_manager_win.cc", - "battery_status_manager_win.h", "battery_status_service.cc", "battery_status_service.h", ] @@ -44,38 +30,34 @@ if (!is_android) { "//mojo/public/cpp/bindings", ] - if (is_chromeos) { + if (is_ash) { configs += [ "//build/config/linux/dbus" ] deps += [ "//chromeos/dbus/power", "//chromeos/dbus/power:power_manager_proto", ] - sources -= [ - "battery_status_manager_default.cc", + sources += [ "battery_status_manager_chromeos.cc" ] + } else if (is_linux && use_dbus) { + configs += [ "//build/config/linux/dbus" ] + deps += [ "//dbus" ] + sources += [ + "battery_status_manager_linux-inl.h", "battery_status_manager_linux.cc", + "battery_status_manager_linux.h", ] - } - - if (is_linux && !is_chromeos) { - if (use_dbus) { - configs += [ "//build/config/linux/dbus" ] - deps += [ "//dbus" ] - sources -= [ "battery_status_manager_default.cc" ] - } else { - sources -= [ "battery_status_manager_linux.cc" ] - } - } - - if (is_mac) { - sources -= [ "battery_status_manager_default.cc" ] + } else if (is_mac) { + sources += [ "battery_status_manager_mac.cc" ] frameworks = [ "CoreFoundation.framework", "IOKit.framework", ] - } - - if (is_win) { - sources -= [ "battery_status_manager_default.cc" ] + } else if (is_win) { + sources += [ + "battery_status_manager_win.cc", + "battery_status_manager_win.h", + ] + } else { + sources += [ "battery_status_manager_default.cc" ] } } } diff --git a/chromium/services/device/battery/battery_status_manager_linux.cc b/chromium/services/device/battery/battery_status_manager_linux.cc index 1a5cbf7895b..429294e30ff 100644 --- a/chromium/services/device/battery/battery_status_manager_linux.cc +++ b/chromium/services/device/battery/battery_status_manager_linux.cc @@ -14,7 +14,7 @@ #include <vector> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "base/message_loop/message_pump_type.h" #include "base/metrics/histogram_macros.h" diff --git a/chromium/services/device/bluetooth/DIR_METADATA b/chromium/services/device/bluetooth/DIR_METADATA new file mode 100644 index 00000000000..4435d72de6f --- /dev/null +++ b/chromium/services/device/bluetooth/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "IO>Bluetooth" +}
\ No newline at end of file diff --git a/chromium/services/device/bluetooth/OWNERS b/chromium/services/device/bluetooth/OWNERS index c88c0647818..1df589a4cf0 100644 --- a/chromium/services/device/bluetooth/OWNERS +++ b/chromium/services/device/bluetooth/OWNERS @@ -1,3 +1,2 @@ ortuno@chromium.org -reillyg@chromium.org -# COMPONENT: IO>Bluetooth +reillyg@chromium.org
\ No newline at end of file diff --git a/chromium/services/device/bluetooth/bluetooth_system_unittest.cc b/chromium/services/device/bluetooth/bluetooth_system_unittest.cc index 3d55e47b4e0..fbb1f7815ec 100644 --- a/chromium/services/device/bluetooth/bluetooth_system_unittest.cc +++ b/chromium/services/device/bluetooth/bluetooth_system_unittest.cc @@ -17,7 +17,7 @@ #include "base/run_loop.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "device/bluetooth/dbus/bluetooth_adapter_client.h" #include "device/bluetooth/dbus/bluetooth_device_client.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h" @@ -377,18 +377,6 @@ class DEVICE_BLUETOOTH_EXPORT TestBluetoothAdapterClient std::move(callback).Run(base::nullopt); } - void PauseDiscovery(const dbus::ObjectPath& object_path, - base::OnceClosure callback, - ErrorCallback error_callback) override { - NOTIMPLEMENTED(); - } - - void UnpauseDiscovery(const dbus::ObjectPath& object_path, - base::OnceClosure callback, - ErrorCallback error_callback) override { - NOTIMPLEMENTED(); - } - void RemoveDevice(const dbus::ObjectPath& object_path, const dbus::ObjectPath& device_path, base::OnceClosure callback, @@ -417,6 +405,14 @@ class DEVICE_BLUETOOTH_EXPORT TestBluetoothAdapterClient NOTIMPLEMENTED(); } + void ConnectDevice(const dbus::ObjectPath& object_path, + const std::string& address, + const base::Optional<AddressType>& address_type, + ConnectDeviceCallback callback, + ErrorCallback error_callback) override { + NOTIMPLEMENTED(); + } + private: // Keeps track of how many times methods have been called. struct CallCounts { diff --git a/chromium/services/device/device_service.cc b/chromium/services/device/device_service.cc index 0afeae0feff..81763809953 100644 --- a/chromium/services/device/device_service.cc +++ b/chromium/services/device/device_service.cc @@ -183,7 +183,7 @@ DeviceService::DeviceService( #endif DeviceService::~DeviceService() { -#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) +#if !defined(OS_ANDROID) && !BUILDFLAG(IS_ASH) // NOTE: We don't call this on Chrome OS due to https://crbug.com/856771, as // Shutdown() implicitly depends on DBusThreadManager, which may already be // destroyed by the time DeviceService is destroyed. Fortunately on Chrome OS @@ -255,7 +255,7 @@ void DeviceService::BindHidManager( } #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void DeviceService::BindBluetoothSystemFactory( mojo::PendingReceiver<mojom::BluetoothSystemFactory> receiver) { BluetoothSystemFactory::CreateFactory(std::move(receiver)); diff --git a/chromium/services/device/device_service.h b/chromium/services/device/device_service.h index c5e950b095c..7614955ffa0 100644 --- a/chromium/services/device/device_service.h +++ b/chromium/services/device/device_service.h @@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "services/device/geolocation/geolocation_provider.h" @@ -45,7 +46,7 @@ #include "services/device/public/mojom/hid.mojom.h" #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "services/device/media_transfer_protocol/mtp_device_manager.h" #include "services/device/public/mojom/bluetooth_system.mojom.h" #endif @@ -165,7 +166,7 @@ class DeviceService : public mojom::DeviceService { mojo::PendingReceiver<mojom::HidManager> receiver) override; #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void BindBluetoothSystemFactory( mojo::PendingReceiver<mojom::BluetoothSystemFactory> receiver) override; void BindMtpManager( @@ -225,7 +226,8 @@ class DeviceService : public mojom::DeviceService { service_manager::InterfaceProvider* GetJavaInterfaceProvider(); // InterfaceProvider that is bound to the Java-side interface registry. - service_manager::InterfaceProvider java_interface_provider_; + service_manager::InterfaceProvider java_interface_provider_{ + base::ThreadTaskRunnerHandle::Get()}; bool java_interface_provider_initialized_; @@ -243,7 +245,7 @@ class DeviceService : public mojom::DeviceService { scoped_refptr<base::SequencedTaskRunner> serial_port_manager_task_runner_; #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) std::unique_ptr<MtpDeviceManager> mtp_device_manager_; #endif diff --git a/chromium/services/device/fingerprint/BUILD.gn b/chromium/services/device/fingerprint/BUILD.gn index 5a39e5bdf84..fdbbde548d7 100644 --- a/chromium/services/device/fingerprint/BUILD.gn +++ b/chromium/services/device/fingerprint/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") component("fingerprint") { @@ -19,7 +20,7 @@ component("fingerprint") { "//mojo/public/cpp/bindings", ] - if (is_chromeos) { + if (is_ash) { sources += [ "fingerprint_chromeos.cc", "fingerprint_chromeos.h", diff --git a/chromium/services/device/fingerprint/DIR_METADATA b/chromium/services/device/fingerprint/DIR_METADATA new file mode 100644 index 00000000000..378d0eb2037 --- /dev/null +++ b/chromium/services/device/fingerprint/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "UI>Shell>LockScreen" +}
\ No newline at end of file diff --git a/chromium/services/device/fingerprint/OWNERS b/chromium/services/device/fingerprint/OWNERS index e8d012e5666..66371f043c5 100644 --- a/chromium/services/device/fingerprint/OWNERS +++ b/chromium/services/device/fingerprint/OWNERS @@ -1,3 +1,2 @@ xiaoyinh@chromium.org -sammiequon@chromium.org -# COMPONENT: UI>Shell>LockScreen +sammiequon@chromium.org
\ No newline at end of file diff --git a/chromium/services/device/fingerprint/fingerprint_chromeos.cc b/chromium/services/device/fingerprint/fingerprint_chromeos.cc index da0779c5063..b73c0a89fc7 100644 --- a/chromium/services/device/fingerprint/fingerprint_chromeos.cc +++ b/chromium/services/device/fingerprint/fingerprint_chromeos.cc @@ -7,7 +7,6 @@ #include <string.h> #include "base/bind.h" -#include "base/bind_helpers.h" #include "base/callback_helpers.h" #include "chromeos/dbus/biod/biod_client.h" #include "dbus/object_path.h" diff --git a/chromium/services/device/generic_sensor/BUILD.gn b/chromium/services/device/generic_sensor/BUILD.gn index 6b81ce41e09..b2d85ab0563 100644 --- a/chromium/services/device/generic_sensor/BUILD.gn +++ b/chromium/services/device/generic_sensor/BUILD.gn @@ -8,13 +8,6 @@ if (is_android) { import("//build/config/android/rules.gni") # For generate_jni(). } -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - source_set("generic_sensor") { visibility = [ "//services/device:*" ] @@ -25,8 +18,6 @@ source_set("generic_sensor") { "generic_sensor_consts.h", "linear_acceleration_fusion_algorithm_using_accelerometer.cc", "linear_acceleration_fusion_algorithm_using_accelerometer.h", - "linux/sensor_data_linux.cc", - "linux/sensor_data_linux.h", "orientation_euler_angles_fusion_algorithm_using_quaternion.cc", "orientation_euler_angles_fusion_algorithm_using_quaternion.h", "orientation_quaternion_fusion_algorithm_using_euler_angles.cc", @@ -35,37 +26,16 @@ source_set("generic_sensor") { "orientation_util.h", "platform_sensor.cc", "platform_sensor.h", - "platform_sensor_accelerometer_mac.cc", - "platform_sensor_accelerometer_mac.h", - "platform_sensor_ambient_light_mac.cc", - "platform_sensor_ambient_light_mac.h", - "platform_sensor_android.cc", - "platform_sensor_android.h", "platform_sensor_fusion.cc", "platform_sensor_fusion.h", "platform_sensor_fusion_algorithm.cc", "platform_sensor_fusion_algorithm.h", - "platform_sensor_linux.cc", - "platform_sensor_linux.h", "platform_sensor_provider.cc", "platform_sensor_provider.h", - "platform_sensor_provider_android.cc", - "platform_sensor_provider_android.h", "platform_sensor_provider_base.cc", "platform_sensor_provider_base.h", - "platform_sensor_provider_mac.cc", - "platform_sensor_provider_mac.h", - "platform_sensor_provider_win.cc", - "platform_sensor_provider_win.h", - "platform_sensor_reader_linux.cc", - "platform_sensor_reader_linux.h", - "platform_sensor_reader_win.cc", - "platform_sensor_reader_win.h", - "platform_sensor_reader_win_base.h", "platform_sensor_util.cc", "platform_sensor_util.h", - "platform_sensor_win.cc", - "platform_sensor_win.h", "relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.cc", "relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.h", "relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope.cc", @@ -78,6 +48,7 @@ source_set("generic_sensor") { deps = [ "//base", + "//build:chromeos_buildflags", "//device/base/synchronization", "//services/device/public/cpp:device_features", "//ui/gfx/geometry:geometry", @@ -86,10 +57,24 @@ source_set("generic_sensor") { public_deps = [ "//services/device/public/cpp/generic_sensor" ] if (is_android) { + sources += [ + "platform_sensor_android.cc", + "platform_sensor_android.h", + "platform_sensor_provider_android.cc", + "platform_sensor_provider_android.h", + ] deps += [ ":jni_headers" ] } if (is_mac) { + sources += [ + "platform_sensor_accelerometer_mac.cc", + "platform_sensor_accelerometer_mac.h", + "platform_sensor_ambient_light_mac.cc", + "platform_sensor_ambient_light_mac.h", + "platform_sensor_provider_mac.cc", + "platform_sensor_provider_mac.h", + ] deps += [ "//third_party/sudden_motion_sensor" ] frameworks = [ "CoreFoundation.framework", @@ -97,26 +82,61 @@ source_set("generic_sensor") { ] } - if (use_udev) { + if (is_linux) { + sources += [ + "linux/sensor_data_linux.cc", + "linux/sensor_data_linux.h", + "platform_sensor_linux.cc", + "platform_sensor_linux.h", + "platform_sensor_reader_linux.cc", + "platform_sensor_reader_linux.h", + ] + if (use_udev) { + deps += [ + "//device/base", + "//device/udev_linux", + ] + + sources += [ + "linux/sensor_device_manager.cc", + "linux/sensor_device_manager.h", + "platform_sensor_provider_linux.cc", + "platform_sensor_provider_linux.h", + "platform_sensor_provider_linux_base.cc", + "platform_sensor_provider_linux_base.h", + ] + } + } + + if (is_chromeos) { deps += [ - "//device/base", - "//device/udev_linux", + "//chromeos/components/sensors", + "//chromeos/components/sensors/mojom", ] sources += [ - "linux/sensor_device_manager.cc", - "linux/sensor_device_manager.h", - "platform_sensor_provider_linux.cc", - "platform_sensor_provider_linux.h", + "platform_sensor_chromeos.cc", + "platform_sensor_chromeos.h", + "platform_sensor_provider_chromeos.cc", + "platform_sensor_provider_chromeos.h", + "platform_sensor_provider_linux_base.cc", + "platform_sensor_provider_linux_base.h", ] } if (is_win) { sources += [ + "platform_sensor_provider_win.cc", + "platform_sensor_provider_win.h", "platform_sensor_provider_winrt.cc", "platform_sensor_provider_winrt.h", + "platform_sensor_reader_win.cc", + "platform_sensor_reader_win.h", + "platform_sensor_reader_win_base.h", "platform_sensor_reader_winrt.cc", "platform_sensor_reader_winrt.h", + "platform_sensor_win.cc", + "platform_sensor_win.h", ] libs = [ diff --git a/chromium/services/device/generic_sensor/DEPS b/chromium/services/device/generic_sensor/DEPS index a89688afaa6..8c07c5d1ffc 100644 --- a/chromium/services/device/generic_sensor/DEPS +++ b/chromium/services/device/generic_sensor/DEPS @@ -1,5 +1,6 @@ include_rules = [ "+device/base/synchronization", + "+chromeos/components/sensors", "+services/device/generic_sensor/jni_headers", "+services/device/public/cpp/device_features.h", "+third_party/sudden_motion_sensor", diff --git a/chromium/services/device/generic_sensor/DIR_METADATA b/chromium/services/device/generic_sensor/DIR_METADATA new file mode 100644 index 00000000000..395c6238f9b --- /dev/null +++ b/chromium/services/device/generic_sensor/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Blink>Sensor" +}
\ No newline at end of file diff --git a/chromium/services/device/generic_sensor/OWNERS b/chromium/services/device/generic_sensor/OWNERS index 3fd6380ca2e..d97025031c0 100644 --- a/chromium/services/device/generic_sensor/OWNERS +++ b/chromium/services/device/generic_sensor/OWNERS @@ -1,6 +1,2 @@ -juncai@chromium.org raphael.kubo.da.costa@intel.com timvolodine@chromium.org - -# COMPONENT: Blink>Sensor -# TEAM: device-dev@chromium.org diff --git a/chromium/services/device/generic_sensor/README.md b/chromium/services/device/generic_sensor/README.md index 606bbbd8b94..7e539b6b013 100644 --- a/chromium/services/device/generic_sensor/README.md +++ b/chromium/services/device/generic_sensor/README.md @@ -62,7 +62,7 @@ Support for the SensorTypes defined by the Mojo interface is summarized in this table. An empty cell indicates that the sensor type is not supported on that platform. -| SensorType | Android | Linux | macOS | Windows | +| SensorType | Android | Linux and ChromeOS | macOS | Windows | | --------------------------------- | ------------------------- | ------------------------------------- | ------------------------------------- | ----------------------------------------- | | AMBIENT_LIGHT | TYPE_LIGHT | in_illuminance | AppleLMUController | Yes | | PROXIMITY | | | | | @@ -103,13 +103,15 @@ For ABSOLUTE_ORIENTATION_QUATERNION, the following sensor fallback is used: For RELATIVE_ORIENTATION_EULER_ANGLES, converts the data produced by RELATIVE_ORIENTATION_QUATERNION to euler angles. -### Linux (and Chrome OS) +### Linux and Chrome OS -Sensors are implemented by reading values from the IIO subsystem. The values in -the "Linux" column of the table above are the prefix of the sysfs files Chrome -searches for to provide data for a SensorType. The -ABSOLUTE_ORIENTATION_EULER_ANGLES sensor type is provided by interpreting the -value that can be read from the ACCELEROMETER and MAGNETOMETER. The +On Linux, sensors are implemented by reading values from the IIO subsystem. +The values in the "Linux" column of the table above are the prefix of the +sysfs files Chrome searches for to provide data for a SensorType. +On ChromeOS, sensors are implemented with Mojo connections to IIO Service, a +CrOS daemon that provides sensors' data to other applications. +The ABSOLUTE_ORIENTATION_EULER_ANGLES sensor type is provided by interpreting +the value that can be read from the ACCELEROMETER and MAGNETOMETER. The ABSOLUTE_ORIENTATION_QUATERNION sensor type is provided by interpreting the value that can be read from the ABSOLUTE_ORIENTATION_EULER_ANGLES. The RELATIVE_ORIENTATION_EULER_ANGLES sensor type is provided by interpreting the diff --git a/chromium/services/device/generic_sensor/generic_sensor_service_unittest.cc b/chromium/services/device/generic_sensor/generic_sensor_service_unittest.cc index 5e670db44d5..cf21ca4cc9a 100644 --- a/chromium/services/device/generic_sensor/generic_sensor_service_unittest.cc +++ b/chromium/services/device/generic_sensor/generic_sensor_service_unittest.cc @@ -4,7 +4,7 @@ #include "base/barrier_closure.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" diff --git a/chromium/services/device/generic_sensor/linux/sensor_data_linux.cc b/chromium/services/device/generic_sensor/linux/sensor_data_linux.cc index af15f85dbf9..11b0af5f631 100644 --- a/chromium/services/device/generic_sensor/linux/sensor_data_linux.cc +++ b/chromium/services/device/generic_sensor/linux/sensor_data_linux.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/system/sys_info.h" #include "base/version.h" +#include "build/chromeos_buildflags.h" #include "services/device/generic_sensor/generic_sensor_consts.h" #include "services/device/public/cpp/generic_sensor/sensor_reading.h" #include "services/device/public/cpp/generic_sensor/sensor_traits.h" @@ -18,12 +19,6 @@ namespace { using mojom::SensorType; -#if defined(OS_CHROMEOS) -// ChromeOS kernel version, when axes were changed to XYZ. Before 3.18, -// they were YXZ. -const char kChangedAxisKernelVersion[] = "3.18.0"; -#endif - void InitAmbientLightSensorData(SensorPathsLinux* data) { std::vector<std::string> file_names{ "in_illuminance0_input", "in_illuminance_input", "in_illuminance0_raw", @@ -39,35 +34,16 @@ void InitAmbientLightSensorData(SensorPathsLinux* data) { SensorTraits<SensorType::AMBIENT_LIGHT>::kDefaultFrequency); } -// Depending on a kernel version, CrOS has a different axes plane. -// Before 3.18 it was YXZ and after XYZ. -// TODO(maksims): Track crbug.com/501184. 3.14 will have the same sensor stack -// as 3.18 has, which will probably change the order of axes. void MaybeCheckKernelVersionAndAssignFileNames( const std::vector<std::string>& file_names_x, const std::vector<std::string>& file_names_y, const std::vector<std::string>& file_names_z, SensorPathsLinux* data) { -#if defined(OS_CHROMEOS) - const base::Version checked_kernel_version(kChangedAxisKernelVersion); - DCHECK(checked_kernel_version.IsValid()); - const base::Version current_version(base::SysInfo::OperatingSystemVersion()); - if (current_version.IsValid() && current_version < checked_kernel_version) { - data->sensor_file_names.push_back(file_names_y); - data->sensor_file_names.push_back(file_names_x); - } else { - data->sensor_file_names.push_back(file_names_x); - data->sensor_file_names.push_back(file_names_y); - } - data->sensor_file_names.push_back(file_names_z); -#else data->sensor_file_names.push_back(file_names_x); data->sensor_file_names.push_back(file_names_y); data->sensor_file_names.push_back(file_names_z); -#endif } -// TODO(maksims): add support for lid accelerometer on chromeos. void InitAccelerometerSensorData(SensorPathsLinux* data) { std::vector<std::string> file_names_x{"in_accel_x_base_raw", "in_accel_x_raw"}; @@ -76,17 +52,6 @@ void InitAccelerometerSensorData(SensorPathsLinux* data) { std::vector<std::string> file_names_z{"in_accel_z_base_raw", "in_accel_z_raw"}; -#if defined(OS_CHROMEOS) - data->sensor_scale_name = "in_accel_base_scale"; - data->sensor_frequency_file_name = "in_accel_base_sampling_frequency"; - data->apply_scaling_func = base::BindRepeating( - [](double scaling_value, double offset, SensorReading& reading) { - double scaling = base::kMeanGravityDouble / scaling_value; - reading.accel.x = scaling * (reading.accel.x + offset); - reading.accel.y = scaling * (reading.accel.y + offset); - reading.accel.z = scaling * (reading.accel.z + offset); - }); -#else data->sensor_scale_name = "in_accel_scale"; data->sensor_offset_file_name = "in_accel_offset"; data->sensor_frequency_file_name = "in_accel_sampling_frequency"; @@ -97,7 +62,6 @@ void InitAccelerometerSensorData(SensorPathsLinux* data) { reading.accel.y = -scaling_value * (reading.accel.y + offset); reading.accel.z = -scaling_value * (reading.accel.z + offset); }); -#endif MaybeCheckKernelVersionAndAssignFileNames(file_names_x, file_names_y, file_names_z, data); @@ -112,19 +76,6 @@ void InitGyroscopeSensorData(SensorPathsLinux* data) { "in_anglvel_y_raw"}; std::vector<std::string> file_names_z{"in_anglvel_z_base_raw", "in_anglvel_z_raw"}; -#if defined(OS_CHROMEOS) - data->sensor_scale_name = "in_anglvel_base_scale"; - data->sensor_frequency_file_name = "in_anglvel_base_frequency"; - data->apply_scaling_func = base::BindRepeating( - [](double scaling_value, double offset, SensorReading& reading) { - double scaling = - gfx::DegToRad(base::kMeanGravityDouble) / scaling_value; - // Adapt CrOS reading values to generic sensor api specs. - reading.gyro.x = -scaling * (reading.gyro.x + offset); - reading.gyro.y = -scaling * (reading.gyro.y + offset); - reading.gyro.z = -scaling * (reading.gyro.z + offset); - }); -#else data->sensor_scale_name = "in_anglvel_scale"; data->sensor_offset_file_name = "in_anglvel_offset"; data->sensor_frequency_file_name = "in_anglvel_sampling_frequency"; @@ -134,7 +85,6 @@ void InitGyroscopeSensorData(SensorPathsLinux* data) { reading.gyro.y = scaling_value * (reading.gyro.y + offset); reading.gyro.z = scaling_value * (reading.gyro.z + offset); }); -#endif MaybeCheckKernelVersionAndAssignFileNames(file_names_x, file_names_y, file_names_z, data); diff --git a/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc b/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc index 7d33e74f4e0..a30e3de33f1 100644 --- a/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc +++ b/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc @@ -12,10 +12,11 @@ #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" +#include "build/chromeos_buildflags.h" #include "services/device/generic_sensor/generic_sensor_consts.h" #include "services/device/generic_sensor/linux/sensor_data_linux.h" #include "services/device/generic_sensor/linux/sensor_device_manager.h" @@ -579,7 +580,7 @@ TEST_F(PlatformSensorAndProviderLinuxTest, SensorReadingSharedBuffer* buffer = static_cast<SensorReadingSharedBuffer*>(mapping.get()); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) double scaling = base::kMeanGravityDouble / kAccelerometerScalingValue; EXPECT_THAT(buffer->reading.accel.x, RoundAccelerometerValue(scaling * sensor_values[0])); @@ -619,7 +620,7 @@ TEST_F(PlatformSensorAndProviderLinuxTest, CheckLinearAcceleration) { mojo::ScopedSharedBufferMapping mapping = handle->MapAtOffset( sizeof(SensorReadingSharedBuffer), SensorReadingSharedBuffer::GetOffset(SensorType::LINEAR_ACCELERATION)); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // CrOS has a different axes plane and scale, see crbug.com/501184. double sensor_values[3] = {0, 0, 1}; #else @@ -689,7 +690,7 @@ TEST_F(PlatformSensorAndProviderLinuxTest, CheckGyroscopeReadingConversion) { SensorReadingSharedBuffer* buffer = static_cast<SensorReadingSharedBuffer*>(mapping.get()); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) double scaling = gfx::DegToRad(base::kMeanGravityDouble) / kGyroscopeScalingValue; EXPECT_THAT(buffer->reading.gyro.x, diff --git a/chromium/services/device/generic_sensor/platform_sensor_chromeos.cc b/chromium/services/device/generic_sensor/platform_sensor_chromeos.cc new file mode 100644 index 00000000000..c7894f58d0f --- /dev/null +++ b/chromium/services/device/generic_sensor/platform_sensor_chromeos.cc @@ -0,0 +1,387 @@ +// 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 "services/device/generic_sensor/platform_sensor_chromeos.h" + +#include <iterator> +#include <utility> + +#include "base/bind.h" +#include "base/ranges/algorithm.h" +#include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "base/time/time.h" +#include "services/device/public/cpp/generic_sensor/sensor_traits.h" + +namespace device { + +namespace { + +constexpr char kAxes[][3] = {"_x", "_y", "_z"}; + +} // namespace + +PlatformSensorChromeOS::PlatformSensorChromeOS( + int32_t iio_device_id, + mojom::SensorType type, + SensorReadingSharedBuffer* reading_buffer, + PlatformSensorProvider* provider, + double scale, + mojo::Remote<chromeos::sensors::mojom::SensorDevice> sensor_device_remote) + : PlatformSensor(type, reading_buffer, provider), + iio_device_id_(iio_device_id), + default_configuration_( + PlatformSensorConfiguration(GetSensorMaxAllowedFrequency(type))), + scale_(scale), + sensor_device_remote_(std::move(sensor_device_remote)) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(sensor_device_remote_.is_bound()); + DCHECK_GT(scale_, 0.0); + + sensor_device_remote_.set_disconnect_handler(base::BindOnce( + &PlatformSensorChromeOS::ResetOnError, weak_factory_.GetWeakPtr())); + + sensor_device_remote_->SetTimeout(0); + + sensor_device_remote_->GetAllChannelIds( + base::BindOnce(&PlatformSensorChromeOS::GetAllChannelIdsCallback, + weak_factory_.GetWeakPtr())); +} + +PlatformSensorChromeOS::~PlatformSensorChromeOS() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +mojom::ReportingMode PlatformSensorChromeOS::GetReportingMode() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (GetType() == mojom::SensorType::AMBIENT_LIGHT) + return mojom::ReportingMode::ON_CHANGE; + return mojom::ReportingMode::CONTINUOUS; +} + +void PlatformSensorChromeOS::OnSampleUpdated( + const base::flat_map<int32_t, int64_t>& sample) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!channel_indices_.empty()); + + if (sample.size() != channel_indices_.size()) { + LOG(WARNING) << "Invalid sample with size: " << sample.size(); + OnErrorOccurred(chromeos::sensors::mojom::ObserverErrorType::READ_FAILED); + return; + } + + for (auto index : channel_indices_) { + if (!base::Contains(sample, index)) { + LOG(ERROR) << "Missing channel: " << iio_channel_ids_[index] + << " in sample."; + OnErrorOccurred(chromeos::sensors::mojom::ObserverErrorType::READ_FAILED); + return; + } + } + + SensorReading reading; + + switch (GetType()) { + case mojom::SensorType::AMBIENT_LIGHT: + DCHECK_EQ(channel_indices_.size(), 2u); + reading.als.value = GetScaledValue(sample.at(channel_indices_[0])); + break; + + case mojom::SensorType::PROXIMITY: + DCHECK_EQ(channel_indices_.size(), 2u); + reading.proximity.value = GetScaledValue(sample.at(channel_indices_[0])); + break; + + case mojom::SensorType::ACCELEROMETER: + DCHECK_EQ(channel_indices_.size(), 4u); + reading.accel.x = GetScaledValue(sample.at(channel_indices_[0])); + reading.accel.y = GetScaledValue(sample.at(channel_indices_[1])); + reading.accel.z = GetScaledValue(sample.at(channel_indices_[2])); + break; + + case mojom::SensorType::GYROSCOPE: + DCHECK_EQ(channel_indices_.size(), 4u); + reading.gyro.x = GetScaledValue(sample.at(channel_indices_[0])); + reading.gyro.y = GetScaledValue(sample.at(channel_indices_[1])); + reading.gyro.z = GetScaledValue(sample.at(channel_indices_[2])); + break; + + case mojom::SensorType::MAGNETOMETER: + DCHECK_EQ(channel_indices_.size(), 4u); + reading.magn.x = GetScaledValue(sample.at(channel_indices_[0])); + reading.magn.y = GetScaledValue(sample.at(channel_indices_[1])); + reading.magn.z = GetScaledValue(sample.at(channel_indices_[2])); + break; + + default: + break; + } + + reading.raw.timestamp = + base::TimeDelta::FromNanoseconds(sample.at(channel_indices_.back())) + .InSecondsF(); + + UpdateSharedBufferAndNotifyClients(reading); +} + +void PlatformSensorChromeOS::OnErrorOccurred( + chromeos::sensors::mojom::ObserverErrorType type) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + switch (type) { + case chromeos::sensors::mojom::ObserverErrorType::ALREADY_STARTED: + LOG(ERROR) << "Sensor " << iio_device_id_ + << ": Another observer has already started to read samples"; + ResetOnError(); + break; + + case chromeos::sensors::mojom::ObserverErrorType::FREQUENCY_INVALID: + LOG(ERROR) << "Sensor " << iio_device_id_ + << ": Observer started with an invalid frequency"; + ResetOnError(); + break; + + case chromeos::sensors::mojom::ObserverErrorType::NO_ENABLED_CHANNELS: + LOG(ERROR) << "Sensor " << iio_device_id_ + << ": Observer started with no channels enabled"; + SetChannelsEnabled(); + break; + + case chromeos::sensors::mojom::ObserverErrorType::SET_FREQUENCY_IO_FAILED: + LOG(ERROR) << "Sensor " << iio_device_id_ + << ": Failed to set frequency to the physical device"; + break; + + case chromeos::sensors::mojom::ObserverErrorType::GET_FD_FAILED: + LOG(ERROR) << "Sensor " << iio_device_id_ + << ": Failed to get the device's fd to poll on"; + break; + + case chromeos::sensors::mojom::ObserverErrorType::READ_FAILED: + LOG(ERROR) << "Sensor " << iio_device_id_ << ": Failed to read a sample"; + break; + + case chromeos::sensors::mojom::ObserverErrorType::READ_TIMEOUT: + LOG(ERROR) << "Sensor " << iio_device_id_ << ": A read timed out"; + break; + + default: + LOG(ERROR) << "Sensor " << iio_device_id_ << ": error " + << static_cast<int>(type); + break; + } +} + +bool PlatformSensorChromeOS::StartSensor( + const PlatformSensorConfiguration& configuration) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!sensor_device_remote_.is_bound()) { + LOG(WARNING) << "Unbound sensor_device_remote_, skipping StartSensor."; + return false; + } + + if (configuration.frequency() <= 0.0) { + LOG(ERROR) << "Invalid frequency: " << configuration.frequency() + << " in sensor with id: " << iio_device_id_; + return false; + } + + if (receiver_.is_bound() && + configuration.frequency() == current_configuration_.frequency()) { + // Nothing to do. + return true; + } + + current_configuration_ = configuration; + StartReadingIfReady(); + return true; +} + +void PlatformSensorChromeOS::StopSensor() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + sensor_device_remote_.reset(); + receiver_.reset(); +} + +bool PlatformSensorChromeOS::CheckSensorConfiguration( + const PlatformSensorConfiguration& configuration) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return configuration.frequency() > 0 && + configuration.frequency() <= default_configuration_.frequency(); +} + +PlatformSensorConfiguration PlatformSensorChromeOS::GetDefaultConfiguration() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return default_configuration_; +} + +void PlatformSensorChromeOS::ResetOnError() { + LOG(ERROR) << "ResetOnError of sensor with id: " << iio_device_id_; + NotifySensorError(); + sensor_device_remote_.reset(); + receiver_.reset(); +} + +void PlatformSensorChromeOS::StartReadingIfReady() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(sensor_device_remote_.is_bound()); + + if (required_channel_ids_.empty() || + current_configuration_.frequency() <= 0.0) { + // Not ready yet. + return; + } + + UpdateSensorDeviceFrequency(); + + if (receiver_.is_bound()) + return; + + sensor_device_remote_->StartReadingSamples(BindNewPipeAndPassRemote()); +} + +mojo::PendingRemote<chromeos::sensors::mojom::SensorDeviceSamplesObserver> +PlatformSensorChromeOS::BindNewPipeAndPassRemote() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!receiver_.is_bound()); + auto pending_remote = receiver_.BindNewPipeAndPassRemote(task_runner_); + + receiver_.set_disconnect_handler( + base::BindOnce(&PlatformSensorChromeOS::OnObserverDisconnect, + weak_factory_.GetWeakPtr())); + return pending_remote; +} + +void PlatformSensorChromeOS::OnObserverDisconnect() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(receiver_.is_bound()); + + LOG(ERROR) << "On Observer Disconnect"; + receiver_.reset(); + + // Try to restart reading. + if (sensor_device_remote_.is_bound()) + StartReadingIfReady(); +} + +void PlatformSensorChromeOS::SetRequiredChannels() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(required_channel_ids_.empty()); // Should only be called once. + + base::Optional<std::string> axes_prefix = base::nullopt; + switch (GetType()) { + case mojom::SensorType::AMBIENT_LIGHT: + required_channel_ids_.push_back(chromeos::sensors::mojom::kLightChannel); + break; + + case mojom::SensorType::ACCELEROMETER: + axes_prefix = chromeos::sensors::mojom::kAccelerometerChannel; + break; + + case mojom::SensorType::GYROSCOPE: + axes_prefix = chromeos::sensors::mojom::kGyroscopeChannel; + break; + + case mojom::SensorType::MAGNETOMETER: + axes_prefix = chromeos::sensors::mojom::kMagnetometerChannel; + break; + + default: + break; + } + + if (axes_prefix.has_value()) { + for (const auto* axis : kAxes) + required_channel_ids_.push_back(axes_prefix.value() + std::string(axis)); + } + + required_channel_ids_.push_back(chromeos::sensors::mojom::kTimestampChannel); +} + +void PlatformSensorChromeOS::GetAllChannelIdsCallback( + const std::vector<std::string>& iio_channel_ids) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + SetRequiredChannels(); + DCHECK(!required_channel_ids_.empty()); + + iio_channel_ids_ = iio_channel_ids; + + for (const std::string& channel : required_channel_ids_) { + auto it = base::ranges::find(iio_channel_ids_, channel); + if (it == iio_channel_ids_.end()) { + LOG(ERROR) << "Missing channel: " << channel; + ResetOnError(); + return; + } + channel_indices_.push_back(std::distance(iio_channel_ids_.begin(), it)); + } + + DCHECK_EQ(channel_indices_.size(), required_channel_ids_.size()); + + SetChannelsEnabled(); + + StartReadingIfReady(); +} + +void PlatformSensorChromeOS::UpdateSensorDeviceFrequency() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(sensor_device_remote_.is_bound()); + + sensor_device_remote_->SetFrequency( + current_configuration_.frequency(), + base::BindOnce(&PlatformSensorChromeOS::SetFrequencyCallback, + weak_factory_.GetWeakPtr(), + current_configuration_.frequency())); +} + +void PlatformSensorChromeOS::SetFrequencyCallback(double target_frequency, + double result_frequency) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if ((target_frequency <= 0.0 && result_frequency <= 0.0) || + (target_frequency > 0.0 && result_frequency > 0.0)) { + return; + } + + LOG(ERROR) << "SetFrequency failed. Target frequency: " << target_frequency + << ", result requency: " << result_frequency; + ResetOnError(); +} + +void PlatformSensorChromeOS::SetChannelsEnabled() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!sensor_device_remote_.is_bound()) { + LOG(WARNING) + << "Unbound sensor_device_remote_, skipping SetChannelEnabled."; + return; + } + + sensor_device_remote_->SetChannelsEnabled( + channel_indices_, true, + base::BindOnce(&PlatformSensorChromeOS::SetChannelsEnabledCallback, + weak_factory_.GetWeakPtr())); +} + +void PlatformSensorChromeOS::SetChannelsEnabledCallback( + const std::vector<int32_t>& failed_indices) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (failed_indices.empty()) + return; + + for (int32_t index : failed_indices) { + LOG(ERROR) << "Failed to enable channel: " << iio_channel_ids_[index] + << " in sensor with id: " << iio_device_id_; + } + + ResetOnError(); +} + +double PlatformSensorChromeOS::GetScaledValue(int64_t value) const { + return value * scale_; +} + +} // namespace device diff --git a/chromium/services/device/generic_sensor/platform_sensor_chromeos.h b/chromium/services/device/generic_sensor/platform_sensor_chromeos.h new file mode 100644 index 00000000000..4b47107df08 --- /dev/null +++ b/chromium/services/device/generic_sensor/platform_sensor_chromeos.h @@ -0,0 +1,106 @@ +// 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 SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_CHROMEOS_H_ +#define SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_CHROMEOS_H_ + +#include <string> +#include <vector> + +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "base/sequence_checker.h" +#include "chromeos/components/sensors/mojom/sensor.mojom.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "services/device/generic_sensor/platform_sensor.h" + +namespace device { + +class PlatformSensorChromeOS + : public PlatformSensor, + public chromeos::sensors::mojom::SensorDeviceSamplesObserver { + public: + PlatformSensorChromeOS(int32_t iio_device_id, + mojom::SensorType type, + SensorReadingSharedBuffer* reading_buffer, + PlatformSensorProvider* provider, + double scale, + mojo::Remote<chromeos::sensors::mojom::SensorDevice> + sensor_device_remote); + PlatformSensorChromeOS(const PlatformSensorChromeOS&) = delete; + PlatformSensorChromeOS& operator=(const PlatformSensorChromeOS&) = delete; + + // PlatformSensor overrides: + // Only ambient light sensors' ReportingMode is ON_CHANGE. + mojom::ReportingMode GetReportingMode() override; + bool CheckSensorConfiguration( + const PlatformSensorConfiguration& configuration) override; + PlatformSensorConfiguration GetDefaultConfiguration() override; + + // chromeos::sensors::mojom::SensorDeviceSamplesObserver overrides: + void OnSampleUpdated(const base::flat_map<int32_t, int64_t>& sample) override; + void OnErrorOccurred( + chromeos::sensors::mojom::ObserverErrorType type) override; + + protected: + ~PlatformSensorChromeOS() override; + + // PlatformSensor overrides: + bool StartSensor(const PlatformSensorConfiguration& configuration) override; + void StopSensor() override; + + private: + void ResetOnError(); + + void StartReadingIfReady(); + + mojo::PendingRemote<chromeos::sensors::mojom::SensorDeviceSamplesObserver> + BindNewPipeAndPassRemote(); + void OnObserverDisconnect(); + + void SetRequiredChannels(); + void GetAllChannelIdsCallback( + const std::vector<std::string>& iio_channel_ids); + + void UpdateSensorDeviceFrequency(); + void SetFrequencyCallback(double target_frequency, double result_frequency); + + void SetChannelsEnabled(); + void SetChannelsEnabledCallback(const std::vector<int32_t>& failed_indices); + + double GetScaledValue(int64_t value) const; + + int32_t iio_device_id_; + const PlatformSensorConfiguration default_configuration_; + PlatformSensorConfiguration current_configuration_; + + double scale_; + + mojo::Remote<chromeos::sensors::mojom::SensorDevice> sensor_device_remote_; + + // The required channel ids for the sensor. + std::vector<std::string> required_channel_ids_; + + // The list of channel ids retrieved from iioservice. Use channels' indices + // in this list to identify them. + std::vector<std::string> iio_channel_ids_; + // Channel indices of |required_channel_ids_| to enable. + std::vector<int32_t> channel_indices_; + + // Stores previously read values that are used to + // determine whether the recent values are changed + // and IPC can be notified that updates are available. + SensorReading old_values_; + + mojo::Receiver<chromeos::sensors::mojom::SensorDeviceSamplesObserver> + receiver_{this}; + + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<PlatformSensorChromeOS> weak_factory_{this}; +}; + +} // namespace device + +#endif // SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_CHROMEOS_H_ diff --git a/chromium/services/device/generic_sensor/platform_sensor_chromeos_unittest.cc b/chromium/services/device/generic_sensor/platform_sensor_chromeos_unittest.cc new file mode 100644 index 00000000000..1273c6ddd79 --- /dev/null +++ b/chromium/services/device/generic_sensor/platform_sensor_chromeos_unittest.cc @@ -0,0 +1,371 @@ +// 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 "services/device/generic_sensor/platform_sensor_chromeos.h" + +#include <memory> +#include <utility> + +#include "base/memory/scoped_refptr.h" +#include "base/run_loop.h" +#include "base/test/gmock_callback_support.h" +#include "base/test/task_environment.h" +#include "base/time/time.h" +#include "chromeos/components/sensors/fake_sensor_device.h" +#include "services/device/generic_sensor/fake_platform_sensor_and_provider.h" +#include "services/device/generic_sensor/platform_sensor_util.h" +#include "services/device/public/cpp/generic_sensor/sensor_traits.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace device { + +namespace { + +constexpr int kFakeDeviceId = 1; + +constexpr char kAccelerometerChannels[][10] = {"accel_x", "accel_y", "accel_z"}; +constexpr char kGyroscopeChannels[][10] = {"anglvel_x", "anglvel_y", + "anglvel_z"}; +constexpr char kMagnetometerChannels[][10] = {"magn_x", "magn_y", "magn_z"}; + +constexpr double kScaleValue = 10.0; + +// The number of axes for which there are accelerometer readings. +constexpr uint32_t kNumberOfAxes = 3u; + +constexpr int64_t kFakeSampleData = 1; +constexpr int64_t kFakeAxesSampleData[] = {1, 2, 3}; +constexpr int64_t kFakeTimestampData = 163176689212344ll; + +} // namespace + +class PlatformSensorChromeOSTestBase { + protected: + void SetUpBase() { + provider_ = std::make_unique<FakePlatformSensorProvider>(); + + pending_receiver_ = sensor_device_remote_.BindNewPipeAndPassReceiver(); + } + + void InitSensorDevice( + std::vector<chromeos::sensors::FakeSensorDevice::ChannelData> + channels_data) { + sensor_device_ = std::make_unique<chromeos::sensors::FakeSensorDevice>( + std::move(channels_data)); + receiver_id_ = sensor_device_->AddReceiver(std::move(pending_receiver_)); + } + + void DisableFirstChannel() { + DCHECK(sensor_device_.get()); + + sensor_device_->SetChannelsEnabled( + {0}, false, + base::BindOnce( + &PlatformSensorChromeOSTestBase::SetChannelsEnabledCallback, + base::Unretained(this))); + } + + void SetChannelsEnabledCallback(const std::vector<int32_t>& failed_indices) { + EXPECT_EQ(failed_indices.size(), 0u); + } + + std::unique_ptr<chromeos::sensors::FakeSensorDevice> sensor_device_; + std::unique_ptr<FakePlatformSensorProvider> provider_; + scoped_refptr<PlatformSensorChromeOS> sensor_; + + mojo::ReceiverId receiver_id_; + mojo::Remote<chromeos::sensors::mojom::SensorDevice> sensor_device_remote_; + mojo::PendingReceiver<chromeos::sensors::mojom::SensorDevice> + pending_receiver_; + + base::test::SingleThreadTaskEnvironment task_environment; +}; + +class PlatformSensorChromeOSOneChannelTest + : public PlatformSensorChromeOSTestBase, + public ::testing::TestWithParam< + std::pair<mojom::SensorType, const char*>> { + protected: + void SetUp() override { + SetUpBase(); + + auto type = GetParam().first; + + sensor_ = base::MakeRefCounted<PlatformSensorChromeOS>( + kFakeDeviceId, type, provider_->GetSensorReadingBuffer(type), + provider_.get(), kScaleValue, std::move(sensor_device_remote_)); + + EXPECT_EQ(sensor_->GetReportingMode(), + type == mojom::SensorType::AMBIENT_LIGHT + ? mojom::ReportingMode::ON_CHANGE + : mojom::ReportingMode::CONTINUOUS); + EXPECT_EQ(sensor_->GetDefaultConfiguration().frequency(), + GetSensorMaxAllowedFrequency(type)); + } + + void SetChannels(const char channel[], bool set_first_channel) { + std::vector<chromeos::sensors::FakeSensorDevice::ChannelData> channels_data( + set_first_channel ? 2 : 1); + if (set_first_channel) { + channels_data.front().id = channel; + channels_data.front().sample_data = kFakeSampleData; + } + + channels_data.back().id = chromeos::sensors::mojom::kTimestampChannel; + channels_data.back().sample_data = kFakeTimestampData; + + InitSensorDevice(std::move(channels_data)); + } + + SensorReadingSingle& GetSensorReadingSingle(SensorReading& reading) { + switch (GetParam().first) { + case mojom::SensorType::AMBIENT_LIGHT: + return reading.als; + default: + LOG(FATAL) << "Invalid type: " << GetParam().first; + return reading.als; + } + } + + void GetRoundedSensorReadingSingle(SensorReadingSingle* reading_single) { + reading_single->value = kFakeSampleData * kScaleValue; + reading_single->timestamp = + base::TimeDelta::FromNanoseconds(kFakeTimestampData).InSecondsF(); + + // No need to do rounding for these types of sensors. + } + + void WaitForAndCheckReading( + testing::NiceMock<MockPlatformSensorClient>* client) { + base::RunLoop loop; + // Wait until a sample is received. + EXPECT_CALL(*client, OnSensorReadingChanged(GetParam().first)) + .WillOnce(base::test::RunOnceClosure(loop.QuitClosure())); + loop.Run(); + + SensorReading reading; + EXPECT_TRUE(sensor_->GetLatestReading(&reading)); + const auto& reading_single = GetSensorReadingSingle(reading); + + SensorReadingSingle rounded_reading_single; + GetRoundedSensorReadingSingle(&rounded_reading_single); + + EXPECT_EQ(reading_single.value, rounded_reading_single.value); + EXPECT_EQ(reading_single.timestamp, rounded_reading_single.timestamp); + } +}; + +TEST_P(PlatformSensorChromeOSOneChannelTest, MissingChannels) { + SetChannels(GetParam().second, false); + + auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(); + sensor_->AddClient(client.get()); + sensor_->StartListening(client.get(), + PlatformSensorConfiguration( + GetSensorMaxAllowedFrequency(GetParam().first))); + EXPECT_TRUE(sensor_->IsActiveForTesting()); + + EXPECT_CALL(*client.get(), OnSensorReadingChanged(GetParam().first)).Times(0); + // Wait until all tasks done and no samples updated. + base::RunLoop().RunUntilIdle(); + + sensor_->RemoveClient(client.get()); +} + +TEST_P(PlatformSensorChromeOSOneChannelTest, GetSamples) { + SetChannels(GetParam().second, true); + + auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(); + sensor_->AddClient(client.get()); + sensor_->StartListening(client.get(), + PlatformSensorConfiguration( + GetSensorMaxAllowedFrequency(GetParam().first))); + EXPECT_TRUE(sensor_->IsActiveForTesting()); + + WaitForAndCheckReading(client.get()); + + sensor_device_->ResetObserverRemote(receiver_id_); + + WaitForAndCheckReading(client.get()); + + DisableFirstChannel(); + sensor_device_->ResetObserverRemote(receiver_id_); + + EXPECT_CALL(*client.get(), OnSensorReadingChanged(GetParam().first)).Times(0); + // Wait until a sample without the first channel is received. + base::RunLoop().RunUntilIdle(); + // No reading updated. + + sensor_device_->RemoveReceiver(receiver_id_); + + base::RunLoop loop; + // Wait until the disconnect arrives at |sensor_|. + EXPECT_CALL(*client.get(), OnSensorError()) + .WillOnce(base::test::RunOnceClosure(loop.QuitClosure())); + loop.Run(); + + sensor_->RemoveClient(client.get()); +} + +INSTANTIATE_TEST_SUITE_P( + PlatformSensorChromeOSOneChannelTestRun, + PlatformSensorChromeOSOneChannelTest, + ::testing::Values(std::make_pair(mojom::SensorType::AMBIENT_LIGHT, + chromeos::sensors::mojom::kLightChannel))); + +class PlatformSensorChromeOSAxesTest + : public PlatformSensorChromeOSTestBase, + public ::testing::TestWithParam< + std::pair<mojom::SensorType, const char (*)[10]>> { + protected: + void SetUp() override { + SetUpBase(); + + auto type = GetParam().first; + + sensor_ = base::MakeRefCounted<PlatformSensorChromeOS>( + kFakeDeviceId, type, provider_->GetSensorReadingBuffer(type), nullptr, + kScaleValue, std::move(sensor_device_remote_)); + + EXPECT_EQ(sensor_->GetReportingMode(), mojom::ReportingMode::CONTINUOUS); + EXPECT_EQ(sensor_->GetDefaultConfiguration().frequency(), + GetSensorMaxAllowedFrequency(type)); + } + + void SetChannelsWithAxes(const char channels[][10], uint32_t num_of_axes) { + CHECK_LE(num_of_axes, kNumberOfAxes); + std::vector<chromeos::sensors::FakeSensorDevice::ChannelData> channels_data( + num_of_axes + 1); + for (uint32_t i = 0; i < num_of_axes; ++i) { + channels_data[i].id = channels[i]; + channels_data[i].sample_data = kFakeAxesSampleData[i]; + } + channels_data.back().id = chromeos::sensors::mojom::kTimestampChannel; + channels_data.back().sample_data = kFakeTimestampData; + + InitSensorDevice(std::move(channels_data)); + } + + SensorReadingXYZ& GetSensorReadingXYZ(SensorReading& reading) { + switch (GetParam().first) { + case mojom::SensorType::ACCELEROMETER: + return reading.accel; + case mojom::SensorType::GYROSCOPE: + return reading.gyro; + case mojom::SensorType::MAGNETOMETER: + return reading.magn; + default: + LOG(FATAL) << "Invalid type: " << GetParam().first; + return reading.accel; + } + } + + void GetRoundedSensorReadingXYZ(SensorReadingXYZ* reading_xyz) { + reading_xyz->x = kFakeAxesSampleData[0] * kScaleValue; + reading_xyz->y = kFakeAxesSampleData[1] * kScaleValue; + reading_xyz->z = kFakeAxesSampleData[2] * kScaleValue; + reading_xyz->timestamp = + base::TimeDelta::FromNanoseconds(kFakeTimestampData).InSecondsF(); + + switch (GetParam().first) { + case mojom::SensorType::ACCELEROMETER: + RoundAccelerometerReading(reading_xyz); + break; + case mojom::SensorType::GYROSCOPE: + RoundGyroscopeReading(reading_xyz); + break; + case mojom::SensorType::MAGNETOMETER: + break; + default: + LOG(FATAL) << "Invalid type: " << GetParam().first; + break; + } + } + + void WaitForAndCheckReading( + testing::NiceMock<MockPlatformSensorClient>* client) { + base::RunLoop loop; + // Wait until a sample is received. + EXPECT_CALL(*client, OnSensorReadingChanged(GetParam().first)) + .WillOnce(base::test::RunOnceClosure(loop.QuitClosure())); + loop.Run(); + + SensorReading reading; + EXPECT_TRUE(sensor_->GetLatestReading(&reading)); + const auto& reading_xyz = GetSensorReadingXYZ(reading); + + SensorReadingXYZ rounded_reading_xyz; + GetRoundedSensorReadingXYZ(&rounded_reading_xyz); + + EXPECT_EQ(reading_xyz.x, rounded_reading_xyz.x); + EXPECT_EQ(reading_xyz.y, rounded_reading_xyz.y); + EXPECT_EQ(reading_xyz.z, rounded_reading_xyz.z); + EXPECT_EQ(reading_xyz.timestamp, rounded_reading_xyz.timestamp); + } +}; + +TEST_P(PlatformSensorChromeOSAxesTest, MissingChannels) { + SetChannelsWithAxes(GetParam().second, kNumberOfAxes - 1); + + auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(); + sensor_->AddClient(client.get()); + sensor_->StartListening(client.get(), + PlatformSensorConfiguration( + GetSensorMaxAllowedFrequency(GetParam().first))); + EXPECT_TRUE(sensor_->IsActiveForTesting()); + + EXPECT_CALL(*client.get(), OnSensorReadingChanged(GetParam().first)).Times(0); + // Wait until all tasks done and no samples updated. + base::RunLoop().RunUntilIdle(); + + sensor_->RemoveClient(client.get()); +} + +TEST_P(PlatformSensorChromeOSAxesTest, GetSamples) { + SetChannelsWithAxes(GetParam().second, kNumberOfAxes); + + auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(); + sensor_->AddClient(client.get()); + sensor_->StartListening(client.get(), + PlatformSensorConfiguration( + GetSensorMaxAllowedFrequency(GetParam().first))); + EXPECT_TRUE(sensor_->IsActiveForTesting()); + + WaitForAndCheckReading(client.get()); + + sensor_device_->ResetObserverRemote(receiver_id_); + + WaitForAndCheckReading(client.get()); + + DisableFirstChannel(); + sensor_device_->ResetObserverRemote(receiver_id_); + + EXPECT_CALL(*client.get(), OnSensorReadingChanged(GetParam().first)).Times(0); + // Wait until a sample without the first channel is received. + base::RunLoop().RunUntilIdle(); + // No reading updated. + + sensor_device_->RemoveReceiver(receiver_id_); + + base::RunLoop loop; + // Wait until the disconnect arrives at |sensor_|. + EXPECT_CALL(*client.get(), OnSensorError()) + .WillOnce(base::test::RunOnceClosure(loop.QuitClosure())); + loop.Run(); + + sensor_->RemoveClient(client.get()); +} + +INSTANTIATE_TEST_SUITE_P( + PlatformSensorChromeOSAxesTestRun, + PlatformSensorChromeOSAxesTest, + ::testing::Values(std::make_pair(mojom::SensorType::ACCELEROMETER, + kAccelerometerChannels), + std::make_pair(mojom::SensorType::GYROSCOPE, + kGyroscopeChannels), + std::make_pair(mojom::SensorType::MAGNETOMETER, + kMagnetometerChannels))); + +} // namespace device diff --git a/chromium/services/device/generic_sensor/platform_sensor_fusion_unittest.cc b/chromium/services/device/generic_sensor/platform_sensor_fusion_unittest.cc index de9dfbb11bf..f7845c9b78d 100644 --- a/chromium/services/device/generic_sensor/platform_sensor_fusion_unittest.cc +++ b/chromium/services/device/generic_sensor/platform_sensor_fusion_unittest.cc @@ -5,7 +5,7 @@ #include <memory> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/test/task_environment.h" diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider.cc b/chromium/services/device/generic_sensor/platform_sensor_provider.cc index 1ab9deb8cd7..a50f733dae5 100644 --- a/chromium/services/device/generic_sensor/platform_sensor_provider.cc +++ b/chromium/services/device/generic_sensor/platform_sensor_provider.cc @@ -15,7 +15,9 @@ #include "services/device/generic_sensor/platform_sensor_provider_win.h" #include "services/device/generic_sensor/platform_sensor_provider_winrt.h" #include "services/device/public/cpp/device_features.h" -#elif (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV) +#elif defined(OS_CHROMEOS) +#include "services/device/generic_sensor/platform_sensor_provider_chromeos.h" +#elif defined(OS_LINUX) && defined(USE_UDEV) #include "services/device/generic_sensor/platform_sensor_provider_linux.h" #endif @@ -33,7 +35,9 @@ std::unique_ptr<PlatformSensorProvider> PlatformSensorProvider::Create() { } else { return std::make_unique<PlatformSensorProviderWin>(); } -#elif (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV) +#elif defined(OS_CHROMEOS) + return std::make_unique<PlatformSensorProviderChromeOS>(); +#elif defined(OS_LINUX) && defined(USE_UDEV) return std::make_unique<PlatformSensorProviderLinux>(); #else return nullptr; diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_chromeos.cc b/chromium/services/device/generic_sensor/platform_sensor_provider_chromeos.cc new file mode 100644 index 00000000000..c4a97a3fa5f --- /dev/null +++ b/chromium/services/device/generic_sensor/platform_sensor_provider_chromeos.cc @@ -0,0 +1,524 @@ +// 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 "services/device/generic_sensor/platform_sensor_provider_chromeos.h" + +#include <algorithm> +#include <iterator> +#include <utility> + +#include "base/bind.h" +#include "base/memory/scoped_refptr.h" +#include "base/ranges/algorithm.h" +#include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "base/task/post_task.h" +#include "base/task/thread_pool.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "chromeos/components/sensors/sensor_hal_dispatcher.h" +#include "services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h" +#include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h" +#include "services/device/generic_sensor/linux/sensor_data_linux.h" +#include "services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h" +#include "services/device/generic_sensor/platform_sensor_chromeos.h" +#include "services/device/generic_sensor/platform_sensor_fusion.h" +#include "services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.h" +#include "services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope.h" + +namespace device { +namespace { + +constexpr base::TimeDelta kReconnectDelay = + base::TimeDelta::FromMilliseconds(1000); + +base::Optional<mojom::SensorType> ConvertSensorType( + chromeos::sensors::mojom::DeviceType device_type) { + switch (device_type) { + case chromeos::sensors::mojom::DeviceType::ACCEL: + return mojom::SensorType::ACCELEROMETER; + + case chromeos::sensors::mojom::DeviceType::ANGLVEL: + return mojom::SensorType::GYROSCOPE; + + case chromeos::sensors::mojom::DeviceType::LIGHT: + return mojom::SensorType::AMBIENT_LIGHT; + + case chromeos::sensors::mojom::DeviceType::MAGN: + return mojom::SensorType::MAGNETOMETER; + + default: + return base::nullopt; + } +} + +bool DeviceNeedsLocationWithTypes(const std::vector<mojom::SensorType>& types) { + for (auto type : types) { + switch (type) { + case mojom::SensorType::AMBIENT_LIGHT: + case mojom::SensorType::ACCELEROMETER: + case mojom::SensorType::GYROSCOPE: + case mojom::SensorType::MAGNETOMETER: + return true; + default: + break; + } + } + + return false; +} + +} // namespace + +PlatformSensorProviderChromeOS::PlatformSensorProviderChromeOS() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + RegisterSensorClient(); +} + +PlatformSensorProviderChromeOS::~PlatformSensorProviderChromeOS() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +} + +void PlatformSensorProviderChromeOS::SetUpChannel( + mojo::PendingRemote<chromeos::sensors::mojom::SensorService> + pending_remote) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (sensor_service_remote_.is_bound()) { + LOG(ERROR) << "Ignoring the second Remote<SensorService>"; + return; + } + + sensor_service_remote_.Bind(std::move(pending_remote)); + sensor_service_remote_.set_disconnect_handler( + base::BindOnce(&PlatformSensorProviderChromeOS::OnSensorServiceDisconnect, + weak_ptr_factory_.GetWeakPtr())); + + sensor_service_remote_->GetAllDeviceIds( + base::BindOnce(&PlatformSensorProviderChromeOS::GetAllDeviceIdsCallback, + weak_ptr_factory_.GetWeakPtr())); +} + +void PlatformSensorProviderChromeOS::CreateSensorInternal( + mojom::SensorType type, + SensorReadingSharedBuffer* reading_buffer, + CreateSensorCallback callback) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + if (!sensor_service_remote_.is_bound() || !AreAllSensorsReady()) { + // Wait until |sensor_service_remote_| is connected and all sensors are + // ready to proceed. + // If |sensor_service_remote_| is disconnected, wait until it re-connects to + // proceed, as it needs a valid SensorDevice channel. + return; + } + + // As mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES needs to know + // whether mojom::SensorType::GYROSCOPE exists or not to determine the + // algorithm, wait until all sensors ready before processing the fusion + // sensors as well. + if (IsFusionSensorType(type)) { + CreateFusionSensor(type, reading_buffer, std::move(callback)); + return; + } + + auto id_opt = GetDeviceId(type); + if (!id_opt.has_value()) { + std::move(callback).Run(nullptr); + return; + } + int32_t id = id_opt.value(); + DCHECK(base::Contains(sensors_, id)); + + auto& sensor = sensors_[id]; + DCHECK(sensor.scale.has_value()); + + auto sensor_device_remote = GetSensorDeviceRemote(id); + std::move(callback).Run(base::MakeRefCounted<PlatformSensorChromeOS>( + id, type, reading_buffer, this, sensor.scale.value(), + std::move(sensor_device_remote))); +} + +void PlatformSensorProviderChromeOS::FreeResources() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +} + +bool PlatformSensorProviderChromeOS::IsSensorTypeAvailable( + mojom::SensorType type) const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return GetDeviceId(type).has_value(); +} + +PlatformSensorProviderChromeOS::SensorData::SensorData() = default; +PlatformSensorProviderChromeOS::SensorData::~SensorData() = default; + +base::Optional<PlatformSensorProviderChromeOS::SensorLocation> +PlatformSensorProviderChromeOS::ParseLocation( + const base::Optional<std::string>& raw_location) { + if (!raw_location.has_value()) { + LOG(ERROR) << "No location attribute"; + return base::nullopt; + } + + // These locations must be listed in the same order as the SensorLocation + // enum. + const std::vector<std::string> location_strings = { + chromeos::sensors::mojom::kLocationBase, + chromeos::sensors::mojom::kLocationLid, + chromeos::sensors::mojom::kLocationCamera}; + const auto it = base::ranges::find(location_strings, raw_location.value()); + if (it == std::end(location_strings)) + return base::nullopt; + + return static_cast<SensorLocation>( + std::distance(std::begin(location_strings), it)); +} + +base::Optional<int32_t> PlatformSensorProviderChromeOS::GetDeviceId( + mojom::SensorType type) const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + const auto type_id = sensor_id_by_type_.find(type); + if (type_id == sensor_id_by_type_.end()) + return base::nullopt; + return type_id->second; +} + +void PlatformSensorProviderChromeOS::RegisterSensorClient() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(!sensor_hal_client_.is_bound()); + + chromeos::sensors::SensorHalDispatcher::GetInstance()->RegisterClient( + sensor_hal_client_.BindNewPipeAndPassRemote()); + + sensor_hal_client_.set_disconnect_handler( + base::BindOnce(&PlatformSensorProviderChromeOS::OnSensorHalClientFailure, + weak_ptr_factory_.GetWeakPtr())); +} + +void PlatformSensorProviderChromeOS::OnSensorHalClientFailure() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + LOG(ERROR) << "OnSensorHalClientFailure"; + + ResetSensorService(); + sensor_hal_client_.reset(); + + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&PlatformSensorProviderChromeOS::RegisterSensorClient, + weak_ptr_factory_.GetWeakPtr()), + kReconnectDelay); +} + +void PlatformSensorProviderChromeOS::OnSensorServiceDisconnect() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + LOG(ERROR) << "OnSensorServiceDisconnect"; + + ResetSensorService(); +} + +void PlatformSensorProviderChromeOS::ResetSensorService() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + for (auto& sensor : sensors_) { + // Reset only the remote while keeping the attributes information to speed + // up recovery, as the attributes won't need to be queried again. + sensor.second.remote.reset(); + } + + sensor_service_remote_.reset(); +} + +void PlatformSensorProviderChromeOS::GetAllDeviceIdsCallback( + const SensorIdTypesMap& ids_types) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(sensor_service_remote_.is_bound()); + + sensor_ids_received_ = true; + + for (const auto& id_types : ids_types) { + int32_t id = id_types.first; + SensorData& sensor = sensors_[id]; + + if (sensor.ignored) + continue; + + for (const auto& device_type : id_types.second) { + auto type_opt = ConvertSensorType(device_type); + if (!type_opt.has_value()) + continue; + + sensor.types.push_back(type_opt.value()); + } + + if (sensor.types.empty()) { + sensor.ignored = true; + continue; + } + + sensor.remote.reset(); + + std::vector<std::string> attr_names; + if (!sensor.scale.has_value()) + attr_names.push_back(chromeos::sensors::mojom::kScale); + if (DeviceNeedsLocationWithTypes(sensor.types) && + !sensor.location.has_value()) { + attr_names.push_back(chromeos::sensors::mojom::kLocation); + } + + if (attr_names.empty()) + continue; + + sensor.remote = GetSensorDeviceRemote(id); + + // Add a temporary disconnect handler to catch failures during sensor + // enumeration. PlatformSensorChromeOS will handle disconnection during + // normal operation. + sensor.remote.set_disconnect_handler(base::BindOnce( + &PlatformSensorProviderChromeOS::OnSensorDeviceDisconnect, + weak_ptr_factory_.GetWeakPtr(), id)); + + sensor.remote->GetAttributes( + std::move(attr_names), + base::BindOnce(&PlatformSensorProviderChromeOS::GetAttributesCallback, + weak_ptr_factory_.GetWeakPtr(), id)); + } + + ProcessSensorsIfPossible(); +} + +void PlatformSensorProviderChromeOS::GetAttributesCallback( + int32_t id, + const std::vector<base::Optional<std::string>>& values) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + auto it = sensors_.find(id); + DCHECK(it != sensors_.end()); + auto& sensor = it->second; + DCHECK(sensor.remote.is_bound()); + + size_t index = 0; + + if (!sensor.scale.has_value()) { + if (index >= values.size()) { + LOG(ERROR) << "values doesn't contain scale attribute."; + IgnoreSensor(sensor); + return; + } + + double scale = 0.0; + if (!values[index].has_value() || + !base::StringToDouble(values[index].value(), &scale)) { + LOG(ERROR) << "Invalid scale: " << values[index].value_or("") + << ", for accel with id: " << id; + IgnoreSensor(sensor); + return; + } + + sensor.scale = scale; + + ++index; + } + + if (DeviceNeedsLocationWithTypes(sensor.types) && + !sensor.location.has_value()) { + if (index >= values.size()) { + LOG(ERROR) << "values doesn't contain location attribute."; + IgnoreSensor(sensor); + return; + } + + sensor.location = ParseLocation(values[index]); + if (!sensor.location.has_value()) { + LOG(ERROR) << "Failed to parse location: " << values[index].value_or("") + << ", with sensor id: " << id; + IgnoreSensor(sensor); + return; + } + + ++index; + } + + ProcessSensorsIfPossible(); +} + +void PlatformSensorProviderChromeOS::IgnoreSensor(SensorData& sensor) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + sensor.ignored = true; + sensor.remote.reset(); + + ProcessSensorsIfPossible(); +} + +bool PlatformSensorProviderChromeOS::AreAllSensorsReady() const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + if (!sensor_ids_received_) + return false; + + return base::ranges::all_of(sensors_, [](const auto& sensor) { + return sensor.second.ignored || + (sensor.second.scale.has_value() && + (!DeviceNeedsLocationWithTypes(sensor.second.types) || + sensor.second.location.has_value())); + }); +} + +void PlatformSensorProviderChromeOS::OnSensorDeviceDisconnect(int32_t id) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + sensors_[id].remote.reset(); +} + +void PlatformSensorProviderChromeOS::ProcessSensorsIfPossible() { + if (!AreAllSensorsReady()) + return; + + DetermineMotionSensors(); + DetermineLightSensor(); + + RemoveUnusedSensorDeviceRemotes(); + ProcessStoredRequests(); +} + +// Follow Android's and W3C's requirements of motion sensors: +// Android: https://source.android.com/devices/sensors/sensor-types +// W3C: https://w3c.github.io/sensors/#local-coordinate-system +// To implement fusion/composite sensors, accelerometer, gyroscope (and +// magnetometer) must be in the same plane, so when it comes to choosing an +// accelerometer in a convertible device, we choose the one which is in the +// same place as the gyroscope. If we still have a choice, we use the one in +// the lid. +void PlatformSensorProviderChromeOS::DetermineMotionSensors() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + struct MotionSensorInfo { + size_t count; + std::vector<std::pair<int32_t, mojom::SensorType>> sensor_info_pairs; + }; + std::map<SensorLocation, MotionSensorInfo> motion_sensor_location_info; + + for (const auto& sensor : sensors_) { + if (sensor.second.ignored || !sensor.second.location) + continue; + + SensorLocation location = sensor.second.location.value(); + DCHECK_LT(location, SensorLocation::kMax); + + for (auto type : sensor.second.types) { + switch (type) { + case mojom::SensorType::ACCELEROMETER: + case mojom::SensorType::GYROSCOPE: + case mojom::SensorType::MAGNETOMETER: { + auto& motion_sensor_info = motion_sensor_location_info[location]; + motion_sensor_info.count++; + motion_sensor_info.sensor_info_pairs.push_back( + std::make_pair(sensor.first, type)); + break; + } + + default: + break; + } + } + } + + const auto preferred_location = + motion_sensor_location_info[SensorLocation::kLid].count >= + motion_sensor_location_info[SensorLocation::kBase].count + ? SensorLocation::kLid + : SensorLocation::kBase; + const auto& sensor_info_pairs = + motion_sensor_location_info[preferred_location].sensor_info_pairs; + for (const auto& pair : sensor_info_pairs) + sensor_id_by_type_[pair.second] = pair.first; +} + +// Prefer the light sensor on the lid, as it's more meaningful to web API users. +void PlatformSensorProviderChromeOS::DetermineLightSensor() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + base::Optional<int32_t> id = base::nullopt; + + for (const auto& sensor : sensors_) { + if (sensor.second.ignored || + !base::Contains(sensor.second.types, mojom::SensorType::AMBIENT_LIGHT)) + continue; + + if (!id.has_value() || sensor.second.location == SensorLocation::kLid) + id = sensor.first; + } + + if (id.has_value()) + sensor_id_by_type_[mojom::SensorType::AMBIENT_LIGHT] = id.value(); +} + +void PlatformSensorProviderChromeOS::RemoveUnusedSensorDeviceRemotes() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + std::set<int32_t> used_ids; + for (const auto& type_id : sensor_id_by_type_) + used_ids.emplace(type_id.second); + + for (auto& sensor : sensors_) { + if (!base::Contains(used_ids, sensor.first)) + sensor.second.remote.reset(); + } +} + +void PlatformSensorProviderChromeOS::ProcessStoredRequests() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + std::vector<mojom::SensorType> request_types = GetPendingRequestTypes(); + for (const auto& type : request_types) { + SensorReadingSharedBuffer* reading_buffer = + GetSensorReadingSharedBufferForType(type); + + if (!reading_buffer) + continue; + + if (IsFusionSensorType(type)) { + CreateFusionSensor( + type, reading_buffer, + base::BindOnce(&PlatformSensorProviderChromeOS::NotifySensorCreated, + weak_ptr_factory_.GetWeakPtr(), type)); + continue; + } + + auto id_opt = GetDeviceId(type); + if (!id_opt.has_value()) { + NotifySensorCreated(type, nullptr); + continue; + } + + int32_t id = id_opt.value(); + DCHECK(base::Contains(sensors_, id)); + + auto& sensor = sensors_[id]; + DCHECK(sensor.scale.has_value()); + + auto sensor_device_remote = GetSensorDeviceRemote(id); + NotifySensorCreated( + type, base::MakeRefCounted<PlatformSensorChromeOS>( + id, type, reading_buffer, this, sensor.scale.value(), + std::move(sensor_device_remote))); + } +} + +mojo::Remote<chromeos::sensors::mojom::SensorDevice> +PlatformSensorProviderChromeOS::GetSensorDeviceRemote(int32_t id) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(sensor_service_remote_.is_bound()); + + mojo::Remote<chromeos::sensors::mojom::SensorDevice> sensor_device_remote; + auto& sensor = sensors_[id]; + if (sensor.remote.is_bound()) { + // Reuse the previous remote. + sensor_device_remote = std::move(sensor.remote); + } else { + sensor_service_remote_->GetDevice( + id, sensor_device_remote.BindNewPipeAndPassReceiver()); + } + + return sensor_device_remote; +} + +} // namespace device diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_chromeos.h b/chromium/services/device/generic_sensor/platform_sensor_provider_chromeos.h new file mode 100644 index 00000000000..e2781f5f793 --- /dev/null +++ b/chromium/services/device/generic_sensor/platform_sensor_provider_chromeos.h @@ -0,0 +1,133 @@ +// 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 SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_PROVIDER_CHROMEOS_H_ +#define SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_PROVIDER_CHROMEOS_H_ + +#include "services/device/generic_sensor/platform_sensor_provider_linux_base.h" + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "base/containers/flat_map.h" +#include "base/gtest_prod_util.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "chromeos/components/sensors/mojom/cros_sensor_service.mojom.h" +#include "chromeos/components/sensors/mojom/sensor.mojom.h" +#include "mojo/public/cpp/bindings/remote.h" + +namespace device { + +class PlatformSensorProviderChromeOS + : public PlatformSensorProviderLinuxBase, + public chromeos::sensors::mojom::SensorHalClient { + public: + PlatformSensorProviderChromeOS(); + PlatformSensorProviderChromeOS(const PlatformSensorProviderChromeOS&) = + delete; + PlatformSensorProviderChromeOS& operator=( + const PlatformSensorProviderChromeOS&) = delete; + ~PlatformSensorProviderChromeOS() override; + + // chromeos::sensors::mojom::SensorHalClient overrides: + void SetUpChannel(mojo::PendingRemote<chromeos::sensors::mojom::SensorService> + pending_remote) override; + + protected: + // PlatformSensorProviderLinuxBase overrides: + void CreateSensorInternal(mojom::SensorType type, + SensorReadingSharedBuffer* reading_buffer, + CreateSensorCallback callback) override; + void FreeResources() override; + bool IsSensorTypeAvailable(mojom::SensorType type) const override; + + private: + friend class PlatformSensorProviderChromeOSTest; + + enum class SensorLocation { + kBase = 0, + kLid, + kCamera, + kMax, + }; + + using SensorIdTypesMap = + base::flat_map<int32_t, + std::vector<chromeos::sensors::mojom::DeviceType>>; + + struct SensorData { + SensorData(); + ~SensorData(); + + std::vector<mojom::SensorType> types; + bool ignored = false; + base::Optional<SensorLocation> location; + base::Optional<double> scale; + + // Temporarily stores the remote, waiting for its attributes information. + // It'll be passed to PlatformSensorChromeOS' constructor as an argument + // after all information is collected, if this sensor is needed. + mojo::Remote<chromeos::sensors::mojom::SensorDevice> remote; + }; + + base::Optional<SensorLocation> ParseLocation( + const base::Optional<std::string>& location); + + base::Optional<int32_t> GetDeviceId(mojom::SensorType type) const; + + void RegisterSensorClient(); + void OnSensorHalClientFailure(); + + void OnSensorServiceDisconnect(); + + void ResetSensorService(); + + void GetAllDeviceIdsCallback(const SensorIdTypesMap& ids_types); + void GetAttributesCallback( + int32_t id, + const std::vector<base::Optional<std::string>>& values); + void IgnoreSensor(SensorData& sensor); + bool AreAllSensorsReady() const; + + void OnSensorDeviceDisconnect(int32_t id); + void ProcessSensorsIfPossible(); + + void DetermineMotionSensors(); + void DetermineLightSensor(); + + // Remove Mojo remotes of the unused devices, as they'll never be used. + void RemoveUnusedSensorDeviceRemotes(); + void ProcessStoredRequests(); + + mojo::Remote<chromeos::sensors::mojom::SensorDevice> GetSensorDeviceRemote( + int32_t id); + + mojo::Receiver<chromeos::sensors::mojom::SensorHalClient> sensor_hal_client_{ + this}; + + // The Mojo remote to query and request for devices. + mojo::Remote<chromeos::sensors::mojom::SensorService> sensor_service_remote_; + + // The flag of sensor ids received or not to help determine if all sensors are + // ready. It's needed when there is no sensor at all. + bool sensor_ids_received_ = false; + + // First is the device id, second is the device's types, data and Mojo remote. + std::map<int32_t, SensorData> sensors_; + + // Stores the selected sensor devices' ids by type. + std::map<mojom::SensorType, int32_t> sensor_id_by_type_; + + base::WeakPtrFactory<PlatformSensorProviderChromeOS> weak_ptr_factory_{this}; + + FRIEND_TEST_ALL_PREFIXES(PlatformSensorProviderChromeOSTest, + CheckUnsupportedTypes); +}; + +} // namespace device + +#endif // SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_PROVIDER_CHROMEOS_H_ diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_chromeos_unittest.cc b/chromium/services/device/generic_sensor/platform_sensor_provider_chromeos_unittest.cc new file mode 100644 index 00000000000..67ee7325a82 --- /dev/null +++ b/chromium/services/device/generic_sensor/platform_sensor_provider_chromeos_unittest.cc @@ -0,0 +1,487 @@ +// 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 "services/device/generic_sensor/platform_sensor_provider_chromeos.h" + +#include <memory> +#include <utility> + +#include "base/optional.h" +#include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" +#include "base/test/bind.h" +#include "base/test/task_environment.h" +#include "chromeos/components/sensors/fake_sensor_device.h" +#include "chromeos/components/sensors/fake_sensor_hal_server.h" +#include "chromeos/components/sensors/sensor_hal_dispatcher.h" +#include "services/device/public/cpp/generic_sensor/sensor_traits.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace device { + +namespace { + +constexpr int kFakeDeviceId = 1; + +constexpr double kScaleValue = 10.0; +constexpr char kWrongScale[] = "10..0"; + +constexpr char kWrongLocation[] = "basee"; + +} // namespace + +class PlatformSensorProviderChromeOSTest : public ::testing::Test { + protected: + void SetUp() override { + chromeos::sensors::SensorHalDispatcher::Initialize(); + + sensor_hal_server_ = + std::make_unique<chromeos::sensors::FakeSensorHalServer>(); + provider_ = std::make_unique<PlatformSensorProviderChromeOS>(); + } + + void TearDown() override { + chromeos::sensors::SensorHalDispatcher::Shutdown(); + } + + void AddDevice(int32_t iio_device_id, + chromeos::sensors::mojom::DeviceType type, + const base::Optional<std::string>& scale, + const base::Optional<std::string>& location) { + AddDevice(iio_device_id, + std::set<chromeos::sensors::mojom::DeviceType>{type}, + std::move(scale), std::move(location)); + } + + void AddDevice(int32_t iio_device_id, + std::set<chromeos::sensors::mojom::DeviceType> types, + const base::Optional<std::string>& scale, + const base::Optional<std::string>& location) { + auto sensor_device = std::make_unique<chromeos::sensors::FakeSensorDevice>( + std::vector<chromeos::sensors::FakeSensorDevice::ChannelData>{}); + + if (scale.has_value()) { + sensor_device->SetAttribute(chromeos::sensors::mojom::kScale, + scale.value()); + } + if (location.has_value()) { + sensor_device->SetAttribute(chromeos::sensors::mojom::kLocation, + location.value()); + } + + sensor_devices_.push_back(sensor_device.get()); + + sensor_hal_server_->GetSensorService()->SetDevice( + iio_device_id, std::move(types), std::move(sensor_device)); + } + + // Sensor creation is asynchronous, therefore inner loop is used to wait for + // PlatformSensorProvider::CreateSensorCallback completion. + scoped_refptr<PlatformSensor> CreateSensor(mojom::SensorType type) { + scoped_refptr<PlatformSensor> sensor; + base::RunLoop run_loop; + provider_->CreateSensor(type, + base::BindLambdaForTesting( + [&](scoped_refptr<PlatformSensor> new_sensor) { + if (new_sensor) + EXPECT_EQ(type, new_sensor->GetType()); + + sensor = std::move(new_sensor); + run_loop.Quit(); + })); + run_loop.Run(); + return sensor; + } + + void StartConnection() { + chromeos::sensors::SensorHalDispatcher::GetInstance()->RegisterServer( + sensor_hal_server_->PassRemote()); + } + + void ResetClient() { + // Similar to provider_->OnSensorHalClientFailure, but without the delay. + provider_->ResetSensorService(); + provider_->sensor_hal_client_.reset(); + provider_->RegisterSensorClient(); + } + + std::unique_ptr<chromeos::sensors::FakeSensorHalServer> sensor_hal_server_; + std::vector<chromeos::sensors::FakeSensorDevice*> sensor_devices_; + + std::unique_ptr<PlatformSensorProviderChromeOS> provider_; + + base::test::SingleThreadTaskEnvironment task_environment_; +}; + +TEST_F(PlatformSensorProviderChromeOSTest, CheckUnsupportedTypes) { + int fake_id = 1; + // Containing at least one supported device type. + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + AddDevice(fake_id++, + std::set<chromeos::sensors::mojom::DeviceType>{ + chromeos::sensors::mojom::DeviceType::ANGLVEL, + chromeos::sensors::mojom::DeviceType::COUNT}, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + // All device types are unsupported. + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::COUNT, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + AddDevice(fake_id++, + std::set<chromeos::sensors::mojom::DeviceType>{ + chromeos::sensors::mojom::DeviceType::ANGL, + chromeos::sensors::mojom::DeviceType::BARO}, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_TRUE(CreateSensor(mojom::SensorType::ACCELEROMETER)); + + EXPECT_FALSE(provider_->sensors_[1].ignored); + EXPECT_FALSE(provider_->sensors_[2].ignored); + EXPECT_TRUE(provider_->sensors_[3].ignored); + EXPECT_TRUE(provider_->sensors_[4].ignored); + EXPECT_TRUE(provider_->sensors_[5].ignored); +} + +TEST_F(PlatformSensorProviderChromeOSTest, MissingScale) { + AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL, + /*scale=*/base::nullopt, chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_FALSE(CreateSensor(mojom::SensorType::ACCELEROMETER)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, MissingLocation) { + AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + /*location=*/base::nullopt); + + StartConnection(); + + EXPECT_FALSE(CreateSensor(mojom::SensorType::ACCELEROMETER)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, WrongScale) { + AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL, + kWrongScale, chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_FALSE(CreateSensor(mojom::SensorType::ACCELEROMETER)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, WrongLocation) { + AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), kWrongLocation); + + StartConnection(); + + EXPECT_FALSE(CreateSensor(mojom::SensorType::ACCELEROMETER)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, CheckMainLocationBase) { + int fake_id = 1; + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + // Will not be used. + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationLid); + + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::MAGN, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_TRUE(CreateSensor(mojom::SensorType::GYROSCOPE)); + + // Wait until the disconnect of the gyroscope arrives at FakeSensorDevice. + base::RunLoop().RunUntilIdle(); + + // Remote stored in |provider_|. + EXPECT_TRUE(sensor_devices_[0]->HasReceivers()); + EXPECT_TRUE(sensor_devices_[3]->HasReceivers()); + // Removed in |provider_| as it'll never be used. + EXPECT_FALSE(sensor_devices_[1]->HasReceivers()); +} + +TEST_F(PlatformSensorProviderChromeOSTest, CheckMainLocationLid) { + int fake_id = 1; + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationLid); + + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationLid); + + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::MAGN, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationCamera); + + StartConnection(); + + // Wait until the disconnect of the first gyroscope arrives at + // FakeSensorDevice. + base::RunLoop().RunUntilIdle(); + + // Removed in |provider_| as they'll never be used. + EXPECT_FALSE(sensor_devices_[0]->HasReceivers()); + EXPECT_FALSE(sensor_devices_[2]->HasReceivers()); + EXPECT_FALSE(sensor_devices_[4]->HasReceivers()); + // Remote stored in |provider_|. + EXPECT_TRUE(sensor_devices_[1]->HasReceivers()); + EXPECT_TRUE(sensor_devices_[3]->HasReceivers()); +} + +TEST_F(PlatformSensorProviderChromeOSTest, + CheckMainLocationLidWithMultitypeSensor) { + int fake_id = 1; + AddDevice(fake_id++, + std::set<chromeos::sensors::mojom::DeviceType>{ + chromeos::sensors::mojom::DeviceType::ACCEL, + chromeos::sensors::mojom::DeviceType::ANGLVEL}, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationLid); + + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + // Wait until the disconnect of the gyroscope arrives at FakeSensorDevice. + base::RunLoop().RunUntilIdle(); + + // Remote stored in |provider_|. + EXPECT_TRUE(sensor_devices_[0]->HasReceivers()); + // Removed in |provider_| as it'll never be used. + EXPECT_FALSE(sensor_devices_[1]->HasReceivers()); + + EXPECT_TRUE(CreateSensor(mojom::SensorType::ACCELEROMETER)); + EXPECT_TRUE(CreateSensor(mojom::SensorType::GYROSCOPE)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, CheckAmbientLightSensorLocationLid) { + int fake_id = 1; + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::LIGHT, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::LIGHT, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationLid); + + StartConnection(); + + // Wait until the disconnect of the first ambient light sensor arrives at + // FakeSensorDevice. + base::RunLoop().RunUntilIdle(); + + // Removed in |provider_| as it'll never be used. + EXPECT_FALSE(sensor_devices_[0]->HasReceivers()); + // Remote stored in |provider_|. + EXPECT_TRUE(sensor_devices_[1]->HasReceivers()); +} + +TEST_F(PlatformSensorProviderChromeOSTest, + CheckAmbientLightSensorLocationBase) { + AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::LIGHT, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_TRUE(CreateSensor(mojom::SensorType::AMBIENT_LIGHT)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, Reconnect) { + int fake_id = 1; + + // Will not be used. + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationLid); + + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::LIGHT, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_FALSE(CreateSensor(mojom::SensorType::ACCELEROMETER)); + + // Simulate a disconnection between |provider_| and the dispatcher. + ResetClient(); + + EXPECT_TRUE(CreateSensor(mojom::SensorType::GYROSCOPE)); + + // Simulate a disconnection of IIO Service. + sensor_hal_server_->GetSensorService()->OnServiceDisconnect(); + sensor_hal_server_->OnServerDisconnect(); + // Remove the stored Mojo remote of the ambient light sensor. + sensor_devices_.back()->ClearReceivers(); + + // Wait until the disconnect arrives at the dispatcher. + base::RunLoop().RunUntilIdle(); + + StartConnection(); + + EXPECT_TRUE(CreateSensor(mojom::SensorType::AMBIENT_LIGHT)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, + CheckLinearAccelerationSensorNotCreatedIfNoAccelerometer) { + StartConnection(); + + EXPECT_FALSE(CreateSensor(mojom::SensorType::LINEAR_ACCELERATION)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, CheckLinearAcceleration) { + AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_TRUE(CreateSensor(mojom::SensorType::LINEAR_ACCELERATION)); +} + +TEST_F( + PlatformSensorProviderChromeOSTest, + CheckAbsoluteOrientationSensorNotCreatedIfNoAccelerometerAndNoMagnetometer) { + StartConnection(); + + EXPECT_FALSE( + CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES)); + EXPECT_FALSE( + CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, + CheckAbsoluteOrientationSensorNotCreatedIfNoAccelerometer) { + AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::MAGN, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_FALSE( + CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES)); + EXPECT_FALSE( + CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, + CheckAbsoluteOrientationSensorNotCreatedIfNoMagnetometer) { + AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_FALSE( + CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES)); + EXPECT_FALSE( + CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, CheckAbsoluteOrientationSensors) { + int fake_id = 1; + + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::MAGN, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_TRUE( + CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES)); + EXPECT_TRUE(CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION)); +} + +TEST_F( + PlatformSensorProviderChromeOSTest, + CheckRelativeOrientationSensorNotCreatedIfNoAccelerometerAndNoGyroscope) { + StartConnection(); + + EXPECT_FALSE( + CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES)); + EXPECT_FALSE( + CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, + CheckRelativeOrientationSensorNotCreatedIfNoAccelerometer) { + AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ANGLVEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_FALSE( + CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES)); + EXPECT_FALSE( + CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, + CheckRelativeOrientationSensorUsingAccelerometer) { + AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_TRUE( + CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES)); + EXPECT_TRUE(CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION)); +} + +TEST_F(PlatformSensorProviderChromeOSTest, + CheckRelativeOrientationSensorUsingAccelerometerAndGyroscope) { + int fake_id = 1; + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL, + base::NumberToString(kScaleValue), + chromeos::sensors::mojom::kLocationBase); + + StartConnection(); + + EXPECT_TRUE( + CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES)); + EXPECT_TRUE(CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION)); +} + +} // namespace device diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc index 63e745911e9..cf15ae504fb 100644 --- a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc +++ b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc @@ -12,15 +12,9 @@ #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/task_runner_util.h" -#include "services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h" -#include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h" #include "services/device/generic_sensor/linux/sensor_data_linux.h" -#include "services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h" -#include "services/device/generic_sensor/platform_sensor_fusion.h" #include "services/device/generic_sensor/platform_sensor_linux.h" #include "services/device/generic_sensor/platform_sensor_reader_linux.h" -#include "services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.h" -#include "services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope.h" namespace device { namespace { @@ -29,18 +23,6 @@ constexpr base::TaskTraits kBlockingTaskRunnerTraits = { base::MayBlock(), base::TaskPriority::USER_VISIBLE, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}; -bool IsFusionSensorType(mojom::SensorType type) { - switch (type) { - case mojom::SensorType::LINEAR_ACCELERATION: - case mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES: - case mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION: - case mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES: - case mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION: - return true; - default: - return false; - } -} } // namespace PlatformSensorProviderLinux::PlatformSensorProviderLinux() @@ -94,10 +76,16 @@ void PlatformSensorProviderLinux::FreeResources() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } +bool PlatformSensorProviderLinux::IsSensorTypeAvailable( + mojom::SensorType type) const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return GetSensorDevice(type); +} + SensorInfoLinux* PlatformSensorProviderLinux::GetSensorDevice( - mojom::SensorType type) { + mojom::SensorType type) const { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - auto sensor = sensor_devices_by_type_.find(type); + const auto sensor = sensor_devices_by_type_.find(type); if (sensor == sensor_devices_by_type_.end()) return nullptr; return sensor->second.get(); @@ -178,47 +166,4 @@ void PlatformSensorProviderLinux::OnDeviceRemoved( } } -void PlatformSensorProviderLinux::CreateFusionSensor( - mojom::SensorType type, - SensorReadingSharedBuffer* reading_buffer, - CreateSensorCallback callback) { - DCHECK(IsFusionSensorType(type)); - std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm; - switch (type) { - case mojom::SensorType::LINEAR_ACCELERATION: - fusion_algorithm = std::make_unique< - LinearAccelerationFusionAlgorithmUsingAccelerometer>(); - break; - case mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES: - fusion_algorithm = std::make_unique< - AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer>(); - break; - case mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION: - fusion_algorithm = std::make_unique< - OrientationQuaternionFusionAlgorithmUsingEulerAngles>( - true /* absolute */); - break; - case mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES: - if (GetSensorDevice(mojom::SensorType::GYROSCOPE)) { - fusion_algorithm = std::make_unique< - RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndGyroscope>(); - } else { - fusion_algorithm = std::make_unique< - RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer>(); - } - break; - case mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION: - fusion_algorithm = std::make_unique< - OrientationQuaternionFusionAlgorithmUsingEulerAngles>( - false /* absolute */); - break; - default: - NOTREACHED(); - } - - DCHECK(fusion_algorithm); - PlatformSensorFusion::Create( - reading_buffer, this, std::move(fusion_algorithm), std::move(callback)); -} - } // namespace device diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h index 820003f1235..9130a86a95a 100644 --- a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h +++ b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SERVICES_DEVICE_GENERIC_SENSOR_PUBLIC_PLATFORM_SENSOR_PROVIDER_LINUX_H_ -#define SERVICES_DEVICE_GENERIC_SENSOR_PUBLIC_PLATFORM_SENSOR_PROVIDER_LINUX_H_ +#ifndef SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_PROVIDER_LINUX_H_ +#define SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_PROVIDER_LINUX_H_ -#include "services/device/generic_sensor/platform_sensor_provider.h" +#include "services/device/generic_sensor/platform_sensor_provider_linux_base.h" #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" @@ -15,7 +15,7 @@ namespace device { struct SensorInfoLinux; -class PlatformSensorProviderLinux : public PlatformSensorProvider, +class PlatformSensorProviderLinux : public PlatformSensorProviderLinuxBase, public SensorDeviceManager::Delegate { public: PlatformSensorProviderLinux(); @@ -26,11 +26,12 @@ class PlatformSensorProviderLinux : public PlatformSensorProvider, std::unique_ptr<SensorDeviceManager> sensor_device_manager); protected: + // PlatformSensorProviderLinuxBase overrides: void CreateSensorInternal(mojom::SensorType type, SensorReadingSharedBuffer* reading_buffer, CreateSensorCallback callback) override; - void FreeResources() override; + bool IsSensorTypeAvailable(mojom::SensorType type) const override; private: friend class PlatformSensorAndProviderLinuxTest; @@ -46,7 +47,7 @@ class PlatformSensorProviderLinux : public PlatformSensorProvider, // If a request cannot be processed immediately, returns nullptr and // all the requests stored in |requests_map_| are processed after // enumeration is ready. - SensorInfoLinux* GetSensorDevice(mojom::SensorType type); + SensorInfoLinux* GetSensorDevice(mojom::SensorType type) const; // Processed stored requests in |request_map_|. void ProcessStoredRequests(); @@ -55,17 +56,13 @@ class PlatformSensorProviderLinux : public PlatformSensorProvider, void CreateSensorAndNotify(mojom::SensorType type, SensorInfoLinux* sensor_device); - // SensorDeviceManager::Delegate implements: + // SensorDeviceManager::Delegate overrides: void OnSensorNodesEnumerated() override; void OnDeviceAdded(mojom::SensorType type, std::unique_ptr<SensorInfoLinux> sensor_device) override; void OnDeviceRemoved(mojom::SensorType type, const std::string& device_node) override; - void CreateFusionSensor(mojom::SensorType type, - SensorReadingSharedBuffer* reading_buffer, - CreateSensorCallback callback); - // Set to true when enumeration is ready. bool sensor_nodes_enumerated_; @@ -91,4 +88,4 @@ class PlatformSensorProviderLinux : public PlatformSensorProvider, } // namespace device -#endif // SERVICES_DEVICE_GENERIC_SENSOR_PUBLIC_PLATFORM_SENSOR_PROVIDER_LINUX_H_ +#endif // SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_PROVIDER_LINUX_H_ diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_linux_base.cc b/chromium/services/device/generic_sensor/platform_sensor_provider_linux_base.cc new file mode 100644 index 00000000000..85edf851d13 --- /dev/null +++ b/chromium/services/device/generic_sensor/platform_sensor_provider_linux_base.cc @@ -0,0 +1,77 @@ +// 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 "services/device/generic_sensor/platform_sensor_provider_linux_base.h" + +#include <memory> +#include <utility> + +#include "services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h" +#include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h" +#include "services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h" +#include "services/device/generic_sensor/platform_sensor_fusion.h" +#include "services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.h" +#include "services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_gyroscope.h" + +namespace device { + +// static +bool PlatformSensorProviderLinuxBase::IsFusionSensorType( + mojom::SensorType type) { + switch (type) { + case mojom::SensorType::LINEAR_ACCELERATION: + case mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES: + case mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION: + case mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES: + case mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION: + return true; + default: + return false; + } +} + +void PlatformSensorProviderLinuxBase::CreateFusionSensor( + mojom::SensorType type, + SensorReadingSharedBuffer* reading_buffer, + CreateSensorCallback callback) { + DCHECK(IsFusionSensorType(type)); + std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm; + switch (type) { + case mojom::SensorType::LINEAR_ACCELERATION: + fusion_algorithm = std::make_unique< + LinearAccelerationFusionAlgorithmUsingAccelerometer>(); + break; + case mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES: + fusion_algorithm = std::make_unique< + AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer>(); + break; + case mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION: + fusion_algorithm = std::make_unique< + OrientationQuaternionFusionAlgorithmUsingEulerAngles>( + true /* absolute */); + break; + case mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES: + if (IsSensorTypeAvailable(mojom::SensorType::GYROSCOPE)) { + fusion_algorithm = std::make_unique< + RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndGyroscope>(); + } else { + fusion_algorithm = std::make_unique< + RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer>(); + } + break; + case mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION: + fusion_algorithm = std::make_unique< + OrientationQuaternionFusionAlgorithmUsingEulerAngles>( + false /* absolute */); + break; + default: + NOTREACHED(); + } + + DCHECK(fusion_algorithm); + PlatformSensorFusion::Create( + reading_buffer, this, std::move(fusion_algorithm), std::move(callback)); +} + +} // namespace device diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_linux_base.h b/chromium/services/device/generic_sensor/platform_sensor_provider_linux_base.h new file mode 100644 index 00000000000..338f712d141 --- /dev/null +++ b/chromium/services/device/generic_sensor/platform_sensor_provider_linux_base.h @@ -0,0 +1,25 @@ +// 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 SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_PROVIDER_LINUX_BASE_H_ +#define SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_PROVIDER_LINUX_BASE_H_ + +#include "services/device/generic_sensor/platform_sensor_provider.h" + +namespace device { + +class PlatformSensorProviderLinuxBase : public PlatformSensorProvider { + protected: + static bool IsFusionSensorType(mojom::SensorType type); + + void CreateFusionSensor(mojom::SensorType type, + SensorReadingSharedBuffer* reading_buffer, + CreateSensorCallback callback); + + virtual bool IsSensorTypeAvailable(mojom::SensorType type) const = 0; +}; + +} // namespace device + +#endif // SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_PROVIDER_LINUX_BASE_H_ diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_winrt_unittest.cc b/chromium/services/device/generic_sensor/platform_sensor_provider_winrt_unittest.cc index 228ca68ce6d..fde2c6b7ce3 100644 --- a/chromium/services/device/generic_sensor/platform_sensor_provider_winrt_unittest.cc +++ b/chromium/services/device/generic_sensor/platform_sensor_provider_winrt_unittest.cc @@ -5,7 +5,7 @@ #include "services/device/generic_sensor/platform_sensor_provider_winrt.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "services/device/generic_sensor/platform_sensor_reader_win_base.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/chromium/services/device/generic_sensor/platform_sensor_reader_winrt_unittests.cc b/chromium/services/device/generic_sensor/platform_sensor_reader_winrt_unittests.cc index 80f13277a5e..da4a7f48376 100644 --- a/chromium/services/device/generic_sensor/platform_sensor_reader_winrt_unittests.cc +++ b/chromium/services/device/generic_sensor/platform_sensor_reader_winrt_unittests.cc @@ -7,7 +7,7 @@ #include <objbase.h> #include "base/numerics/math_constants.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/win/core_winrt_util.h" #include "base/win/scoped_com_initializer.h" diff --git a/chromium/services/device/geolocation/BUILD.gn b/chromium/services/device/geolocation/BUILD.gn index 2250f47f0ba..4246b61680a 100644 --- a/chromium/services/device/geolocation/BUILD.gn +++ b/chromium/services/device/geolocation/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") if (is_android) { @@ -9,13 +10,6 @@ if (is_android) { import("//build/config/android/rules.gni") # For generate_jni(). } -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - source_set("geolocation") { visibility = [ ":*", @@ -23,8 +17,6 @@ source_set("geolocation") { ] sources = [ - "empty_wifi_data_provider.cc", - "empty_wifi_data_provider.h", "geolocation_config.cc", "geolocation_config.h", "geolocation_context.cc", @@ -34,14 +26,8 @@ source_set("geolocation") { "geolocation_provider.h", "geolocation_provider_impl.cc", "geolocation_provider_impl.h", - "location_api_adapter_android.cc", - "location_api_adapter_android.h", "location_arbitrator.cc", "location_arbitrator.h", - "location_provider_android.cc", - "location_provider_android.h", - "network_location_provider.cc", - "network_location_provider.h", "network_location_request.cc", "network_location_request.h", "position_cache.h", @@ -57,20 +43,8 @@ source_set("geolocation") { "wifi_data.h", "wifi_data_provider.cc", "wifi_data_provider.h", - "wifi_data_provider_chromeos.cc", - "wifi_data_provider_chromeos.h", - "wifi_data_provider_common.cc", - "wifi_data_provider_common.h", - "wifi_data_provider_common_win.cc", - "wifi_data_provider_common_win.h", - "wifi_data_provider_linux.cc", - "wifi_data_provider_linux.h", - "wifi_data_provider_mac.h", - "wifi_data_provider_mac.mm", "wifi_data_provider_manager.cc", "wifi_data_provider_manager.h", - "wifi_data_provider_win.cc", - "wifi_data_provider_win.h", "wifi_polling_policy.cc", "wifi_polling_policy.h", ] @@ -88,47 +62,26 @@ source_set("geolocation") { "//services/device/public/mojom", "//services/network/public/cpp", ] - if (is_android) { - sources -= [ - "network_location_provider.cc", - "network_location_provider.h", - ] - deps += [ ":geolocation_jni_headers" ] - } - - # TODO(mcasas): prefer adding files than removing them (see cookbook.md). - # Dealing with *wifi_data_provider_*.cc is also a bit complicated given - # android, chromeos, linux and use_dbus. if (is_android) { - sources -= [ "wifi_data_provider_common.cc" ] - } - if (is_chromeos || (is_linux && !use_dbus)) { - sources -= [ "wifi_data_provider_linux.cc" ] - } - if ((is_linux || is_chromeos) && use_dbus) { - sources -= [ "empty_wifi_data_provider.cc" ] - deps += [ "//dbus" ] - } - if (is_win || is_mac) { - sources -= [ - "empty_wifi_data_provider.cc", - "empty_wifi_data_provider.h", + sources += [ + "location_api_adapter_android.cc", + "location_api_adapter_android.h", + "location_provider_android.cc", + "location_provider_android.h", ] - } - if (is_chromeos) { - deps += [ - "//chromeos/dbus/shill", - "//chromeos/network", + deps += [ ":geolocation_jni_headers" ] + } else { + sources += [ + "network_location_provider.cc", + "network_location_provider.h", + "wifi_data_provider_common.cc", + "wifi_data_provider_common.h", ] } if (is_mac) { - frameworks = [ - "CoreWLAN.framework", - "Foundation.framework", - "CoreLocation.framework", - ] + frameworks = [ "CoreLocation.framework" ] sources += [ "core_location_provider.h", "core_location_provider.mm", @@ -142,9 +95,47 @@ source_set("geolocation") { "win/location_provider_winrt.cc", "win/location_provider_winrt.h", ] - deps += [ "//services/device/public/cpp:device_features" ] } + + # Platform-specific WifiDataProvider implementations. + if (is_ash) { + sources += [ + "wifi_data_provider_chromeos.cc", + "wifi_data_provider_chromeos.h", + ] + deps += [ "//chromeos/network" ] + } else if (is_linux && use_dbus) { + sources += [ + "wifi_data_provider_linux.cc", + "wifi_data_provider_linux.h", + ] + deps += [ "//dbus" ] + } else if (is_mac) { + frameworks += [ + "CoreWLAN.framework", + "Foundation.framework", + ] + sources += [ + "wifi_data_provider_mac.h", + "wifi_data_provider_mac.mm", + ] + } else if (is_win) { + sources += [ + "wifi_data_provider_common_win.cc", + "wifi_data_provider_common_win.h", + "wifi_data_provider_win.cc", + "wifi_data_provider_win.h", + ] + } else { + # WifiDataProviderManager declares a static factory method that is defined + # by the platform implementation. Platforms with no Wi-Fi data provider must + # include EmptyWifiDataProvider to provide this definition. + sources += [ + "empty_wifi_data_provider.cc", + "empty_wifi_data_provider.h", + ] + } } if (is_android) { @@ -173,6 +164,7 @@ if (is_android) { "//components/location/android:location_java", "//services/device/public/java:geolocation_java", "//third_party/android_deps:androidx_annotation_annotation_java", + "//third_party/android_deps:chromium_play_services_availability_java", ] annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] } @@ -195,4 +187,8 @@ source_set("test_support") { "//testing/gmock", "//testing/gtest", ] + + if (is_ash) { + deps += [ "//chromeos/dbus/shill" ] + } } diff --git a/chromium/services/device/geolocation/DIR_METADATA b/chromium/services/device/geolocation/DIR_METADATA new file mode 100644 index 00000000000..78b63ec5ff8 --- /dev/null +++ b/chromium/services/device/geolocation/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Blink>Geolocation" +}
\ No newline at end of file diff --git a/chromium/services/device/geolocation/OWNERS b/chromium/services/device/geolocation/OWNERS index 2596b2d67e8..a87509a71d3 100644 --- a/chromium/services/device/geolocation/OWNERS +++ b/chromium/services/device/geolocation/OWNERS @@ -3,6 +3,3 @@ mattreynolds@chromium.org # Original (legacy) owners. mcasas@chromium.org timvolodine@chromium.org - -# COMPONENT: Blink>Geolocation -# TEAM: device-dev@chromium.org diff --git a/chromium/services/device/geolocation/core_location_provider_unittest.mm b/chromium/services/device/geolocation/core_location_provider_unittest.mm index d32adc573f0..43218df1bf0 100644 --- a/chromium/services/device/geolocation/core_location_provider_unittest.mm +++ b/chromium/services/device/geolocation/core_location_provider_unittest.mm @@ -5,7 +5,7 @@ #include "services/device/geolocation/core_location_provider.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "services/device/public/cpp/geolocation/geoposition.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/services/device/geolocation/fake_location_provider.cc b/chromium/services/device/geolocation/fake_location_provider.cc index 781cc07bcc1..59dc9f542a5 100644 --- a/chromium/services/device/geolocation/fake_location_provider.cc +++ b/chromium/services/device/geolocation/fake_location_provider.cc @@ -10,7 +10,7 @@ #include "services/device/geolocation/fake_location_provider.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/location.h" #include "base/memory/weak_ptr.h" diff --git a/chromium/services/device/geolocation/geolocation_provider_impl.cc b/chromium/services/device/geolocation/geolocation_provider_impl.cc index 15dad9765c6..3eb6f681d7e 100644 --- a/chromium/services/device/geolocation/geolocation_provider_impl.cc +++ b/chromium/services/device/geolocation/geolocation_provider_impl.cc @@ -7,8 +7,8 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" #include "base/callback.h" +#include "base/callback_helpers.h" #include "base/check.h" #include "base/lazy_instance.h" #include "base/location.h" diff --git a/chromium/services/device/geolocation/geolocation_provider_impl_unittest.cc b/chromium/services/device/geolocation/geolocation_provider_impl_unittest.cc index 4413f964df7..e085cb23ff6 100644 --- a/chromium/services/device/geolocation/geolocation_provider_impl_unittest.cc +++ b/chromium/services/device/geolocation/geolocation_provider_impl_unittest.cc @@ -8,7 +8,7 @@ #include "base/at_exit.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/location.h" #include "base/macros.h" #include "base/memory/ptr_util.h" diff --git a/chromium/services/device/geolocation/geolocation_service_unittest.cc b/chromium/services/device/geolocation/geolocation_service_unittest.cc index 905c78d74a2..255f1aa647c 100644 --- a/chromium/services/device/geolocation/geolocation_service_unittest.cc +++ b/chromium/services/device/geolocation/geolocation_service_unittest.cc @@ -4,10 +4,11 @@ #include "base/bind.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" -#if defined(OS_CHROMEOS) +#include "build/chromeos_buildflags.h" +#if BUILDFLAG(IS_ASH) #include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/network/geolocation_handler.h" #endif @@ -40,7 +41,7 @@ class GeolocationServiceUnitTest : public DeviceServiceTestBase { protected: void SetUp() override { -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) chromeos::shill_clients::InitializeFakes(); chromeos::NetworkHandler::Initialize(); #endif @@ -62,7 +63,7 @@ class GeolocationServiceUnitTest : public DeviceServiceTestBase { void TearDown() override { DeviceServiceTestBase::TearDown(); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) chromeos::NetworkHandler::Shutdown(); chromeos::shill_clients::Shutdown(); #endif @@ -90,7 +91,7 @@ class GeolocationServiceUnitTest : public DeviceServiceTestBase { DISALLOW_COPY_AND_ASSIGN(GeolocationServiceUnitTest); }; -#if defined(OS_CHROMEOS) || defined(OS_ANDROID) +#if BUILDFLAG(IS_ASH) || defined(OS_ANDROID) // ChromeOS fails to perform network geolocation when zero wifi networks are // detected in a scan: https://crbug.com/767300. #else diff --git a/chromium/services/device/geolocation/location_arbitrator.cc b/chromium/services/device/geolocation/location_arbitrator.cc index e5a1f312fdb..17147d94166 100644 --- a/chromium/services/device/geolocation/location_arbitrator.cc +++ b/chromium/services/device/geolocation/location_arbitrator.cc @@ -9,7 +9,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/memory/ptr_util.h" #include "build/build_config.h" #include "services/device/geolocation/network_location_provider.h" diff --git a/chromium/services/device/geolocation/public_ip_address_geolocator_unittest.cc b/chromium/services/device/geolocation/public_ip_address_geolocator_unittest.cc index d6e7b4ddc15..821d050163a 100644 --- a/chromium/services/device/geolocation/public_ip_address_geolocator_unittest.cc +++ b/chromium/services/device/geolocation/public_ip_address_geolocator_unittest.cc @@ -5,7 +5,7 @@ #include "services/device/geolocation/public_ip_address_geolocator.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/run_loop.h" #include "base/strings/string_util.h" #include "base/test/task_environment.h" diff --git a/chromium/services/device/geolocation/wifi_data_provider_common_unittest.cc b/chromium/services/device/geolocation/wifi_data_provider_common_unittest.cc index cf7bcca510b..eb8c480993a 100644 --- a/chromium/services/device/geolocation/wifi_data_provider_common_unittest.cc +++ b/chromium/services/device/geolocation/wifi_data_provider_common_unittest.cc @@ -6,7 +6,7 @@ #include <memory> -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" diff --git a/chromium/services/device/hid/BUILD.gn b/chromium/services/device/hid/BUILD.gn index a70323b8d25..c8e78bcbaa4 100644 --- a/chromium/services/device/hid/BUILD.gn +++ b/chromium/services/device/hid/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") import("//testing/libfuzzer/fuzzer_test.gni") @@ -25,6 +26,7 @@ source_set("hid") { deps = [ "//base", + "//build:chromeos_buildflags", "//components/device_event_log", "//device/base", "//services/device/public/cpp/hid", @@ -43,7 +45,7 @@ source_set("hid") { deps += [ "//device/udev_linux" ] } - if (is_chromeos) { + if (is_ash) { deps += [ "//chromeos/dbus/permission_broker" ] } diff --git a/chromium/services/device/hid/hid_connection_impl_unittest.cc b/chromium/services/device/hid/hid_connection_impl_unittest.cc index 1a1b4613e00..2cea116c608 100644 --- a/chromium/services/device/hid/hid_connection_impl_unittest.cc +++ b/chromium/services/device/hid/hid_connection_impl_unittest.cc @@ -5,7 +5,7 @@ #include "services/device/hid/hid_connection_impl.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/memory/ref_counted_memory.h" #include "build/build_config.h" #include "mojo/public/cpp/bindings/pending_receiver.h" diff --git a/chromium/services/device/hid/hid_manager_unittest.cc b/chromium/services/device/hid/hid_manager_unittest.cc index 6a5066d6b13..8040dcf286d 100644 --- a/chromium/services/device/hid/hid_manager_unittest.cc +++ b/chromium/services/device/hid/hid_manager_unittest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/run_loop.h" diff --git a/chromium/services/device/hid/hid_service.h b/chromium/services/device/hid/hid_service.h index 49a49dd7ae9..0784fd48f23 100644 --- a/chromium/services/device/hid/hid_service.h +++ b/chromium/services/device/hid/hid_service.h @@ -10,7 +10,7 @@ #include <string> #include <vector> -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/check.h" #include "base/macros.h" #include "base/memory/ref_counted.h" diff --git a/chromium/services/device/hid/hid_service_linux.cc b/chromium/services/device/hid/hid_service_linux.cc index a9b1fabc91a..257d3935389 100644 --- a/chromium/services/device/hid/hid_service_linux.cc +++ b/chromium/services/device/hid/hid_service_linux.cc @@ -30,15 +30,16 @@ #include "base/threading/scoped_blocking_call.h" #include "base/threading/sequenced_task_runner_handle.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "components/device_event_log/device_event_log.h" #include "device/udev_linux/scoped_udev.h" #include "device/udev_linux/udev_watcher.h" #include "services/device/hid/hid_connection_linux.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "base/system/sys_info.h" #include "chromeos/dbus/permission_broker/permission_broker_client.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) namespace device { @@ -354,7 +355,7 @@ void HidServiceLinux::Connect(const std::string& device_guid, } scoped_refptr<HidDeviceInfo> device_info = map_entry->second; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // Adapt |callback| to a repeating callback because the implementation below // requires separate callbacks for success and error. Only one will be called. auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); @@ -373,10 +374,10 @@ void HidServiceLinux::Connect(const std::string& device_guid, blocking_task_runner->PostTask( FROM_HERE, base::BindOnce(&HidServiceLinux::OpenOnBlockingThread, std::move(params))); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // static void HidServiceLinux::OnPathOpenComplete(std::unique_ptr<ConnectParams> params, @@ -433,7 +434,7 @@ void HidServiceLinux::OpenOnBlockingThread( std::move(params))); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) // static void HidServiceLinux::FinishOpen(std::unique_ptr<ConnectParams> params) { diff --git a/chromium/services/device/hid/hid_service_linux.h b/chromium/services/device/hid/hid_service_linux.h index 132de1e5218..1386fe1b6fc 100644 --- a/chromium/services/device/hid/hid_service_linux.h +++ b/chromium/services/device/hid/hid_service_linux.h @@ -13,6 +13,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "services/device/hid/hid_device_info.h" #include "services/device/hid/hid_service.h" @@ -35,7 +36,7 @@ class HidServiceLinux : public HidService { // opening a device. Because this operation crosses multiple threads these // functions are static and the necessary parameters are passed as a single // struct. -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) static void OnPathOpenComplete(std::unique_ptr<ConnectParams> params, base::ScopedFD fd); static void OnPathOpenError(const std::string& device_path, diff --git a/chromium/services/device/hid/hid_service_win.cc b/chromium/services/device/hid/hid_service_win.cc index e9233de42b4..ca4bd47dc01 100644 --- a/chromium/services/device/hid/hid_service_win.cc +++ b/chromium/services/device/hid/hid_service_win.cc @@ -17,7 +17,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/files/file.h" #include "base/location.h" #include "base/memory/free_deleter.h" diff --git a/chromium/services/device/media_transfer_protocol/BUILD.gn b/chromium/services/device/media_transfer_protocol/BUILD.gn index 31a8ff1e068..679be24a00b 100644 --- a/chromium/services/device/media_transfer_protocol/BUILD.gn +++ b/chromium/services/device/media_transfer_protocol/BUILD.gn @@ -2,10 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") import("//third_party/protobuf/proto_library.gni") -assert(is_chromeos) +assert(is_ash) assert(use_dbus) proto_library("mtp_file_entry_proto") { @@ -32,6 +33,7 @@ source_set("media_transfer_protocol") { ":mtp_file_entry_proto", ":mtp_storage_info_proto", "//base", + "//build:chromeos_buildflags", "//chromeos/dbus", "//dbus", ] diff --git a/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h b/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h index 9266787b00c..2f0a7da2c77 100644 --- a/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h +++ b/chromium/services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h @@ -19,10 +19,11 @@ #include "base/callback.h" #include "base/macros.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "services/device/public/mojom/mtp_file_entry.mojom.h" #include "services/device/public/mojom/mtp_storage_info.mojom.h" -#if !defined(OS_CHROMEOS) +#if !BUILDFLAG(IS_ASH) #error "Only used on ChromeOS" #endif diff --git a/chromium/services/device/media_transfer_protocol/mtp_device_manager.cc b/chromium/services/device/media_transfer_protocol/mtp_device_manager.cc index 18eda92e9ef..4c978dc7cc8 100644 --- a/chromium/services/device/media_transfer_protocol/mtp_device_manager.cc +++ b/chromium/services/device/media_transfer_protocol/mtp_device_manager.cc @@ -5,7 +5,7 @@ #include "services/device/media_transfer_protocol/mtp_device_manager.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "dbus/bus.h" #include "third_party/cros_system_api/dbus/service_constants.h" diff --git a/chromium/services/device/media_transfer_protocol/mtp_device_manager.h b/chromium/services/device/media_transfer_protocol/mtp_device_manager.h index 5fcd34093f2..7a964c2df11 100644 --- a/chromium/services/device/media_transfer_protocol/mtp_device_manager.h +++ b/chromium/services/device/media_transfer_protocol/mtp_device_manager.h @@ -16,6 +16,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" #include "base/threading/thread_checker.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/pending_associated_remote.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -23,7 +24,7 @@ #include "services/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h" #include "services/device/public/mojom/mtp_manager.mojom.h" -#if !defined(OS_CHROMEOS) +#if !BUILDFLAG(IS_ASH) #error "Only used on ChromeOS" #endif diff --git a/chromium/services/device/nfc/DIR_METADATA b/chromium/services/device/nfc/DIR_METADATA new file mode 100644 index 00000000000..881462d7223 --- /dev/null +++ b/chromium/services/device/nfc/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Blink>NFC" +}
\ No newline at end of file diff --git a/chromium/services/device/nfc/OWNERS b/chromium/services/device/nfc/OWNERS index 18960d009f3..3ced0f20e4f 100644 --- a/chromium/services/device/nfc/OWNERS +++ b/chromium/services/device/nfc/OWNERS @@ -1,6 +1,3 @@ blundell@chromium.org file://third_party/blink/renderer/modules/nfc/OWNERS - -# COMPONENT: Blink>NFC -# TEAM: device-dev@chromium.org
\ No newline at end of file diff --git a/chromium/services/device/public/cpp/BUILD.gn b/chromium/services/device/public/cpp/BUILD.gn index 9c31fcdc6d4..939dc5d00b3 100644 --- a/chromium/services/device/public/cpp/BUILD.gn +++ b/chromium/services/device/public/cpp/BUILD.gn @@ -33,6 +33,8 @@ source_set("test_support") { sources = [ "test/fake_sensor_and_provider.cc", "test/fake_sensor_and_provider.h", + "test/fake_serial_port_client.cc", + "test/fake_serial_port_client.h", "test/fake_serial_port_manager.cc", "test/fake_serial_port_manager.h", "test/fake_usb_device.cc", @@ -60,6 +62,7 @@ source_set("test_support") { ] deps = [ + "//build:chromeos_buildflags", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", "//services/device:lib", diff --git a/chromium/services/device/public/cpp/bluetooth/OWNERS b/chromium/services/device/public/cpp/bluetooth/OWNERS index 83626ef93f3..c16c8ebf61a 100644 --- a/chromium/services/device/public/cpp/bluetooth/OWNERS +++ b/chromium/services/device/public/cpp/bluetooth/OWNERS @@ -1,4 +1,3 @@ -odejesush@chromium.org ortuno@chromium.org reillyg@chromium.org diff --git a/chromium/services/device/public/cpp/hid/BUILD.gn b/chromium/services/device/public/cpp/hid/BUILD.gn index df32b07cd86..48f1dabd9bd 100644 --- a/chromium/services/device/public/cpp/hid/BUILD.gn +++ b/chromium/services/device/public/cpp/hid/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") source_set("hid") { @@ -31,7 +32,7 @@ source_set("hid") { "//services/service_manager/public/cpp", ] - if (is_chromeos) { + if (is_ash) { sources += [ "fake_input_service_linux.cc", "fake_input_service_linux.h", diff --git a/chromium/services/device/public/cpp/hid/fake_hid_manager.cc b/chromium/services/device/public/cpp/hid/fake_hid_manager.cc index 12db20ecb8c..69617c8b4e3 100644 --- a/chromium/services/device/public/cpp/hid/fake_hid_manager.cc +++ b/chromium/services/device/public/cpp/hid/fake_hid_manager.cc @@ -13,8 +13,23 @@ namespace device { -FakeHidConnection::FakeHidConnection(mojom::HidDeviceInfoPtr device) - : device_(std::move(device)) {} +FakeHidConnection::FakeHidConnection( + mojom::HidDeviceInfoPtr device, + mojo::PendingReceiver<mojom::HidConnection> receiver, + mojo::PendingRemote<mojom::HidConnectionClient> connection_client, + mojo::PendingRemote<mojom::HidConnectionWatcher> watcher) + : receiver_(this, std::move(receiver)), + device_(std::move(device)), + watcher_(std::move(watcher)) { + receiver_.set_disconnect_handler(base::BindOnce( + [](FakeHidConnection* self) { delete self; }, base::Unretained(this))); + if (watcher_) { + watcher_.set_disconnect_handler(base::BindOnce( + [](FakeHidConnection* self) { delete self; }, base::Unretained(this))); + } + if (connection_client) + client_.Bind(std::move(connection_client)); +} FakeHidConnection::~FakeHidConnection() = default; @@ -135,9 +150,10 @@ void FakeHidManager::Connect( } mojo::PendingRemote<mojom::HidConnection> connection; - mojo::MakeSelfOwnedReceiver( - std::make_unique<FakeHidConnection>(devices_[device_guid]->Clone()), - connection.InitWithNewPipeAndPassReceiver()); + // FakeHidConnection is self-owned. + new FakeHidConnection(devices_[device_guid]->Clone(), + connection.InitWithNewPipeAndPassReceiver(), + std::move(connection_client), std::move(watcher)); std::move(callback).Run(std::move(connection)); } diff --git a/chromium/services/device/public/cpp/hid/fake_hid_manager.h b/chromium/services/device/public/cpp/hid/fake_hid_manager.h index 2bc31f5d1b2..623efab4883 100644 --- a/chromium/services/device/public/cpp/hid/fake_hid_manager.h +++ b/chromium/services/device/public/cpp/hid/fake_hid_manager.h @@ -19,7 +19,11 @@ namespace device { class FakeHidConnection : public mojom::HidConnection { public: - explicit FakeHidConnection(mojom::HidDeviceInfoPtr device); + FakeHidConnection( + mojom::HidDeviceInfoPtr device, + mojo::PendingReceiver<mojom::HidConnection> receiver, + mojo::PendingRemote<mojom::HidConnectionClient> connection_client, + mojo::PendingRemote<mojom::HidConnectionWatcher> watcher); FakeHidConnection(FakeHidConnection&) = delete; FakeHidConnection& operator=(FakeHidConnection&) = delete; ~FakeHidConnection() override; @@ -37,7 +41,10 @@ class FakeHidConnection : public mojom::HidConnection { SendFeatureReportCallback callback) override; private: + mojo::Receiver<mojom::HidConnection> receiver_; mojom::HidDeviceInfoPtr device_; + mojo::Remote<mojom::HidConnectionClient> client_; + mojo::Remote<mojom::HidConnectionWatcher> watcher_; }; class FakeHidManager : public mojom::HidManager { diff --git a/chromium/services/device/public/mojom/BUILD.gn b/chromium/services/device/public/mojom/BUILD.gn index 55d880ef036..3b253917ede 100644 --- a/chromium/services/device/public/mojom/BUILD.gn +++ b/chromium/services/device/public/mojom/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") import("//mojo/public/tools/bindings/mojom.gni") @@ -40,7 +41,7 @@ mojom("mojom") { "//url/mojom:url_mojom_gurl", ] - if (is_chromeos) { + if (is_ash) { sources += [ "mtp_file_entry.mojom", "mtp_manager.mojom", @@ -177,11 +178,13 @@ mojom("usb") { "//third_party/blink/renderer/modules/webusb", "//chrome/browser/ui/webui/usb_internals:mojo_bindings_blink", ] + + webui_module_path = "/" } mojom("usb_test") { generate_java = true sources = [ "usb_manager_test.mojom" ] - public_deps = [ "//url/mojom:url_mojom_gurl" ] + webui_module_path = "/" } diff --git a/chromium/services/device/public/mojom/hid.mojom b/chromium/services/device/public/mojom/hid.mojom index 8229a5c5f3c..b93b66c0f3d 100644 --- a/chromium/services/device/public/mojom/hid.mojom +++ b/chromium/services/device/public/mojom/hid.mojom @@ -345,7 +345,7 @@ struct HidDeviceInfo { // A client interface for receiving a notification when HID devices are // physically connected or disconnected. -[Stable] +[Stable, Uuid="1b9b8008-dcf3-4c2e-9d68-ca3c47778817"] interface HidManagerClient { // Notifies the client that a device is added. DeviceAdded@0(HidDeviceInfo device_info); @@ -358,7 +358,7 @@ interface HidManagerClient { // Provides an interface for enumerating available HID devices, registering for // device connection and disconnection notifications, and opening a connection // for reading from and writing to a HID device. -[Stable] +[Stable, Uuid="9e931765-42c9-4afd-9dc5-9086621b7bb6"] interface HidManager { // Enumerates available devices and set as a client of HidManager. // The implementation of HidManager guarantees that the returned callback @@ -392,7 +392,7 @@ interface HidManager { // allows a device to define its own packet formats (reports) for sending or // receiving data. The methods in HidConnection send or receive data and specify // which report is used. -[Stable] +[Stable, Uuid="1b9b8008-dcf3-4c2e-9d68-ca3c47778817"] interface HidConnection { // A |report_id| of 0 is returned via callback if report IDs are not // supported by the device. @@ -412,7 +412,7 @@ interface HidConnection { // A client interface for receiving a notification when input reports are // received. -[Stable] +[Stable, Uuid="11f949ed-fa57-4a94-a433-90b72a2d2b63"] interface HidConnectionClient { // Notifies the client that an input report was received. A |report_id| of 0 // is passed if report IDs are not used by the device. @@ -429,6 +429,6 @@ interface HidConnectionClient { // itself as a watcher so it can be notified when the connection is closed. This // allows the service to keep track of whether there are open connections for // the purpose of drawing an indicator icon when a tab is using a HID device. -[Stable] +[Stable, Uuid="8af071b5-0994-4af7-9c3f-6025d7f9e9d0"] interface HidConnectionWatcher { }; diff --git a/chromium/services/device/public/mojom/serial.mojom b/chromium/services/device/public/mojom/serial.mojom index bb5f27e70a1..881421a1920 100644 --- a/chromium/services/device/public/mojom/serial.mojom +++ b/chromium/services/device/public/mojom/serial.mojom @@ -147,14 +147,17 @@ interface SerialPortManager { // Returns the list of serial ports currently available on the host. GetDevices() => (array<SerialPortInfo> devices); - // Creates a SerialPort instance attached to the port represented by |token|. - // If |use_alternate_path| is specified then the |alternate_path| for the - // port will be used instead. When the pipe passed in |port_receiver| is - // closed the optional pipe passed in |watcher| will also be closed. - GetPort(mojo_base.mojom.UnguessableToken token, - bool use_alternate_path, - pending_receiver<SerialPort> port_receiver, - pending_remote<SerialPortConnectionWatcher>? watcher); + // Opens the port represented by |token| using |options| and returns a + // connection to it as |port|. If |use_alternate_path| is specified then the + // |alternate_path| for the port will be used instead. When the pipe returned + // in |port| is closed the optional pipe passed in |watcher| will also be + // closed and vice a versa. + OpenPort(mojo_base.mojom.UnguessableToken token, + bool use_alternate_path, + SerialConnectionOptions options, + pending_remote<SerialPortClient> client, + pending_remote<SerialPortConnectionWatcher>? watcher) + => (pending_remote<SerialPort>? port); }; // Client interface for SerialPortManager. @@ -168,10 +171,6 @@ interface SerialPortManagerClient { // Performs asynchronous I/O on serial devices. interface SerialPort { - // Initiates an Open of the device then returns result. - Open(SerialConnectionOptions options, - pending_remote<SerialPortClient> client) => (bool success); - // Start writing data from |consumer| to the port. This should be called after // Open() or to restart data flow after when SerialPortClient#OnSendError is // called on |client| to indicate an error. @@ -201,8 +200,8 @@ interface SerialPort { // Performs a platform-specific port configuration query and returns got info. GetPortInfo() => (SerialConnectionInfo info); - // Closes the connection created by Open(). Once this returns no more data - // will be sent or received on |in_stream| or |out_stream|. + // Closes the port and this pipe. Once this returns no more data will be sent + // or received on |in_stream| or |out_stream|. Close() => (); }; diff --git a/chromium/services/device/public/mojom/usb_device.mojom b/chromium/services/device/public/mojom/usb_device.mojom index ea44e13a48a..89f39ea7a25 100644 --- a/chromium/services/device/public/mojom/usb_device.mojom +++ b/chromium/services/device/public/mojom/usb_device.mojom @@ -132,6 +132,15 @@ struct UsbControlTransferParams { uint8 request; uint16 value; uint16 index; + + // Unless the USB device was opened with |GetSecurityKeyDevice| then control + // transfers to attempt to configure an AOA[1] version with the following + // prefix will be rejected. These requests are blocked because they instruct + // an Android phone to act as a security key and this should not be exposed + // to, e.g., WebUSB. + // + // [1] https://source.android.com/devices/accessories/aoa + const string kSecurityKeyAOAVersion = "12eba9f901039b36"; }; // This enum is exposed through the chrome.usb extension API so existing values diff --git a/chromium/services/device/public/mojom/usb_manager.mojom b/chromium/services/device/public/mojom/usb_manager.mojom index 68b01cd08ff..cd0c3e009ee 100644 --- a/chromium/services/device/public/mojom/usb_manager.mojom +++ b/chromium/services/device/public/mojom/usb_manager.mojom @@ -24,6 +24,13 @@ interface UsbDeviceManager { GetDevice(string guid, pending_receiver<UsbDevice> device_receiver, pending_remote<UsbDeviceClient>? device_client); + // Requests a device by guid. The returned device will be permitted to send + // control transfers that attempt to configure an AOA[1] version that + // indicates a security key request. See comment in + // |UsbControlTransferParams|. + GetSecurityKeyDevice(string guid, pending_receiver<UsbDevice> device_receiver, + pending_remote<UsbDeviceClient>? device_client); + // Check Android permissions to access the device identified by |guid|. If // necessary the user is prompted to grant this access. If access is granted // the device information is refreshed to include data not previously diff --git a/chromium/services/device/screen_orientation/BUILD.gn b/chromium/services/device/screen_orientation/BUILD.gn index 11e526340c2..8b4c03ea44e 100644 --- a/chromium/services/device/screen_orientation/BUILD.gn +++ b/chromium/services/device/screen_orientation/BUILD.gn @@ -8,20 +8,10 @@ if (is_android) { import("//build/config/android/rules.gni") # For generate_jni(). } -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - source_set("screen_orientation") { visibility = [ "//services/device:lib" ] - sources = [ - "screen_orientation_listener_android.cc", - "screen_orientation_listener_android.h", - ] + sources = [] deps = [ "//base", @@ -31,6 +21,10 @@ source_set("screen_orientation") { public_deps = [ "//services/device/public/mojom" ] if (is_android) { + sources += [ + "screen_orientation_listener_android.cc", + "screen_orientation_listener_android.h", + ] deps += [ ":screen_orientation_jni_headers" ] } } diff --git a/chromium/services/device/screen_orientation/DIR_METADATA b/chromium/services/device/screen_orientation/DIR_METADATA new file mode 100644 index 00000000000..2a304f06a28 --- /dev/null +++ b/chromium/services/device/screen_orientation/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Blink>ScreenOrientation" +}
\ No newline at end of file diff --git a/chromium/services/device/screen_orientation/OWNERS b/chromium/services/device/screen_orientation/OWNERS index 60c92e4b8bc..88b35792ced 100644 --- a/chromium/services/device/screen_orientation/OWNERS +++ b/chromium/services/device/screen_orientation/OWNERS @@ -1,4 +1,2 @@ blundell@chromium.org mlamouri@chromium.org - -# COMPONENT: Blink>ScreenOrientation diff --git a/chromium/services/device/serial/BUILD.gn b/chromium/services/device/serial/BUILD.gn index 94aeb94c423..028db4a5f90 100644 --- a/chromium/services/device/serial/BUILD.gn +++ b/chromium/services/device/serial/BUILD.gn @@ -2,15 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - if (is_win || ((is_linux || is_chromeos) && use_udev) || is_mac) { config("platform_support") { visibility = [ ":serial" ] @@ -36,16 +30,8 @@ if (is_win || ((is_linux || is_chromeos) && use_udev) || is_mac) { "buffer.h", "serial_device_enumerator.cc", "serial_device_enumerator.h", - "serial_device_enumerator_linux.cc", - "serial_device_enumerator_linux.h", - "serial_device_enumerator_mac.cc", - "serial_device_enumerator_mac.h", - "serial_device_enumerator_win.cc", - "serial_device_enumerator_win.h", "serial_io_handler.cc", "serial_io_handler.h", - "serial_io_handler_win.cc", - "serial_io_handler_win.h", "serial_port_impl.cc", "serial_port_impl.h", "serial_port_manager_impl.cc", @@ -58,6 +44,7 @@ if (is_win || ((is_linux || is_chromeos) && use_udev) || is_mac) { deps = [ "//base", + "//build:chromeos_buildflags", "//components/device_event_log", "//device/bluetooth:bluetooth", "//device/bluetooth/public/cpp", @@ -68,6 +55,29 @@ if (is_win || ((is_linux || is_chromeos) && use_udev) || is_mac) { "//services/device/public/cpp/serial:switches", ] + if (is_linux || is_chromeos) { + sources += [ + "serial_device_enumerator_linux.cc", + "serial_device_enumerator_linux.h", + ] + } + + if (is_mac) { + sources += [ + "serial_device_enumerator_mac.cc", + "serial_device_enumerator_mac.h", + ] + } + + if (is_win) { + sources += [ + "serial_device_enumerator_win.cc", + "serial_device_enumerator_win.h", + "serial_io_handler_win.cc", + "serial_io_handler_win.h", + ] + } + if (is_posix) { sources += [ "serial_io_handler_posix.cc", @@ -79,7 +89,7 @@ if (is_win || ((is_linux || is_chromeos) && use_udev) || is_mac) { deps += [ "//device/udev_linux" ] } - if (is_chromeos) { + if (is_ash) { deps += [ "//chromeos/dbus/permission_broker" ] } diff --git a/chromium/services/device/serial/bluetooth_serial_port_impl.cc b/chromium/services/device/serial/bluetooth_serial_port_impl.cc index 3d8d293e080..fe527d0019a 100644 --- a/chromium/services/device/serial/bluetooth_serial_port_impl.cc +++ b/chromium/services/device/serial/bluetooth_serial_port_impl.cc @@ -13,33 +13,37 @@ namespace device { // static -void BluetoothSerialPortImpl::Create( +void BluetoothSerialPortImpl::Open( scoped_refptr<BluetoothAdapter> adapter, const std::string& address, - mojo::PendingReceiver<mojom::SerialPort> receiver, - mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) { + mojom::SerialConnectionOptionsPtr options, + mojo::PendingRemote<mojom::SerialPortClient> client, + mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher, + OpenCallback callback) { DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableBluetoothSerialPortProfileInSerialApi)); - // This BluetoothSerialPortImpl is owned by |receiver| and |watcher|. - new BluetoothSerialPortImpl(std::move(adapter), address, std::move(receiver), - std::move(watcher)); + // This BluetoothSerialPortImpl is owned by its |receiver_| and |watcher_| and + // will self-destruct on connection failure. + auto* port = new BluetoothSerialPortImpl( + std::move(adapter), address, std::move(options), std::move(client), + std::move(watcher)); + port->OpenSocket(std::move(callback)); } BluetoothSerialPortImpl::BluetoothSerialPortImpl( scoped_refptr<BluetoothAdapter> adapter, const std::string& address, - mojo::PendingReceiver<mojom::SerialPort> receiver, + mojom::SerialConnectionOptionsPtr options, + mojo::PendingRemote<mojom::SerialPortClient> client, mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) - : receiver_(this, std::move(receiver)), - watcher_(std::move(watcher)), + : watcher_(std::move(watcher)), + client_(std::move(client)), in_stream_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), out_stream_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), bluetooth_adapter_(std::move(adapter)), - address_(address) { - receiver_.set_disconnect_handler( - base::BindOnce([](BluetoothSerialPortImpl* self) { delete self; }, - base::Unretained(this))); + address_(address), + options_(std::move(options)) { if (watcher_.is_bound()) { watcher_.set_disconnect_handler( base::BindOnce([](BluetoothSerialPortImpl* self) { delete self; }, @@ -52,17 +56,14 @@ BluetoothSerialPortImpl::~BluetoothSerialPortImpl() { bluetooth_socket_->Close(); } -void BluetoothSerialPortImpl::Open( - mojom::SerialConnectionOptionsPtr options, - mojo::PendingRemote<mojom::SerialPortClient> client, - OpenCallback callback) { - if (client) - client_.Bind(std::move(client)); +void BluetoothSerialPortImpl::OpenSocket(OpenCallback callback) { BluetoothDevice* device = bluetooth_adapter_->GetDevice(address_); if (!device) { - std::move(callback).Run(false); + std::move(callback).Run(mojo::NullRemote()); + delete this; return; } + BluetoothDevice::UUIDSet device_uuids = device->GetUUIDs(); if (base::Contains(device_uuids, GetSerialPortProfileUUID())) { auto copyable_callback = @@ -75,7 +76,9 @@ void BluetoothSerialPortImpl::Open( weak_ptr_factory_.GetWeakPtr(), copyable_callback)); return; } - std::move(callback).Run(false); + + std::move(callback).Run(mojo::NullRemote()); + delete this; } void BluetoothSerialPortImpl::OnSocketConnected( @@ -83,13 +86,19 @@ void BluetoothSerialPortImpl::OnSocketConnected( scoped_refptr<BluetoothSocket> socket) { DCHECK(socket); bluetooth_socket_ = std::move(socket); - std::move(callback).Run(true); + mojo::PendingRemote<mojom::SerialPort> port = + receiver_.BindNewPipeAndPassRemote(); + receiver_.set_disconnect_handler( + base::BindOnce([](BluetoothSerialPortImpl* self) { delete self; }, + base::Unretained(this))); + std::move(callback).Run(std::move(port)); } void BluetoothSerialPortImpl::OnSocketConnectedError( OpenCallback callback, const std::string& message) { - std::move(callback).Run(false); + std::move(callback).Run(mojo::NullRemote()); + delete this; } void BluetoothSerialPortImpl::StartWriting( @@ -378,12 +387,8 @@ void BluetoothSerialPortImpl::GetPortInfo(GetPortInfoCallback callback) { } void BluetoothSerialPortImpl::Close(CloseCallback callback) { - client_.reset(); - if (bluetooth_socket_) { - bluetooth_socket_->Close(); - bluetooth_socket_.reset(); - } std::move(callback).Run(); + delete this; } } // namespace device diff --git a/chromium/services/device/serial/bluetooth_serial_port_impl.h b/chromium/services/device/serial/bluetooth_serial_port_impl.h index 46e0840d71f..69bdb6878b5 100644 --- a/chromium/services/device/serial/bluetooth_serial_port_impl.h +++ b/chromium/services/device/serial/bluetooth_serial_port_impl.h @@ -22,19 +22,25 @@ namespace device { // which is closed upon error in any of the interface functions. class BluetoothSerialPortImpl : public mojom::SerialPort { public: + using OpenCallback = + base::OnceCallback<void(mojo::PendingRemote<mojom::SerialPort>)>; + // Creates of instance of BluetoothSerialPortImpl using a Bluetooth // adapter, a Bluetooth device address and a receiver/watcher to // create a pipe. The receiver and watcher will own this object. - static void Create( + static void Open( scoped_refptr<BluetoothAdapter> adapter, const std::string& address, - mojo::PendingReceiver<mojom::SerialPort> receiver, - mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher); + mojom::SerialConnectionOptionsPtr options, + mojo::PendingRemote<mojom::SerialPortClient> client, + mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher, + OpenCallback callback); BluetoothSerialPortImpl( scoped_refptr<BluetoothAdapter> adapter, const std::string& address, - mojo::PendingReceiver<mojom::SerialPort> receiver, + mojom::SerialConnectionOptionsPtr options, + mojo::PendingRemote<mojom::SerialPortClient> client, mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher); BluetoothSerialPortImpl(const BluetoothSerialPortImpl&) = delete; BluetoothSerialPortImpl& operator=(const BluetoothSerialPortImpl&) = delete; @@ -42,9 +48,6 @@ class BluetoothSerialPortImpl : public mojom::SerialPort { private: // mojom::SerialPort methods: - void Open(mojom::SerialConnectionOptionsPtr options, - mojo::PendingRemote<mojom::SerialPortClient> client, - OpenCallback callback) override; void StartWriting(mojo::ScopedDataPipeConsumerHandle consumer) override; void StartReading(mojo::ScopedDataPipeProducerHandle producer) override; void Flush(mojom::SerialPortFlushMode mode, FlushCallback callback) override; @@ -57,6 +60,7 @@ class BluetoothSerialPortImpl : public mojom::SerialPort { void GetPortInfo(GetPortInfoCallback callback) override; void Close(CloseCallback callback) override; + void OpenSocket(OpenCallback callback); void WriteToSocket(MojoResult result, const mojo::HandleSignalsState& state); void ReadFromSocketAndWriteOut(MojoResult result, const mojo::HandleSignalsState& state); @@ -78,7 +82,7 @@ class BluetoothSerialPortImpl : public mojom::SerialPort { void OnBluetoothSocketSend(int num_bytes_sent); void OnBluetoothSocketSendError(const std::string& error_message); - mojo::Receiver<mojom::SerialPort> receiver_; + mojo::Receiver<mojom::SerialPort> receiver_{this}; mojo::Remote<mojom::SerialPortConnectionWatcher> watcher_; mojo::Remote<mojom::SerialPortClient> client_; diff --git a/chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc b/chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc index b74b85ef4a7..d839f807935 100644 --- a/chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc +++ b/chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc @@ -5,7 +5,7 @@ #include "services/device/serial/bluetooth_serial_port_impl.h" #include "base/command_line.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/gmock_callback_support.h" #include "base/test/task_environment.h" #include "device/bluetooth/bluetooth_adapter_factory.h" @@ -21,6 +21,7 @@ #include "net/base/io_buffer.h" #include "services/device/public/cpp/bluetooth/bluetooth_utils.h" #include "services/device/public/cpp/serial/serial_switches.h" +#include "services/device/public/cpp/test/fake_serial_port_client.h" #include "services/device/public/mojom/serial.mojom.h" #include "services/device/serial/buffer.h" #include "testing/gmock/include/gmock/gmock.h" @@ -73,35 +74,18 @@ class BluetoothSerialPortImplTest : public testing::Test { ConnectToService(GetSerialPortProfileUUID(), _, _)) .WillOnce(RunOnceCallback<1>(mock_socket_)); - BluetoothSerialPortImpl::Create(std::move(adapter), kDeviceAddress, - port->BindNewPipeAndPassReceiver(), - std::move(watcher_remote)); - } - - void CreatePortWithSocketError( - mojo::Remote<mojom::SerialPort>* port, - mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher>* watcher) { - mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher_remote; - *watcher = mojo::MakeSelfOwnedReceiver( - std::make_unique<mojom::SerialPortConnectionWatcher>(), - watcher_remote.InitWithNewPipeAndPassReceiver()); - - scoped_refptr<MockBluetoothAdapter> adapter = - base::MakeRefCounted<MockBluetoothAdapter>(); - device::BluetoothAdapterFactory::SetAdapterForTesting(adapter); - mock_device_ = std::make_unique<MockBluetoothDevice>( - adapter.get(), 0, "Test Device", kDeviceAddress, false, false); - mock_device_->AddUUID(GetSerialPortProfileUUID()); - - EXPECT_CALL(*adapter, GetDevice(kDeviceAddress)) - .WillOnce(Return(mock_device_.get())); - EXPECT_CALL(*mock_device_, - ConnectToService(GetSerialPortProfileUUID(), _, _)) - .WillOnce(RunOnceCallback<2>("Error")); - - BluetoothSerialPortImpl::Create(std::move(adapter), kDeviceAddress, - port->BindNewPipeAndPassReceiver(), - std::move(watcher_remote)); + base::RunLoop loop; + BluetoothSerialPortImpl::Open( + std::move(adapter), kDeviceAddress, + mojom::SerialConnectionOptions::New(), FakeSerialPortClient::Create(), + std::move(watcher_remote), + base::BindLambdaForTesting( + [&](mojo::PendingRemote<mojom::SerialPort> remote) { + EXPECT_TRUE(remote.is_valid()); + port->Bind(std::move(remote)); + loop.Quit(); + })); + loop.Run(); } void CreateDataPipe(mojo::ScopedDataPipeProducerHandle* producer, @@ -126,58 +110,34 @@ class BluetoothSerialPortImplTest : public testing::Test { base::test::SingleThreadTaskEnvironment task_environment_; }; -class FakeSerialPortClient : public mojom::SerialPortClient { - public: - FakeSerialPortClient() = default; - FakeSerialPortClient(FakeSerialPortClient&) = delete; - FakeSerialPortClient& operator=(FakeSerialPortClient&) = delete; - ~FakeSerialPortClient() override = default; - - void Bind(mojo::PendingReceiver<device::mojom::SerialPortClient> receiver) { - receiver_.Bind(std::move(receiver)); - } - - // mojom::SerialPortClient - void OnReadError(mojom::SerialReceiveError error) override {} - void OnSendError(mojom::SerialSendError error) override {} - - private: - mojo::Receiver<mojom::SerialPortClient> receiver_{this}; -}; - } // namespace -TEST_F(BluetoothSerialPortImplTest, NullSocketTest) { - mojo::Remote<mojom::SerialPort> serial_port; - mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher; - CreatePortWithSocketError(&serial_port, &watcher); - - mojo::ScopedDataPipeProducerHandle producer; - mojo::ScopedDataPipeConsumerHandle consumer; - CreateDataPipe(&producer, &consumer); +TEST_F(BluetoothSerialPortImplTest, OpenFailure) { + scoped_refptr<MockBluetoothAdapter> adapter = + base::MakeRefCounted<MockBluetoothAdapter>(); + device::BluetoothAdapterFactory::SetAdapterForTesting(adapter); + auto mock_device = std::make_unique<MockBluetoothDevice>( + adapter.get(), 0, "Test Device", kDeviceAddress, false, false); + mock_device->AddUUID(GetSerialPortProfileUUID()); - auto options = mojom::SerialConnectionOptions::New(); - mojo::PendingRemote<mojom::SerialPortClient> client; - FakeSerialPortClient serial_client; - serial_client.Bind(client.InitWithNewPipeAndPassReceiver()); - base::RunLoop loop; - serial_port->Open(std::move(options), std::move(client), - base::BindLambdaForTesting([&loop](bool success) { - EXPECT_FALSE(success); - loop.Quit(); - })); - loop.Run(); + EXPECT_CALL(*adapter, GetDevice(kDeviceAddress)) + .WillOnce(Return(mock_device.get())); + EXPECT_CALL(*mock_device, ConnectToService(GetSerialPortProfileUUID(), _, _)) + .WillOnce(RunOnceCallback<2>("Error")); EXPECT_CALL(mock_socket(), Receive(_, _, _)).Times(0); EXPECT_CALL(mock_socket(), Close()).Times(0); - serial_port->StartReading(std::move(producer)); - - base::RunLoop disconnect_loop; - watcher->set_connection_error_handler(disconnect_loop.QuitClosure()); - - serial_port.reset(); - disconnect_loop.Run(); + base::RunLoop loop; + BluetoothSerialPortImpl::Open( + std::move(adapter), kDeviceAddress, mojom::SerialConnectionOptions::New(), + FakeSerialPortClient::Create(), mojo::NullRemote(), + base::BindLambdaForTesting( + [&](mojo::PendingRemote<mojom::SerialPort> remote) { + EXPECT_FALSE(remote.is_valid()); + loop.Quit(); + })); + loop.Run(); } TEST_F(BluetoothSerialPortImplTest, StartWritingTest) { @@ -189,18 +149,6 @@ TEST_F(BluetoothSerialPortImplTest, StartWritingTest) { mojo::ScopedDataPipeConsumerHandle consumer; CreateDataPipe(&producer, &consumer); - auto options = mojom::SerialConnectionOptions::New(); - mojo::PendingRemote<mojom::SerialPortClient> client; - FakeSerialPortClient serial_client; - serial_client.Bind(client.InitWithNewPipeAndPassReceiver()); - base::RunLoop loop; - serial_port->Open(std::move(options), std::move(client), - base::BindLambdaForTesting([&loop](bool success) { - EXPECT_TRUE(success); - loop.Quit(); - })); - loop.Run(); - uint32_t bytes_read = std::char_traits<char>::length(kBuffer); auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>(kBuffer); @@ -244,18 +192,6 @@ TEST_F(BluetoothSerialPortImplTest, StartReadingTest) { mojo::ScopedDataPipeConsumerHandle consumer; CreateDataPipe(&producer, &consumer); - auto options = mojom::SerialConnectionOptions::New(); - mojo::PendingRemote<mojom::SerialPortClient> client; - FakeSerialPortClient serial_client; - serial_client.Bind(client.InitWithNewPipeAndPassReceiver()); - base::RunLoop loop; - serial_port->Open(std::move(options), std::move(client), - base::BindLambdaForTesting([&loop](bool success) { - EXPECT_TRUE(success); - loop.Quit(); - })); - loop.Run(); - uint32_t bytes_read = std::char_traits<char>::length(kBuffer); auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>(kBuffer); @@ -295,18 +231,6 @@ TEST_F(BluetoothSerialPortImplTest, Drain) { mojo::ScopedDataPipeConsumerHandle consumer; CreateDataPipe(&producer, &consumer); - auto options = mojom::SerialConnectionOptions::New(); - mojo::PendingRemote<mojom::SerialPortClient> client; - FakeSerialPortClient serial_client; - serial_client.Bind(client.InitWithNewPipeAndPassReceiver()); - base::RunLoop loop; - serial_port->Open(std::move(options), std::move(client), - base::BindLambdaForTesting([&loop](bool success) { - EXPECT_TRUE(success); - loop.Quit(); - })); - loop.Run(); - serial_port->StartWriting(std::move(consumer)); producer.reset(); @@ -331,17 +255,6 @@ TEST_F(BluetoothSerialPortImplTest, Close) { mojo::ScopedDataPipeConsumerHandle consumer; CreateDataPipe(&producer, &consumer); - auto options = mojom::SerialConnectionOptions::New(); - mojo::PendingRemote<mojom::SerialPortClient> client; - FakeSerialPortClient serial_client; - serial_client.Bind(client.InitWithNewPipeAndPassReceiver()); - base::RunLoop loop; - serial_port->Open( - std::move(options), std::move(client), - base::BindOnce([](base::RunLoop* loop, bool success) { loop->Quit(); }, - &loop)); - loop.Run(); - EXPECT_CALL(mock_socket(), Close()); base::RunLoop close_loop; diff --git a/chromium/services/device/serial/serial_io_handler.cc b/chromium/services/device/serial/serial_io_handler.cc index 5e1411a4813..d10f905fa46 100644 --- a/chromium/services/device/serial/serial_io_handler.cc +++ b/chromium/services/device/serial/serial_io_handler.cc @@ -8,7 +8,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/files/file_path.h" #include "base/location.h" #include "base/strings/string_util.h" @@ -16,11 +16,12 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "components/device_event_log/device_event_log.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "chromeos/dbus/permission_broker/permission_broker_client.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) namespace device { @@ -50,7 +51,7 @@ void SerialIoHandler::Open(const mojom::SerialConnectionOptions& options, DCHECK(ui_thread_task_runner_.get()); MergeConnectionOptions(options); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // Note: dbus clients are destroyed in PostDestroyThreads so passing |client| // as unretained is safe. auto* client = chromeos::PermissionBrokerClient::Get(); @@ -72,10 +73,10 @@ void SerialIoHandler::Open(const mojom::SerialConnectionOptions& options, {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::BindOnce(&SerialIoHandler::StartOpen, this, base::ThreadTaskRunnerHandle::Get())); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void SerialIoHandler::OnPathOpened( scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner, diff --git a/chromium/services/device/serial/serial_io_handler.h b/chromium/services/device/serial/serial_io_handler.h index cd49076f551..f14ac447ad3 100644 --- a/chromium/services/device/serial/serial_io_handler.h +++ b/chromium/services/device/serial/serial_io_handler.h @@ -18,6 +18,7 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "services/device/public/mojom/serial.mojom.h" #include "services/device/serial/buffer.h" @@ -40,7 +41,7 @@ class SerialIoHandler : public base::RefCountedThreadSafe<SerialIoHandler> { virtual void Open(const mojom::SerialConnectionOptions& options, OpenCompleteCallback callback); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // Signals that the port has been opened. void OnPathOpened( scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner, @@ -55,7 +56,7 @@ class SerialIoHandler : public base::RefCountedThreadSafe<SerialIoHandler> { // Reports the open error from the permission broker. void ReportPathOpenError(const std::string& error_name, const std::string& error_message); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) // Performs an async Read operation. Behavior is undefined if this is called // while a Read is already pending. Otherwise, the Done or DoneWithError diff --git a/chromium/services/device/serial/serial_io_handler_posix.cc b/chromium/services/device/serial/serial_io_handler_posix.cc index e768f572b71..c3469bd23c6 100644 --- a/chromium/services/device/serial/serial_io_handler_posix.cc +++ b/chromium/services/device/serial/serial_io_handler_posix.cc @@ -14,6 +14,7 @@ #include "base/files/file_util.h" #include "base/posix/eintr_wrapper.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "components/device_event_log/device_event_log.h" #if defined(OS_LINUX) || defined(OS_CHROMEOS) @@ -296,7 +297,7 @@ bool SerialIoHandlerPosix::ConfigurePortImpl() { } bool SerialIoHandlerPosix::PostOpen() { -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // The Chrome OS permission broker does not open devices in async mode. return base::SetNonBlocking(file().GetPlatformFile()); #else diff --git a/chromium/services/device/serial/serial_io_handler_win.cc b/chromium/services/device/serial/serial_io_handler_win.cc index 04eb76a8390..65e90477d53 100644 --- a/chromium/services/device/serial/serial_io_handler_win.cc +++ b/chromium/services/device/serial/serial_io_handler_win.cc @@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/sequence_checker.h" #include "base/task/current_thread.h" +#include "base/time/time.h" #include "components/device_event_log/device_event_log.h" namespace device { @@ -156,8 +157,22 @@ bool SerialIoHandlerWin::PostOpen() { read_context_.reset(new base::MessagePumpForIO::IOContext()); write_context_.reset(new base::MessagePumpForIO::IOContext()); + // Based on the MSDN documentation setting both ReadIntervalTimeout and + // ReadTotalTimeoutMultiplier to MAXDWORD should cause ReadFile() to return + // immediately if there is data in the buffer or when a byte arrives while + // waiting. + // + // ReadTotalTimeoutConstant is set to a value low enough to ensure that the + // timeout case is exercised frequently but high enough to avoid unnecessary + // wakeups as it is not possible to have ReadFile() return immediately when a + // byte is received without specifying a timeout. + // + // https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts#remarks COMMTIMEOUTS timeouts = {0}; - timeouts.ReadIntervalTimeout = 1; + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; + timeouts.ReadTotalTimeoutConstant = + base::TimeDelta::FromMinutes(5).InMilliseconds(); if (!::SetCommTimeouts(file().GetPlatformFile(), &timeouts)) { SERIAL_PLOG(DEBUG) << "Failed to set serial timeouts"; return false; diff --git a/chromium/services/device/serial/serial_port_impl.cc b/chromium/services/device/serial/serial_port_impl.cc index 01058c91808..89c9b3d4076 100644 --- a/chromium/services/device/serial/serial_port_impl.cc +++ b/chromium/services/device/serial/serial_port_impl.cc @@ -8,7 +8,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/single_thread_task_runner.h" #include "services/device/serial/buffer.h" #include "services/device/serial/serial_io_handler.h" @@ -16,39 +16,45 @@ namespace device { // static -void SerialPortImpl::Create( +void SerialPortImpl::Open( const base::FilePath& path, - mojo::PendingReceiver<mojom::SerialPort> receiver, + mojom::SerialConnectionOptionsPtr options, + mojo::PendingRemote<mojom::SerialPortClient> client, mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher, - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { - // This SerialPortImpl is owned by |receiver| and |watcher|. - new SerialPortImpl( + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, + OpenCallback callback) { + // This SerialPortImpl is owned by |receiver_| and |watcher_| and will + // self-destruct on close. + auto* port = new SerialPortImpl( device::SerialIoHandler::Create(path, std::move(ui_task_runner)), - std::move(receiver), std::move(watcher)); + std::move(client), std::move(watcher)); + port->OpenPort(*options, std::move(callback)); } // static -void SerialPortImpl::CreateForTesting( +void SerialPortImpl::OpenForTesting( scoped_refptr<SerialIoHandler> io_handler, - mojo::PendingReceiver<mojom::SerialPort> receiver, - mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) { - // This SerialPortImpl is owned by |receiver| and |watcher|. - new SerialPortImpl(std::move(io_handler), std::move(receiver), - std::move(watcher)); + mojom::SerialConnectionOptionsPtr options, + mojo::PendingRemote<mojom::SerialPortClient> client, + mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher, + OpenCallback callback) { + // This SerialPortImpl is owned by |receiver| and |watcher| and will + // self-destruct on close. + auto* port = new SerialPortImpl(std::move(io_handler), std::move(client), + std::move(watcher)); + port->OpenPort(*options, std::move(callback)); } SerialPortImpl::SerialPortImpl( scoped_refptr<SerialIoHandler> io_handler, - mojo::PendingReceiver<mojom::SerialPort> receiver, + mojo::PendingRemote<mojom::SerialPortClient> client, mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) - : receiver_(this, std::move(receiver)), - io_handler_(std::move(io_handler)), + : io_handler_(std::move(io_handler)), + client_(std::move(client)), watcher_(std::move(watcher)), in_stream_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), out_stream_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL) { - receiver_.set_disconnect_handler(base::BindOnce( - [](SerialPortImpl* self) { delete self; }, base::Unretained(this))); if (watcher_.is_bound()) { watcher_.set_disconnect_handler(base::BindOnce( [](SerialPortImpl* self) { delete self; }, base::Unretained(this))); @@ -60,13 +66,25 @@ SerialPortImpl::~SerialPortImpl() { io_handler_->Close(base::DoNothing()); } -void SerialPortImpl::Open(mojom::SerialConnectionOptionsPtr options, - mojo::PendingRemote<mojom::SerialPortClient> client, - OpenCallback callback) { - if (client) - client_.Bind(std::move(client)); +void SerialPortImpl::OpenPort(const mojom::SerialConnectionOptions& options, + OpenCallback callback) { + io_handler_->Open( + options, base::BindOnce(&SerialPortImpl::PortOpened, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + +void SerialPortImpl::PortOpened(OpenCallback callback, bool success) { + mojo::PendingRemote<SerialPort> port; + if (success) { + port = receiver_.BindNewPipeAndPassRemote(); + receiver_.set_disconnect_handler(base::BindOnce( + [](SerialPortImpl* self) { delete self; }, base::Unretained(this))); + } - io_handler_->Open(*options, std::move(callback)); + std::move(callback).Run(std::move(port)); + + if (!success) + delete this; } void SerialPortImpl::StartWriting(mojo::ScopedDataPipeConsumerHandle consumer) { @@ -183,7 +201,9 @@ void SerialPortImpl::GetPortInfo(GetPortInfoCallback callback) { } void SerialPortImpl::Close(CloseCallback callback) { - io_handler_->Close(std::move(callback)); + io_handler_->Close(base::BindOnce(&SerialPortImpl::PortClosed, + weak_factory_.GetWeakPtr(), + std::move(callback))); } void SerialPortImpl::WriteToPort(MojoResult result, @@ -300,4 +320,9 @@ void SerialPortImpl::WriteToOutStream(uint32_t bytes_read, out_stream_watcher_.ArmOrNotify(); } +void SerialPortImpl::PortClosed(CloseCallback callback) { + std::move(callback).Run(); + delete this; +} + } // namespace device diff --git a/chromium/services/device/serial/serial_port_impl.h b/chromium/services/device/serial/serial_port_impl.h index 1757a553316..db7016d2181 100644 --- a/chromium/services/device/serial/serial_port_impl.h +++ b/chromium/services/device/serial/serial_port_impl.h @@ -33,28 +33,32 @@ class SerialIoHandler; // This class must be constructed and run on IO thread. class SerialPortImpl : public mojom::SerialPort { public: - static void Create( + using OpenCallback = + base::OnceCallback<void(mojo::PendingRemote<mojom::SerialPort>)>; + + static void Open( const base::FilePath& path, - mojo::PendingReceiver<mojom::SerialPort> receiver, + mojom::SerialConnectionOptionsPtr options, + mojo::PendingRemote<mojom::SerialPortClient> client, mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher, - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, + OpenCallback callback); - static void CreateForTesting( + static void OpenForTesting( scoped_refptr<SerialIoHandler> io_handler, - mojo::PendingReceiver<mojom::SerialPort> receiver, - mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher); + mojom::SerialConnectionOptionsPtr options, + mojo::PendingRemote<mojom::SerialPortClient> client, + mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher, + OpenCallback callback); private: SerialPortImpl( scoped_refptr<SerialIoHandler> io_handler, - mojo::PendingReceiver<mojom::SerialPort> receiver, + mojo::PendingRemote<mojom::SerialPortClient> client, mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher); ~SerialPortImpl() override; // mojom::SerialPort methods: - void Open(mojom::SerialConnectionOptionsPtr options, - mojo::PendingRemote<mojom::SerialPortClient> client, - OpenCallback callback) override; void StartWriting(mojo::ScopedDataPipeConsumerHandle consumer) override; void StartReading(mojo::ScopedDataPipeProducerHandle producer) override; void Flush(mojom::SerialPortFlushMode mode, FlushCallback callback) override; @@ -67,6 +71,9 @@ class SerialPortImpl : public mojom::SerialPort { void GetPortInfo(GetPortInfoCallback callback) override; void Close(CloseCallback callback) override; + void OpenPort(const mojom::SerialConnectionOptions& options, + OpenCallback callback); + void PortOpened(OpenCallback callback, bool success); void WriteToPort(MojoResult result, const mojo::HandleSignalsState& state); void OnWriteToPortCompleted(uint32_t bytes_expected, uint32_t bytes_sent, @@ -74,8 +81,9 @@ class SerialPortImpl : public mojom::SerialPort { void ReadFromPortAndWriteOut(MojoResult result, const mojo::HandleSignalsState& state); void WriteToOutStream(uint32_t bytes_read, mojom::SerialReceiveError error); + void PortClosed(CloseCallback callback); - mojo::Receiver<mojom::SerialPort> receiver_; + mojo::Receiver<mojom::SerialPort> receiver_{this}; // Underlying connection to the serial port. scoped_refptr<SerialIoHandler> io_handler_; diff --git a/chromium/services/device/serial/serial_port_impl_unittest.cc b/chromium/services/device/serial/serial_port_impl_unittest.cc index fdd037496a9..806a828783b 100644 --- a/chromium/services/device/serial/serial_port_impl_unittest.cc +++ b/chromium/services/device/serial/serial_port_impl_unittest.cc @@ -5,7 +5,7 @@ #include "services/device/serial/serial_port_impl.h" #include "base/stl_util.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" @@ -79,9 +79,18 @@ class SerialPortImplTest : public DeviceServiceTestBase { *watcher = mojo::MakeSelfOwnedReceiver( std::make_unique<mojom::SerialPortConnectionWatcher>(), watcher_remote.InitWithNewPipeAndPassReceiver()); - SerialPortImpl::CreateForTesting( + base::RunLoop loop; + SerialPortImpl::OpenForTesting( base::MakeRefCounted<FakeSerialIoHandler>(), - port->BindNewPipeAndPassReceiver(), std::move(watcher_remote)); + mojom::SerialConnectionOptions::New(), mojo::NullRemote(), + std::move(watcher_remote), + base::BindLambdaForTesting( + [&](mojo::PendingRemote<mojom::SerialPort> pending_remote) { + EXPECT_TRUE(pending_remote.is_valid()); + port->Bind(std::move(pending_remote)); + loop.Quit(); + })); + loop.Run(); } void CreateDataPipe(mojo::ScopedDataPipeProducerHandle* producer, @@ -115,32 +124,6 @@ class SerialPortImplTest : public DeviceServiceTestBase { } }; -TEST_F(SerialPortImplTest, StartIoBeforeOpen) { - mojo::Remote<mojom::SerialPort> serial_port; - mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher_remote; - mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher = - mojo::MakeSelfOwnedReceiver( - std::make_unique<mojom::SerialPortConnectionWatcher>(), - watcher_remote.InitWithNewPipeAndPassReceiver()); - SerialPortImpl::Create( - base::FilePath(FILE_PATH_LITERAL("/dev/fakeserialmojo")), - serial_port.BindNewPipeAndPassReceiver(), std::move(watcher_remote), - task_environment_.GetMainThreadTaskRunner()); - - mojo::ScopedDataPipeConsumerHandle consumer = StartReading(serial_port.get()); - mojo::ScopedDataPipeProducerHandle producer = StartWriting(serial_port.get()); - - // Write some data so that StartWriting() will cause a call to Write(). - static const char kBuffer[] = "test"; - uint32_t bytes_written = base::size(kBuffer); - MojoResult result = - producer->WriteData(&kBuffer, &bytes_written, MOJO_WRITE_DATA_FLAG_NONE); - DCHECK_EQ(result, MOJO_RESULT_OK); - DCHECK_EQ(bytes_written, base::size(kBuffer)); - - base::RunLoop().RunUntilIdle(); -} - TEST_F(SerialPortImplTest, WatcherClosedWhenPortClosed) { mojo::Remote<mojom::SerialPort> serial_port; mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher; diff --git a/chromium/services/device/serial/serial_port_manager_impl.cc b/chromium/services/device/serial/serial_port_manager_impl.cc index 180d676c0b6..06df5ae996a 100644 --- a/chromium/services/device/serial/serial_port_manager_impl.cc +++ b/chromium/services/device/serial/serial_port_manager_impl.cc @@ -20,6 +20,17 @@ namespace device { +namespace { + +void OnPortOpened(mojom::SerialPortManager::OpenPortCallback callback, + const scoped_refptr<base::TaskRunner>& task_runner, + mojo::PendingRemote<mojom::SerialPort> port) { + task_runner->PostTask(FROM_HERE, + base::BindOnce(std::move(callback), std::move(port))); +} + +} // namespace + SerialPortManagerImpl::SerialPortManagerImpl( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) @@ -75,11 +86,13 @@ void SerialPortManagerImpl::GetDevices(GetDevicesCallback callback) { std::move(callback).Run(std::move(devices)); } -void SerialPortManagerImpl::GetPort( +void SerialPortManagerImpl::OpenPort( const base::UnguessableToken& token, bool use_alternate_path, - mojo::PendingReceiver<mojom::SerialPort> receiver, - mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) { + device::mojom::SerialConnectionOptionsPtr options, + mojo::PendingRemote<mojom::SerialPortClient> client, + mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher, + OpenPortCallback callback) { if (!enumerator_) { enumerator_ = SerialDeviceEnumerator::Create(ui_task_runner_); observed_enumerator_.Add(enumerator_.get()); @@ -89,20 +102,36 @@ void SerialPortManagerImpl::GetPort( if (path) { io_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&SerialPortImpl::Create, *path, std::move(receiver), - std::move(watcher), ui_task_runner_)); + base::BindOnce(&SerialPortImpl::Open, *path, std::move(options), + std::move(client), std::move(watcher), ui_task_runner_, + base::BindOnce(&OnPortOpened, std::move(callback), + base::SequencedTaskRunnerHandle::Get()))); return; } - DCHECK(bluetooth_enumerator_); - base::Optional<std::string> address = - bluetooth_enumerator_->GetAddressFromToken(token); - if (address) { - ui_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&BluetoothSerialPortImpl::Create, - bluetooth_enumerator_->GetAdapter(), *address, - std::move(receiver), std::move(watcher))); + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableBluetoothSerialPortProfileInSerialApi)) { + if (!bluetooth_enumerator_) { + bluetooth_enumerator_ = + std::make_unique<BluetoothSerialDeviceEnumerator>(); + observed_enumerator_.Add(bluetooth_enumerator_.get()); + } + base::Optional<std::string> address = + bluetooth_enumerator_->GetAddressFromToken(token); + if (address) { + ui_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &BluetoothSerialPortImpl::Open, + bluetooth_enumerator_->GetAdapter(), *address, std::move(options), + std::move(client), std::move(watcher), + base::BindOnce(&OnPortOpened, std::move(callback), + base::SequencedTaskRunnerHandle::Get()))); + return; + } } + + std::move(callback).Run(mojo::NullRemote()); } void SerialPortManagerImpl::OnPortAdded(const mojom::SerialPortInfo& port) { diff --git a/chromium/services/device/serial/serial_port_manager_impl.h b/chromium/services/device/serial/serial_port_manager_impl.h index 7e918711fbf..9b92c30743a 100644 --- a/chromium/services/device/serial/serial_port_manager_impl.h +++ b/chromium/services/device/serial/serial_port_manager_impl.h @@ -48,11 +48,12 @@ class SerialPortManagerImpl : public mojom::SerialPortManager, void SetClient( mojo::PendingRemote<mojom::SerialPortManagerClient> client) override; void GetDevices(GetDevicesCallback callback) override; - void GetPort( - const base::UnguessableToken& token, - bool use_alternate_path, - mojo::PendingReceiver<mojom::SerialPort> receiver, - mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) override; + void OpenPort(const base::UnguessableToken& token, + bool use_alternate_path, + device::mojom::SerialConnectionOptionsPtr options, + mojo::PendingRemote<mojom::SerialPortClient> client, + mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher, + OpenPortCallback callback) override; // SerialDeviceEnumerator::Observer methods: void OnPortAdded(const mojom::SerialPortInfo& port) override; diff --git a/chromium/services/device/serial/serial_port_manager_impl_unittest.cc b/chromium/services/device/serial/serial_port_manager_impl_unittest.cc index dd0989a443a..75d998b3d76 100644 --- a/chromium/services/device/serial/serial_port_manager_impl_unittest.cc +++ b/chromium/services/device/serial/serial_port_manager_impl_unittest.cc @@ -13,7 +13,7 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/task/post_task.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/gmock_callback_support.h" #include "base/threading/thread.h" #include "device/bluetooth/bluetooth_adapter_factory.h" @@ -28,6 +28,7 @@ #include "services/device/device_service_test_base.h" #include "services/device/public/cpp/bluetooth/bluetooth_utils.h" #include "services/device/public/cpp/serial/serial_switches.h" +#include "services/device/public/cpp/test/fake_serial_port_client.h" #include "services/device/public/mojom/serial.mojom.h" #include "services/device/serial/bluetooth_serial_device_enumerator.h" #include "services/device/serial/fake_serial_device_enumerator.h" @@ -68,25 +69,6 @@ class MockSerialPortManagerClient : public mojom::SerialPortManagerClient { mojo::Receiver<mojom::SerialPortManagerClient> receiver_{this}; }; -class FakeSerialPortClient : public mojom::SerialPortClient { - public: - FakeSerialPortClient() = default; - FakeSerialPortClient(FakeSerialPortClient&) = delete; - FakeSerialPortClient& operator=(FakeSerialPortClient&) = delete; - ~FakeSerialPortClient() override = default; - - void Bind(mojo::PendingReceiver<device::mojom::SerialPortClient> receiver) { - receiver_.Bind(std::move(receiver)); - } - - // mojom::SerialPortClient - void OnReadError(mojom::SerialReceiveError error) override {} - void OnSendError(mojom::SerialSendError error) override {} - - private: - mojo::Receiver<mojom::SerialPortClient> receiver_{this}; -}; - } // namespace class SerialPortManagerImplTest : public DeviceServiceTestBase { @@ -178,7 +160,7 @@ class SerialPortManagerImplTest : public DeviceServiceTestBase { // This is to simply test that we can enumerate devices on the platform without // hanging or crashing. -TEST_F(SerialPortManagerImplTest, SimpleConnectTest) { +TEST_F(SerialPortManagerImplTest, SimpleEnumerationTest) { // DeviceService has its own instance of SerialPortManagerImpl that is used to // bind the receiver over the one created for this test. mojo::Remote<mojom::SerialPortManager> port_manager; @@ -188,17 +170,6 @@ TEST_F(SerialPortManagerImplTest, SimpleConnectTest) { base::RunLoop loop; port_manager->GetDevices(base::BindLambdaForTesting( [&](std::vector<mojom::SerialPortInfoPtr> results) { - for (auto& device : results) { - mojo::Remote<mojom::SerialPort> serial_port; - port_manager->GetPort(device->token, - /*use_alternate_path=*/false, - serial_port.BindNewPipeAndPassReceiver(), - /*watcher=*/mojo::NullRemote()); - // Send a message on the pipe and wait for the response to make sure - // that the interface request was bound successfully. - serial_port.FlushForTesting(); - EXPECT_TRUE(serial_port.is_connected()); - } loop.Quit(); })); loop.Run(); @@ -225,6 +196,24 @@ TEST_F(SerialPortManagerImplTest, GetDevices) { loop.Run(); } +TEST_F(SerialPortManagerImplTest, OpenUnknownPort) { + mojo::Remote<mojom::SerialPortManager> port_manager; + Bind(port_manager.BindNewPipeAndPassReceiver()); + + base::RunLoop loop; + port_manager->OpenPort( + base::UnguessableToken::Create(), + /*use_alternate_path=*/false, mojom::SerialConnectionOptions::New(), + FakeSerialPortClient::Create(), + /*watcher=*/mojo::NullRemote(), + base::BindLambdaForTesting( + [&](mojo::PendingRemote<mojom::SerialPort> pending_remote) { + EXPECT_FALSE(pending_remote.is_valid()); + loop.Quit(); + })); + loop.Run(); +} + TEST_F(SerialPortManagerImplTest, PortRemovedAndAdded) { SetupBluetoothEnumerator(); mojo::Remote<mojom::SerialPortManager> port_manager; @@ -275,31 +264,7 @@ TEST_F(SerialPortManagerImplTest, PortRemovedAndAdded) { } } -TEST_F(SerialPortManagerImplTest, GetPort) { - SetupBluetoothEnumerator(); - mojo::Remote<mojom::SerialPortManager> port_manager; - Bind(port_manager.BindNewPipeAndPassReceiver()); - - base::RunLoop loop; - port_manager->GetDevices(base::BindLambdaForTesting( - [&](std::vector<mojom::SerialPortInfoPtr> results) { - EXPECT_GT(results.size(), 0u); - - mojo::Remote<mojom::SerialPort> serial_port; - port_manager->GetPort(results[0]->token, - /*use_alternate_path=*/false, - serial_port.BindNewPipeAndPassReceiver(), - /*watcher=*/mojo::NullRemote()); - // Send a message on the pipe and wait for the response to make sure - // that the interface request was bound successfully. - serial_port.FlushForTesting(); - EXPECT_TRUE(serial_port.is_connected()); - loop.Quit(); - })); - loop.Run(); -} - -TEST_F(SerialPortManagerImplTest, GetBluetoothDevicePort) { +TEST_F(SerialPortManagerImplTest, OpenBluetoothDevicePort) { SetupBluetoothEnumeratorWithExpectations(); mojo::Remote<mojom::SerialPortManager> port_manager; Bind(port_manager.BindNewPipeAndPassReceiver()); @@ -308,11 +273,6 @@ TEST_F(SerialPortManagerImplTest, GetBluetoothDevicePort) { mojo::MakeSelfOwnedReceiver( std::make_unique<mojom::SerialPortConnectionWatcher>(), watcher_remote.InitWithNewPipeAndPassReceiver()); - auto options = mojom::SerialConnectionOptions::New(); - mojo::PendingRemote<mojom::SerialPortClient> client; - FakeSerialPortClient serial_client; - serial_client.Bind(client.InitWithNewPipeAndPassReceiver()); - mojo::Remote<mojom::SerialPort> serial_port; // Since we only want to use devices enumerated by the Bluetooth // enumerator, we can remove the devices that are not. @@ -322,6 +282,7 @@ TEST_F(SerialPortManagerImplTest, GetBluetoothDevicePort) { const std::set<base::FilePath> expected_paths = { base::FilePath::FromUTF8Unsafe(kDeviceAddress)}; + mojo::Remote<mojom::SerialPort> serial_port; base::RunLoop loop; port_manager->GetDevices(base::BindLambdaForTesting( [&](std::vector<mojom::SerialPortInfoPtr> results) { @@ -331,15 +292,16 @@ TEST_F(SerialPortManagerImplTest, GetBluetoothDevicePort) { actual_paths.insert(results[i]->path); EXPECT_EQ(expected_paths, actual_paths); - port_manager->GetPort(results[0]->token, - /*use_alternate_path=*/false, - serial_port.BindNewPipeAndPassReceiver(), - /*watcher=*/std::move(watcher_remote)); - serial_port->Open(std::move(options), std::move(client), - base::BindLambdaForTesting([&loop](bool success) { - EXPECT_TRUE(success); - loop.Quit(); - })); + port_manager->OpenPort( + results[0]->token, + /*use_alternate_path=*/false, mojom::SerialConnectionOptions::New(), + FakeSerialPortClient::Create(), std::move(watcher_remote), + base::BindLambdaForTesting( + [&](mojo::PendingRemote<mojom::SerialPort> pending_remote) { + serial_port.Bind(std::move(pending_remote)); + EXPECT_TRUE(serial_port.is_connected()); + loop.Quit(); + })); })); loop.Run(); diff --git a/chromium/services/device/time_zone_monitor/BUILD.gn b/chromium/services/device/time_zone_monitor/BUILD.gn index 0e06756b169..54e38cff71e 100644 --- a/chromium/services/device/time_zone_monitor/BUILD.gn +++ b/chromium/services/device/time_zone_monitor/BUILD.gn @@ -2,31 +2,19 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") if (is_android) { import("//build/config/android/rules.gni") # For generate_jni(). } -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - source_set("time_zone_monitor") { visibility = [ "//services/device:lib" ] sources = [ "time_zone_monitor.cc", "time_zone_monitor.h", - "time_zone_monitor_android.cc", - "time_zone_monitor_android.h", - "time_zone_monitor_chromeos.cc", - "time_zone_monitor_linux.cc", - "time_zone_monitor_mac.mm", - "time_zone_monitor_win.cc", ] deps = [ @@ -39,18 +27,29 @@ source_set("time_zone_monitor") { public_deps = [ "//services/device/public/mojom" ] if (is_android) { + sources += [ + "time_zone_monitor_android.cc", + "time_zone_monitor_android.h", + ] deps += [ ":time_zone_monitor_jni_headers" ] } if (is_win) { + sources += [ "time_zone_monitor_win.cc" ] deps += [ "//ui/gfx" ] } - if (is_chromeos) { + if (is_linux) { + sources += [ "time_zone_monitor_linux.cc" ] + } + + if (is_ash) { + sources += [ "time_zone_monitor_chromeos.cc" ] deps += [ "//chromeos/settings" ] } if (is_mac) { + sources += [ "time_zone_monitor_mac.mm" ] frameworks = [ "Foundation.framework" ] } diff --git a/chromium/services/device/time_zone_monitor/time_zone_monitor_android.cc b/chromium/services/device/time_zone_monitor/time_zone_monitor_android.cc index 818670a821e..f57f9724e5d 100644 --- a/chromium/services/device/time_zone_monitor/time_zone_monitor_android.cc +++ b/chromium/services/device/time_zone_monitor/time_zone_monitor_android.cc @@ -34,7 +34,7 @@ void TimeZoneMonitorAndroid::TimeZoneChangedFromJava( // See base/i18n/icu_util.cc:InitializeIcuTimeZone() for more information. base::string16 zone_id = base::android::GetDefaultTimeZoneId(); std::unique_ptr<icu::TimeZone> new_zone(icu::TimeZone::createTimeZone( - icu::UnicodeString(FALSE, zone_id.data(), zone_id.length()))); + icu::UnicodeString(false, zone_id.data(), zone_id.length()))); UpdateIcuAndNotifyClients(std::move(new_zone)); } diff --git a/chromium/services/device/time_zone_monitor/time_zone_monitor_fuchsia.cc b/chromium/services/device/time_zone_monitor/time_zone_monitor_fuchsia.cc index fb508ea52cd..6c99389b3ff 100644 --- a/chromium/services/device/time_zone_monitor/time_zone_monitor_fuchsia.cc +++ b/chromium/services/device/time_zone_monitor/time_zone_monitor_fuchsia.cc @@ -48,7 +48,7 @@ class TimeZoneMonitorFuchsia : public TimeZoneMonitor { UpdateIcuAndNotifyClients(std::move(new_zone)); } - base::fuchsia::IntlProfileWatcher watcher_; + base::FuchsiaIntlProfileWatcher watcher_; }; } // namespace diff --git a/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc b/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc index c03a0d554c6..9f69bd65b62 100644 --- a/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc +++ b/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#if !defined(OS_CHROMEOS) - #include "services/device/time_zone_monitor/time_zone_monitor.h" #include <stddef.h> @@ -203,5 +201,3 @@ std::unique_ptr<TimeZoneMonitor> TimeZoneMonitor::Create( } } // namespace device - -#endif // !OS_CHROMEOS diff --git a/chromium/services/device/time_zone_monitor/time_zone_monitor_win.cc b/chromium/services/device/time_zone_monitor/time_zone_monitor_win.cc index 8c8fe730acb..9f5d5a69aa7 100644 --- a/chromium/services/device/time_zone_monitor/time_zone_monitor_win.cc +++ b/chromium/services/device/time_zone_monitor/time_zone_monitor_win.cc @@ -9,7 +9,7 @@ #include <memory> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "base/trace_event/trace_event.h" #include "third_party/icu/source/i18n/unicode/timezone.h" diff --git a/chromium/services/device/usb/BUILD.gn b/chromium/services/device/usb/BUILD.gn index f2d45240547..1c140a144a8 100644 --- a/chromium/services/device/usb/BUILD.gn +++ b/chromium/services/device/usb/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") import("//testing/libfuzzer/fuzzer_test.gni") @@ -11,13 +12,6 @@ if (is_android) { import("//build/config/android/rules.gni") # For generate_jni(). } -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - static_library("usb") { # Only targets under //services/device folder can depend on it. visibility = [ @@ -27,46 +21,21 @@ static_library("usb") { ] sources = [ - "usb_configuration_android.cc", - "usb_configuration_android.h", "usb_descriptors.cc", "usb_descriptors.h", "usb_device.cc", "usb_device.h", - "usb_device_android.cc", - "usb_device_android.h", "usb_device_handle.cc", "usb_device_handle.h", - "usb_device_handle_android.cc", - "usb_device_handle_android.h", - "usb_device_handle_mac.cc", - "usb_device_handle_mac.h", - "usb_device_handle_win.cc", - "usb_device_handle_win.h", - "usb_device_linux.cc", - "usb_device_linux.h", - "usb_device_mac.cc", - "usb_device_mac.h", - "usb_device_win.cc", - "usb_device_win.h", - "usb_endpoint_android.cc", - "usb_endpoint_android.h", - "usb_interface_android.cc", - "usb_interface_android.h", "usb_service.cc", "usb_service.h", - "usb_service_android.cc", - "usb_service_android.h", - "usb_service_mac.cc", - "usb_service_mac.h", - "usb_service_win.cc", - "usb_service_win.h", "webusb_descriptors.cc", "webusb_descriptors.h", ] deps = [ "//base/third_party/dynamic_annotations", + "//build:chromeos_buildflags", "//components/device_event_log", "//device/base", "//services/device/public/cpp/usb", @@ -78,11 +47,59 @@ static_library("usb") { "//url", ] - if (use_udev) { + if (is_android) { + sources += [ + "usb_configuration_android.cc", + "usb_configuration_android.h", + "usb_device_android.cc", + "usb_device_android.h", + "usb_device_handle_android.cc", + "usb_device_handle_android.h", + "usb_endpoint_android.cc", + "usb_endpoint_android.h", + "usb_interface_android.cc", + "usb_interface_android.h", + "usb_service_android.cc", + "usb_service_android.h", + ] + } + + if (is_win) { sources += [ - "usb_service_linux.cc", - "usb_service_linux.h", + "usb_device_handle_win.cc", + "usb_device_handle_win.h", + "usb_device_win.cc", + "usb_device_win.h", + "usb_service_win.cc", + "usb_service_win.h", ] + } + + if (is_mac) { + sources += [ + "usb_device_handle_mac.cc", + "usb_device_handle_mac.h", + "usb_device_mac.cc", + "usb_device_mac.h", + "usb_service_mac.cc", + "usb_service_mac.h", + ] + } + + if (is_linux || is_chromeos) { + sources += [ + "usb_device_linux.cc", + "usb_device_linux.h", + ] + } + + if (use_udev) { + if (is_linux || is_chromeos) { + sources += [ + "usb_service_linux.cc", + "usb_service_linux.h", + ] + } deps += [ "//device/udev_linux" ] } @@ -132,7 +149,7 @@ static_library("usb") { ] } - if (is_chromeos) { + if (is_ash) { deps += [ "//chromeos/dbus/permission_broker", "//dbus", diff --git a/chromium/services/device/usb/DIR_METADATA b/chromium/services/device/usb/DIR_METADATA new file mode 100644 index 00000000000..600c85a14d0 --- /dev/null +++ b/chromium/services/device/usb/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "IO>USB" +}
\ No newline at end of file diff --git a/chromium/services/device/usb/OWNERS b/chromium/services/device/usb/OWNERS index ddbf0e31a83..a6c2f1b9750 100644 --- a/chromium/services/device/usb/OWNERS +++ b/chromium/services/device/usb/OWNERS @@ -1,5 +1,2 @@ pfeldman@chromium.org file://chrome/browser/usb/OWNERS - -# COMPONENT: IO>USB -# TEAM: device-dev@chromium.org diff --git a/chromium/services/device/usb/mojo/BUILD.gn b/chromium/services/device/usb/mojo/BUILD.gn index e75fbb247cb..cefa32104d3 100644 --- a/chromium/services/device/usb/mojo/BUILD.gn +++ b/chromium/services/device/usb/mojo/BUILD.gn @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") + source_set("mojo") { sources = [ "device_impl.cc", @@ -13,6 +15,7 @@ source_set("mojo") { ] deps = [ + "//build:chromeos_buildflags", "//mojo/public/cpp/bindings", "//net", "//services/device/public/cpp/usb", @@ -21,7 +24,7 @@ source_set("mojo") { "//services/device/usb", ] - if (is_chromeos) { + if (is_ash) { deps += [ "//chromeos/dbus/permission_broker" ] } } diff --git a/chromium/services/device/usb/mojo/device_impl.cc b/chromium/services/device/usb/mojo/device_impl.cc index bc708148647..c8fe75013b1 100644 --- a/chromium/services/device/usb/mojo/device_impl.cc +++ b/chromium/services/device/usb/mojo/device_impl.cc @@ -84,13 +84,34 @@ void OnIsochronousTransferOut( std::move(callback).Run(std::move(packets)); } +// IsAndroidSecurityKeyRequest returns true if |params| is attempting to +// configure an Android phone to act as a security key. +bool IsAndroidSecurityKeyRequest( + const mojom::UsbControlTransferParamsPtr& params, + const std::vector<uint8_t>& data) { + // This matches a request to send an AOA version string: + // https://source.android.com/devices/accessories/aoa#attempt-to-start-in-accessory-mode + // + // The magic version is matched as a prefix because sending trailing NULs etc + // would be considered equivalent by Android but would not be caught by an + // exact match here. Android is case-sensitive thus a byte-wise match is + // suitable. + const char* magic = mojom::UsbControlTransferParams::kSecurityKeyAOAVersion; + return params->type == mojom::UsbControlTransferType::VENDOR && + params->request == 52 && params->index == 3 && + data.size() >= strlen(magic) && + memcmp(data.data(), magic, strlen(magic)) == 0; +} + } // namespace // static void DeviceImpl::Create(scoped_refptr<device::UsbDevice> device, mojo::PendingReceiver<mojom::UsbDevice> receiver, - mojo::PendingRemote<mojom::UsbDeviceClient> client) { - auto* device_impl = new DeviceImpl(std::move(device), std::move(client)); + mojo::PendingRemote<mojom::UsbDeviceClient> client, + bool allow_security_key_requests) { + auto* device_impl = new DeviceImpl(std::move(device), std::move(client), + allow_security_key_requests); device_impl->receiver_ = mojo::MakeSelfOwnedReceiver( base::WrapUnique(device_impl), std::move(receiver)); } @@ -100,8 +121,12 @@ DeviceImpl::~DeviceImpl() { } DeviceImpl::DeviceImpl(scoped_refptr<device::UsbDevice> device, - mojo::PendingRemote<mojom::UsbDeviceClient> client) - : device_(std::move(device)), observer_(this), client_(std::move(client)) { + mojo::PendingRemote<mojom::UsbDeviceClient> client, + bool allow_security_key_requests) + : device_(std::move(device)), + observer_(this), + allow_security_key_requests_(allow_security_key_requests), + client_(std::move(client)) { DCHECK(device_); observer_.Add(device_.get()); @@ -313,7 +338,9 @@ void DeviceImpl::ControlTransferOut(UsbControlTransferParamsPtr params, return; } - if (HasControlTransferPermission(params->recipient, params->index)) { + if (HasControlTransferPermission(params->recipient, params->index) && + (allow_security_key_requests_ || + !IsAndroidSecurityKeyRequest(params, data))) { auto buffer = base::MakeRefCounted<base::RefCountedBytes>(data); device_handle_->ControlTransfer( UsbTransferDirection::OUTBOUND, params->type, params->recipient, diff --git a/chromium/services/device/usb/mojo/device_impl.h b/chromium/services/device/usb/mojo/device_impl.h index 0965ca72663..70f7c827abf 100644 --- a/chromium/services/device/usb/mojo/device_impl.h +++ b/chromium/services/device/usb/mojo/device_impl.h @@ -31,13 +31,15 @@ class DeviceImpl : public mojom::UsbDevice, public device::UsbDevice::Observer { public: static void Create(scoped_refptr<device::UsbDevice> device, mojo::PendingReceiver<mojom::UsbDevice> receiver, - mojo::PendingRemote<mojom::UsbDeviceClient> client); + mojo::PendingRemote<mojom::UsbDeviceClient> client, + bool allow_security_key_requests); ~DeviceImpl() override; private: DeviceImpl(scoped_refptr<device::UsbDevice> device, - mojo::PendingRemote<mojom::UsbDeviceClient> client); + mojo::PendingRemote<mojom::UsbDeviceClient> client, + bool allow_security_key_requests); // Closes the device if it's open. This will always set |device_handle_| to // null. @@ -111,6 +113,7 @@ class DeviceImpl : public mojom::UsbDevice, public device::UsbDevice::Observer { bool opening_ = false; scoped_refptr<UsbDeviceHandle> device_handle_; + const bool allow_security_key_requests_; mojo::SelfOwnedReceiverRef<mojom::UsbDevice> receiver_; mojo::Remote<device::mojom::UsbDeviceClient> client_; base::WeakPtrFactory<DeviceImpl> weak_factory_{this}; diff --git a/chromium/services/device/usb/mojo/device_impl_unittest.cc b/chromium/services/device/usb/mojo/device_impl_unittest.cc index 4987fbe5519..ecd9ac6b810 100644 --- a/chromium/services/device/usb/mojo/device_impl_unittest.cc +++ b/chromium/services/device/usb/mojo/device_impl_unittest.cc @@ -22,7 +22,7 @@ #include "base/memory/ref_counted_memory.h" #include "base/run_loop.h" #include "base/stl_util.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -185,6 +185,7 @@ class USBDeviceImplTest : public testing::Test { const std::string& manufacturer, const std::string& product, const std::string& serial, + bool allow_security_key_requests, mojo::PendingRemote<mojom::UsbDeviceClient> client) { mock_device_ = new MockUsbDevice(vendor_id, product_id, manufacturer, product, serial); @@ -192,7 +193,7 @@ class USBDeviceImplTest : public testing::Test { mojo::Remote<mojom::UsbDevice> proxy; DeviceImpl::Create(mock_device_, proxy.BindNewPipeAndPassReceiver(), - std::move(client)); + std::move(client), allow_security_key_requests); // Set up mock handle calls to respond based on mock device configs // established by the test. @@ -227,9 +228,16 @@ class USBDeviceImplTest : public testing::Test { mojo::Remote<mojom::UsbDevice> GetMockDeviceProxy( mojo::PendingRemote<mojom::UsbDeviceClient> client) { return GetMockDeviceProxy(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF", + /*allow_security_key_requests=*/false, std::move(client)); } + mojo::Remote<mojom::UsbDevice> GetMockSecurityKeyDeviceProxy() { + return GetMockDeviceProxy(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF", + /*allow_security_key_requests=*/true, + mojo::NullRemote()); + } + mojo::Remote<mojom::UsbDevice> GetMockDeviceProxy() { return GetMockDeviceProxy(mojo::NullRemote()); } @@ -1020,5 +1028,81 @@ TEST_F(USBDeviceImplTest, IsochronousTransfer) { EXPECT_CALL(mock_handle(), Close()); } +class USBDeviceImplSecurityKeyTest : public USBDeviceImplTest, + public testing::WithParamInterface<bool> { +}; + +TEST_P(USBDeviceImplSecurityKeyTest, SecurityKeyControlTransferBlocked) { + const bool allow_security_key_requests = GetParam(); + mojo::Remote<mojom::UsbDevice> device; + if (allow_security_key_requests) { + device = GetMockSecurityKeyDeviceProxy(); + } else { + device = GetMockDeviceProxy(); + } + + EXPECT_CALL(mock_device(), OpenInternal(_)); + + { + base::RunLoop loop; + device->Open(base::BindOnce( + &ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); + loop.Run(); + } + + AddMockConfig(ConfigBuilder(1).AddInterface(7, 0, 1, 2, 3).Build()); + EXPECT_CALL(mock_handle(), SetConfigurationInternal(1, _)); + + { + base::RunLoop loop; + device->SetConfiguration( + 1, base::BindOnce(&ExpectResultAndThen, true, loop.QuitClosure())); + loop.Run(); + } + + const char* data_str = + mojom::UsbControlTransferParams::kSecurityKeyAOAVersion; + const std::vector<uint8_t> data( + reinterpret_cast<const uint8_t*>(data_str), + reinterpret_cast<const uint8_t*>(data_str) + strlen(data_str)); + + if (allow_security_key_requests) { + AddMockOutboundData(data); + EXPECT_CALL(mock_handle(), + ControlTransferInternal(UsbTransferDirection::OUTBOUND, + UsbControlTransferType::VENDOR, + UsbControlTransferRecipient::DEVICE, 52, + 0, 3, _, 0, _)); + } + + { + // This control transfer should be rejected, unless + // |allow_security_key_requests| is true, because it's a request to + // trigger security key functionality on Android devices. + + auto params = mojom::UsbControlTransferParams::New(); + params->type = UsbControlTransferType::VENDOR; + params->recipient = UsbControlTransferRecipient::DEVICE; + params->request = 52; + params->value = 0; + params->index = 3; + base::RunLoop loop; + device->ControlTransferOut( + std::move(params), data, 0, + base::BindOnce(&ExpectTransferStatusAndThen, + allow_security_key_requests + ? mojom::UsbTransferStatus::COMPLETED + : mojom::UsbTransferStatus::PERMISSION_DENIED, + loop.QuitClosure())); + loop.Run(); + } + + EXPECT_CALL(mock_handle(), Close()); +} + +INSTANTIATE_TEST_SUITE_P(USBDeviceImplSecurityKeyTests, + USBDeviceImplSecurityKeyTest, + testing::Values(false, true)); + } // namespace usb } // namespace device diff --git a/chromium/services/device/usb/mojo/device_manager_impl.cc b/chromium/services/device/usb/mojo/device_manager_impl.cc index f388efa4322..950ab9c0744 100644 --- a/chromium/services/device/usb/mojo/device_manager_impl.cc +++ b/chromium/services/device/usb/mojo/device_manager_impl.cc @@ -15,6 +15,7 @@ #include "base/callback_helpers.h" #include "base/files/file_util.h" #include "base/memory/ptr_util.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "services/device/public/cpp/usb/usb_utils.h" #include "services/device/public/mojom/usb_device.mojom.h" @@ -24,10 +25,10 @@ #include "services/device/usb/usb_device.h" #include "services/device/usb/usb_service.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "chromeos/dbus/permission_broker/permission_broker_client.h" #include "services/device/usb/usb_device_linux.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) namespace device { namespace usb { @@ -68,12 +69,18 @@ void DeviceManagerImpl::GetDevice( const std::string& guid, mojo::PendingReceiver<mojom::UsbDevice> device_receiver, mojo::PendingRemote<mojom::UsbDeviceClient> device_client) { - scoped_refptr<UsbDevice> device = usb_service_->GetDevice(guid); - if (!device) - return; + return GetDeviceInternal(guid, std::move(device_receiver), + std::move(device_client), + /*allow_security_key_requests=*/false); +} - DeviceImpl::Create(std::move(device), std::move(device_receiver), - std::move(device_client)); +void DeviceManagerImpl::GetSecurityKeyDevice( + const std::string& guid, + mojo::PendingReceiver<mojom::UsbDevice> device_receiver, + mojo::PendingRemote<mojom::UsbDeviceClient> device_client) { + return GetDeviceInternal(guid, std::move(device_receiver), + std::move(device_client), + /*allow_security_key_requests=*/true); } #if defined(OS_ANDROID) @@ -109,7 +116,7 @@ void DeviceManagerImpl::OnPermissionGrantedToRefresh( } #endif // defined(OS_ANDROID) -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void DeviceManagerImpl::CheckAccess(const std::string& guid, CheckAccessCallback callback) { scoped_refptr<UsbDevice> device = usb_service_->GetDevice(guid); @@ -162,7 +169,7 @@ void DeviceManagerImpl::OnOpenFileDescriptorError( << message; std::move(callback).Run(base::File()); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) void DeviceManagerImpl::SetClient( mojo::PendingAssociatedRemote<mojom::UsbDeviceManagerClient> client) { @@ -211,5 +218,18 @@ void DeviceManagerImpl::WillDestroyUsbService() { clients_.Clear(); } +void DeviceManagerImpl::GetDeviceInternal( + const std::string& guid, + mojo::PendingReceiver<mojom::UsbDevice> device_receiver, + mojo::PendingRemote<mojom::UsbDeviceClient> device_client, + bool allow_security_key_requests) { + scoped_refptr<UsbDevice> device = usb_service_->GetDevice(guid); + if (!device) + return; + + DeviceImpl::Create(std::move(device), std::move(device_receiver), + std::move(device_client), allow_security_key_requests); +} + } // namespace usb } // namespace device diff --git a/chromium/services/device/usb/mojo/device_manager_impl.h b/chromium/services/device/usb/mojo/device_manager_impl.h index c670c21189f..807f19d1af6 100644 --- a/chromium/services/device/usb/mojo/device_manager_impl.h +++ b/chromium/services/device/usb/mojo/device_manager_impl.h @@ -17,6 +17,7 @@ #include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/pending_associated_remote.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -56,6 +57,10 @@ class DeviceManagerImpl : public mojom::UsbDeviceManager, const std::string& guid, mojo::PendingReceiver<mojom::UsbDevice> device_receiver, mojo::PendingRemote<mojom::UsbDeviceClient> device_client) override; + void GetSecurityKeyDevice( + const std::string& guid, + mojo::PendingReceiver<mojom::UsbDevice> device_receiver, + mojo::PendingRemote<mojom::UsbDeviceClient> device_client) override; #if defined(OS_ANDROID) void RefreshDeviceInfo(const std::string& guid, @@ -65,7 +70,7 @@ class DeviceManagerImpl : public mojom::UsbDeviceManager, bool granted); #endif // defined(OS_ANDROID) -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void CheckAccess(const std::string& guid, CheckAccessCallback callback) override; @@ -80,7 +85,7 @@ class DeviceManagerImpl : public mojom::UsbDeviceManager, void OnOpenFileDescriptorError(OpenFileDescriptorCallback callback, const std::string& error_name, const std::string& message); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) void SetClient(mojo::PendingAssociatedRemote<mojom::UsbDeviceManagerClient> client) override; @@ -98,6 +103,11 @@ class DeviceManagerImpl : public mojom::UsbDeviceManager, void WillDestroyUsbService() override; void MaybeRunDeviceChangesCallback(); + void GetDeviceInternal( + const std::string& guid, + mojo::PendingReceiver<mojom::UsbDevice> device_receiver, + mojo::PendingRemote<mojom::UsbDeviceClient> device_client, + bool allow_security_key_requests); std::unique_ptr<UsbService> usb_service_; ScopedObserver<UsbService, UsbService::Observer> observer_; diff --git a/chromium/services/device/usb/usb_device_handle_android.cc b/chromium/services/device/usb/usb_device_handle_android.cc index e71b3d79f87..fa9eeb62250 100644 --- a/chromium/services/device/usb/usb_device_handle_android.cc +++ b/chromium/services/device/usb/usb_device_handle_android.cc @@ -34,6 +34,7 @@ UsbDeviceHandleAndroid::UsbDeviceHandleAndroid( const base::android::JavaRef<jobject>& wrapper) : UsbDeviceHandleUsbfs(device, std::move(fd), + base::ScopedFD(), UsbService::CreateBlockingTaskRunner()), j_object_(wrapper) {} diff --git a/chromium/services/device/usb/usb_device_handle_impl.cc b/chromium/services/device/usb/usb_device_handle_impl.cc index c204a0b9e90..c4ae3c372c6 100644 --- a/chromium/services/device/usb/usb_device_handle_impl.cc +++ b/chromium/services/device/usb/usb_device_handle_impl.cc @@ -11,7 +11,7 @@ #include <vector> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/location.h" #include "base/macros.h" #include "base/memory/ref_counted_memory.h" diff --git a/chromium/services/device/usb/usb_device_handle_usbfs.cc b/chromium/services/device/usb/usb_device_handle_usbfs.cc index 68eb5658725..8e0d035368d 100644 --- a/chromium/services/device/usb/usb_device_handle_usbfs.cc +++ b/chromium/services/device/usb/usb_device_handle_usbfs.cc @@ -141,6 +141,7 @@ class UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper { public: BlockingTaskRunnerHelper( base::ScopedFD fd, + base::ScopedFD lifeline_fd, scoped_refptr<UsbDeviceHandleUsbfs> device_handle, scoped_refptr<base::SequencedTaskRunner> task_runner); ~BlockingTaskRunnerHelper(); @@ -162,6 +163,7 @@ class UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper { void OnFileCanWriteWithoutBlocking(); base::ScopedFD fd_; + base::ScopedFD lifeline_fd_; scoped_refptr<UsbDeviceHandleUsbfs> device_handle_; scoped_refptr<base::SequencedTaskRunner> task_runner_; std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_; @@ -208,9 +210,11 @@ struct UsbDeviceHandleUsbfs::Transfer final { UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::BlockingTaskRunnerHelper( base::ScopedFD fd, + base::ScopedFD lifeline_fd, scoped_refptr<UsbDeviceHandleUsbfs> device_handle, scoped_refptr<base::SequencedTaskRunner> task_runner) : fd_(std::move(fd)), + lifeline_fd_(std::move(lifeline_fd)), device_handle_(std::move(device_handle)), task_runner_(std::move(task_runner)) {} @@ -356,9 +360,9 @@ void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper:: for (size_t i = 0; i < MAX_URBS_PER_EVENT; ++i) { base::ScopedBlockingCall scoped_blocking_call( FROM_HERE, base::BlockingType::MAY_BLOCK); - usbdevfs_urb* urb; + usbdevfs_urb* urb = nullptr; int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_REAPURBNDELAY, &urb)); - if (rc) { + if (rc || !urb) { if (errno == EAGAIN) break; USB_PLOG(DEBUG) << "Failed to reap urbs"; @@ -432,6 +436,7 @@ void UsbDeviceHandleUsbfs::Transfer::RunIsochronousCallback( UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs( scoped_refptr<UsbDevice> device, base::ScopedFD fd, + base::ScopedFD lifeline_fd, scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) : device_(device), fd_(fd.get()), @@ -441,8 +446,8 @@ UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs( DCHECK(fd.is_valid()); DCHECK(blocking_task_runner_); - helper_.reset( - new BlockingTaskRunnerHelper(std::move(fd), this, task_runner_)); + helper_ = std::make_unique<BlockingTaskRunnerHelper>( + std::move(fd), std::move(lifeline_fd), this, task_runner_); blocking_task_runner_->PostTask( FROM_HERE, base::BindOnce(&BlockingTaskRunnerHelper::Start, base::Unretained(helper_.get()))); @@ -472,6 +477,9 @@ void UsbDeviceHandleUsbfs::Close() { // The device is no longer attached so we don't have any endpoints either. endpoints_.clear(); + // The destruction of the |helper_| below will close the lifeline pipe if it + // exists and re-attach kernel driver. + // Releases |helper_|. blocking_task_runner_->PostTask( FROM_HERE, base::BindOnce(&UsbDeviceHandleUsbfs::CloseBlocking, this)); diff --git a/chromium/services/device/usb/usb_device_handle_usbfs.h b/chromium/services/device/usb/usb_device_handle_usbfs.h index 949ddd05327..10e4fecad8d 100644 --- a/chromium/services/device/usb/usb_device_handle_usbfs.h +++ b/chromium/services/device/usb/usb_device_handle_usbfs.h @@ -33,6 +33,7 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle { UsbDeviceHandleUsbfs( scoped_refptr<UsbDevice> device, base::ScopedFD fd, + base::ScopedFD lifeline_fd, scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); // UsbDeviceHandle implementation. diff --git a/chromium/services/device/usb/usb_device_handle_win.cc b/chromium/services/device/usb/usb_device_handle_win.cc index 1d94b7dc08c..9903ffeebb7 100644 --- a/chromium/services/device/usb/usb_device_handle_win.cc +++ b/chromium/services/device/usb/usb_device_handle_win.cc @@ -99,7 +99,7 @@ bool ResetPipeBlocking(WINUSB_INTERFACE_HANDLE handle, UCHAR pipeId) { base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, base::BlockingType::WILL_BLOCK); if (!WinUsb_ResetPipe(handle, pipeId)) { - USB_PLOG(DEBUG) << "Failed to reset pipe " << static_cast<int>(pipeId); + USB_PLOG(DEBUG) << "Failed to reset pipe " << int{pipeId}; return false; } @@ -111,8 +111,7 @@ bool SetCurrentAlternateSettingBlocking(WINUSB_INTERFACE_HANDLE handle, base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, base::BlockingType::WILL_BLOCK); if (!WinUsb_SetCurrentAlternateSetting(handle, settingNumber)) { - USB_PLOG(DEBUG) << "Failed to set alternate setting " - << static_cast<int>(settingNumber); + USB_PLOG(DEBUG) << "Failed to set alternate setting " << int{settingNumber}; return false; } @@ -203,7 +202,6 @@ void UsbDeviceHandleWin::Close() { return; device_->HandleClosed(this); - device_ = nullptr; if (hub_handle_.IsValid()) { CancelIo(hub_handle_.Get()); @@ -226,6 +224,8 @@ void UsbDeviceHandleWin::Close() { scoped_refptr<UsbDeviceHandleWin> self(this); while (!requests_.empty()) requests_.begin()->second->Abort(); + + device_ = nullptr; } void UsbDeviceHandleWin::SetConfiguration(int configuration_value, @@ -587,15 +587,31 @@ UsbDeviceHandleWin::UsbDeviceHandleWin(scoped_refptr<UsbDeviceWin> device) interface_info.info = interface.get(); RegisterEndpoints(interface.get(), *alternate); - if (interface->interface_number == interface->first_interface) { - auto it = device_->functions().find(interface->interface_number); - if (it != device_->functions().end()) { - interface_info.function_driver = it->second.driver; - interface_info.function_path = it->second.path; + if (device_->driver_type() == UsbDeviceWin::DriverType::kComposite) { + if (interface->interface_number == interface->first_interface) { + auto it = device_->functions().find(interface->interface_number); + if (it != device_->functions().end()) { + interface_info.function_driver = it->second.driver; + interface_info.function_path = it->second.path; + } } } } } + + if (device_->driver_type() == UsbDeviceWin::DriverType::kWinUSB) { + // If this is not a composite device we can assume UsbServiceWin has + // set up the device with a single function entry no matter how many + // functions the device appears to have based on its descriptors. + DCHECK_EQ(1u, device_->functions().size()); + DCHECK(base::Contains(device_->functions(), 0)); + const UsbDeviceWin::FunctionInfo& function_info = + device_->functions().find(0)->second; + DCHECK(base::Contains(interfaces_, 0)); + Interface& interface_info = interfaces_[0]; + interface_info.function_driver = function_info.driver; + interface_info.function_path = function_info.path; + } } UsbDeviceHandleWin::UsbDeviceHandleWin(scoped_refptr<UsbDeviceWin> device, @@ -660,12 +676,8 @@ void UsbDeviceHandleWin::OpenInterfaceHandle(Interface* interface, return; } - if (interface->info->first_interface != interface->info->interface_number) { - auto first_interface_it = - interfaces_.find(interface->info->first_interface); - DCHECK(first_interface_it != interfaces_.end()); - Interface* first_interface = &first_interface_it->second; - + Interface* first_interface = GetFirstInterfaceForFunction(interface); + if (first_interface != interface) { OpenInterfaceHandle( first_interface, base::BindOnce(&UsbDeviceHandleWin::OnFirstInterfaceOpened, @@ -684,6 +696,28 @@ void UsbDeviceHandleWin::OpenInterfaceHandle(Interface* interface, OnFunctionAvailable(std::move(callback), interface); } +UsbDeviceHandleWin::Interface* UsbDeviceHandleWin::GetFirstInterfaceForFunction( + Interface* interface) { + switch (device_->driver_type()) { + case UsbDeviceWin::DriverType::kUnsupported: + NOTREACHED(); + return nullptr; + case UsbDeviceWin::DriverType::kWinUSB: + // If WinUSB has been loaded for a composite device then all of its + // interfaces must be treated as a single function. + DCHECK(base::Contains(interfaces_, 0)); + return &interfaces_[0]; + case UsbDeviceWin::DriverType::kComposite: { + if (interface->info->interface_number == interface->info->first_interface) + return interface; + + auto it = interfaces_.find(interface->info->first_interface); + DCHECK(it != interfaces_.end()); + return &it->second; + } + } +} + void UsbDeviceHandleWin::OnFunctionAvailable(OpenInterfaceCallback callback, Interface* interface) { base::ScopedClosureRunner run_callback( @@ -694,16 +728,14 @@ void UsbDeviceHandleWin::OnFunctionAvailable(OpenInterfaceCallback callback, if (!base::EqualsCaseInsensitiveASCII(interface->function_driver, kWinUsbDriverName)) { - USB_LOG(ERROR) << "Interface " - << static_cast<int>(interface->info->interface_number) + USB_LOG(ERROR) << "Interface " << int{interface->info->interface_number} << " uses driver \"" << interface->function_driver << "\" instead of WinUSB."; return; } if (interface->function_path.empty()) { - USB_LOG(ERROR) << "Interface " - << static_cast<int>(interface->info->interface_number) + USB_LOG(ERROR) << "Interface " << int{interface->info->interface_number} << " has no device path."; return; } @@ -732,10 +764,12 @@ void UsbDeviceHandleWin::OnFirstInterfaceOpened(int interface_number, auto interface_it = interfaces_.find(interface_number); DCHECK(interface_it != interfaces_.end()); Interface* interface = &interface_it->second; - DCHECK_NE(interface->info->first_interface, - interface->info->interface_number); - DCHECK_EQ(interface->info->first_interface, - first_interface->info->interface_number); + if (device_->driver_type() == UsbDeviceWin::DriverType::kComposite) { + DCHECK_NE(interface->info->first_interface, + interface->info->interface_number); + DCHECK_EQ(interface->info->first_interface, + first_interface->info->interface_number); + } base::ScopedClosureRunner run_callback( base::BindOnce(std::move(callback), interface)); @@ -745,8 +779,8 @@ void UsbDeviceHandleWin::OnFirstInterfaceOpened(int interface_number, first_interface->reference_count++; - int index = - interface->info->interface_number - interface->info->first_interface - 1; + int index = interface->info->interface_number - + first_interface->info->interface_number - 1; WINUSB_INTERFACE_HANDLE handle; if (WinUsb_GetAssociatedInterface(first_interface->handle.Get(), index, &handle)) { @@ -754,7 +788,7 @@ void UsbDeviceHandleWin::OnFirstInterfaceOpened(int interface_number, } else { USB_PLOG(ERROR) << "Failed to get associated interface " << index << " from interface " - << static_cast<int>(interface->info->first_interface); + << int{first_interface->info->interface_number}; ReleaseInterfaceReference(first_interface); } } @@ -953,12 +987,7 @@ UsbDeviceHandleWin::Request* UsbDeviceHandleWin::MakeRequest( if (!interface) { handle = hub_handle_.Get(); } else { - if (interface->info->interface_number != interface->info->first_interface) { - auto it = interfaces_.find(interface->info->first_interface); - DCHECK(it != interfaces_.end()); - interface = &it->second; - } - + interface = GetFirstInterfaceForFunction(interface); handle = interface->handle.Get(); interface->reference_count++; } @@ -1083,18 +1112,25 @@ void UsbDeviceHandleWin::ReportIsochronousError( } bool UsbDeviceHandleWin::AllFunctionsEnumerated() const { - for (const auto& map_entry : interfaces_) { - const Interface& interface = map_entry.second; - - // Iterate over functions, rather than interfaces. - if (interface.info->first_interface != interface.info->interface_number) - continue; - - if (interface.function_driver.empty()) + switch (device_->driver_type()) { + case UsbDeviceWin::DriverType::kUnsupported: + NOTREACHED(); return false; + case UsbDeviceWin::DriverType::kWinUSB: + return true; + case UsbDeviceWin::DriverType::kComposite: + for (const auto& map_entry : interfaces_) { + const Interface& interface = map_entry.second; + + // Iterate over functions, rather than interfaces. + if (interface.info->first_interface != interface.info->interface_number) + continue; + + if (interface.function_driver.empty()) + return false; + } + return true; } - - return true; } void UsbDeviceHandleWin::ReleaseInterfaceReference(Interface* interface) { @@ -1111,11 +1147,9 @@ void UsbDeviceHandleWin::ReleaseInterfaceReference(Interface* interface) { if (interface->function_handle.IsValid()) interface->function_handle.Close(); - if (interface->info->interface_number != interface->info->first_interface) { - auto it = interfaces_.find(interface->info->first_interface); - DCHECK(it != interfaces_.end()); - ReleaseInterfaceReference(&it->second); - } + Interface* first_interface = GetFirstInterfaceForFunction(interface); + if (first_interface != interface) + ReleaseInterfaceReference(first_interface); } } // namespace device diff --git a/chromium/services/device/usb/usb_device_handle_win.h b/chromium/services/device/usb/usb_device_handle_win.h index de6e1459697..a07bc7b13b1 100644 --- a/chromium/services/device/usb/usb_device_handle_win.h +++ b/chromium/services/device/usb/usb_device_handle_win.h @@ -130,6 +130,13 @@ class UsbDeviceHandleWin : public UsbDeviceHandle { void OpenInterfaceHandle(Interface* interface, OpenInterfaceCallback callback); + + // Interfaces on a USB device are organized into "functions". When making a + // request to a device the first interface of each function is the one that + // has a valid |function_handle|. This function finds the correct interface + // for making requests to the provided interface based on the device's driver + // configuration. + Interface* GetFirstInterfaceForFunction(Interface* interface); void OnFunctionAvailable(OpenInterfaceCallback callback, Interface* interface); void OnFirstInterfaceOpened(int interface_number, diff --git a/chromium/services/device/usb/usb_device_impl.cc b/chromium/services/device/usb/usb_device_impl.cc index 94f2d9c8cf4..91fa8a1a69b 100644 --- a/chromium/services/device/usb/usb_device_impl.cc +++ b/chromium/services/device/usb/usb_device_impl.cc @@ -81,11 +81,12 @@ void UsbDeviceImpl::ReadAllConfigurations() { if (!usb_descriptor.Parse(base::make_span(buffer, rv))) USB_LOG(EVENT) << "Config descriptor index " << i << " was corrupt."; free(buffer); - - // Update the configurations. - device_info_->configurations = - std::move(usb_descriptor.device_info->configurations); } + + // The only populated field in |usb_descriptor| is the parsed configuration + // descriptor info. + device_info_->configurations = + std::move(usb_descriptor.device_info->configurations); } else { USB_LOG(EVENT) << "Failed to get device descriptor: " << ConvertPlatformUsbErrorToString(rv); diff --git a/chromium/services/device/usb/usb_device_linux.cc b/chromium/services/device/usb/usb_device_linux.cc index 070cdd53054..cc2b82713d9 100644 --- a/chromium/services/device/usb/usb_device_linux.cc +++ b/chromium/services/device/usb/usb_device_linux.cc @@ -11,19 +11,25 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/files/file_util.h" #include "base/location.h" #include "base/posix/eintr_wrapper.h" #include "base/sequenced_task_runner.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" +#include "build/chromeos_buildflags.h" #include "components/device_event_log/device_event_log.h" #include "services/device/usb/usb_descriptors.h" #include "services/device/usb/usb_device_handle_usbfs.h" #include "services/device/usb/usb_service.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "chromeos/dbus/permission_broker/permission_broker_client.h" -#endif // defined(OS_CHROMEOS) + +namespace { +constexpr uint32_t kAllInterfacesMask = ~0U; +} // namespace +#endif // BUILDFLAG(IS_ASH) namespace device { @@ -34,7 +40,7 @@ UsbDeviceLinux::UsbDeviceLinux(const std::string& device_path, UsbDeviceLinux::~UsbDeviceLinux() = default; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void UsbDeviceLinux::CheckUsbAccess(ResultCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -42,17 +48,26 @@ void UsbDeviceLinux::CheckUsbAccess(ResultCallback callback) { std::move(callback)); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) void UsbDeviceLinux::Open(OpenCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) + // create the pipe used as a lifetime to re-attach the original kernel driver + // to the USB device in permission_broker. + base::ScopedFD read_end, write_end; + if (!base::CreatePipe(&read_end, &write_end, /*non_blocking*/ true)) { + LOG(ERROR) << "Couldn't create pipe for USB device " << device_path_; + std::move(callback).Run(nullptr); + return; + } + auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); - chromeos::PermissionBrokerClient::Get()->OpenPath( - device_path_, + chromeos::PermissionBrokerClient::Get()->ClaimDevicePath( + device_path_, kAllInterfacesMask, read_end.get(), base::BindOnce(&UsbDeviceLinux::OnOpenRequestComplete, this, - copyable_callback), + copyable_callback, std::move(write_end)), base::BindOnce(&UsbDeviceLinux::OnOpenRequestError, this, copyable_callback)); #else @@ -63,19 +78,20 @@ void UsbDeviceLinux::Open(OpenCallback callback) { base::BindOnce(&UsbDeviceLinux::OpenOnBlockingThread, this, std::move(callback), base::ThreadTaskRunnerHandle::Get(), blocking_task_runner)); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void UsbDeviceLinux::OnOpenRequestComplete(OpenCallback callback, + base::ScopedFD lifeline_fd, base::ScopedFD fd) { if (!fd.is_valid()) { USB_LOG(EVENT) << "Did not get valid device handle from permission broker."; std::move(callback).Run(nullptr); return; } - Opened(std::move(fd), std::move(callback), + Opened(std::move(fd), std::move(lifeline_fd), std::move(callback), UsbService::CreateBlockingTaskRunner()); } @@ -97,7 +113,8 @@ void UsbDeviceLinux::OpenOnBlockingThread( if (fd.is_valid()) { task_runner->PostTask( FROM_HERE, base::BindOnce(&UsbDeviceLinux::Opened, this, std::move(fd), - std::move(callback), blocking_task_runner)); + base::ScopedFD(), std::move(callback), + blocking_task_runner)); } else { USB_PLOG(EVENT) << "Failed to open " << device_path_; task_runner->PostTask(FROM_HERE, @@ -105,15 +122,16 @@ void UsbDeviceLinux::OpenOnBlockingThread( } } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) void UsbDeviceLinux::Opened( base::ScopedFD fd, + base::ScopedFD lifeline_fd, OpenCallback callback, scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - scoped_refptr<UsbDeviceHandle> device_handle = - new UsbDeviceHandleUsbfs(this, std::move(fd), blocking_task_runner); + scoped_refptr<UsbDeviceHandle> device_handle = new UsbDeviceHandleUsbfs( + this, std::move(fd), std::move(lifeline_fd), blocking_task_runner); handles().push_back(device_handle.get()); std::move(callback).Run(device_handle); } diff --git a/chromium/services/device/usb/usb_device_linux.h b/chromium/services/device/usb/usb_device_linux.h index 6e6a87329af..255771f6043 100644 --- a/chromium/services/device/usb/usb_device_linux.h +++ b/chromium/services/device/usb/usb_device_linux.h @@ -15,6 +15,7 @@ #include "base/macros.h" #include "base/sequence_checker.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "services/device/usb/usb_device.h" namespace base { @@ -28,7 +29,7 @@ struct UsbDeviceDescriptor; class UsbDeviceLinux : public UsbDevice { public: // UsbDevice implementation: -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void CheckUsbAccess(ResultCallback callback) override; #endif // OS_CHROMEOS void Open(OpenCallback callback) override; @@ -51,8 +52,10 @@ class UsbDeviceLinux : public UsbDevice { ~UsbDeviceLinux() override; private: -#if defined(OS_CHROMEOS) - void OnOpenRequestComplete(OpenCallback callback, base::ScopedFD fd); +#if BUILDFLAG(IS_ASH) + void OnOpenRequestComplete(OpenCallback callback, + base::ScopedFD fd, + base::ScopedFD lifeline_fd); void OnOpenRequestError(OpenCallback callback, const std::string& error_name, const std::string& error_message); @@ -61,8 +64,9 @@ class UsbDeviceLinux : public UsbDevice { OpenCallback callback, scoped_refptr<base::SequencedTaskRunner> task_runner, scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) void Opened(base::ScopedFD fd, + base::ScopedFD lifeline_fd, OpenCallback callback, scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); diff --git a/chromium/services/device/usb/usb_device_win.cc b/chromium/services/device/usb/usb_device_win.cc index 59217626973..7c3f4afaa86 100644 --- a/chromium/services/device/usb/usb_device_win.cc +++ b/chromium/services/device/usb/usb_device_win.cc @@ -29,12 +29,12 @@ UsbDeviceWin::UsbDeviceWin(const std::wstring& device_path, const base::flat_map<int, FunctionInfo>& functions, uint32_t bus_number, uint32_t port_number, - bool is_supported) + DriverType driver_type) : UsbDevice(bus_number, port_number), device_path_(device_path), hub_path_(hub_path), functions_(functions), - is_supported_(is_supported) {} + driver_type_(driver_type) {} UsbDeviceWin::~UsbDeviceWin() {} @@ -42,7 +42,7 @@ void UsbDeviceWin::Open(OpenCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); scoped_refptr<UsbDeviceHandle> device_handle; - if (is_supported_) { + if (driver_type_ != DriverType::kUnsupported) { device_handle = new UsbDeviceHandleWin(this); handles().push_back(device_handle.get()); } diff --git a/chromium/services/device/usb/usb_device_win.h b/chromium/services/device/usb/usb_device_win.h index 9514777c6ad..f0a268c6f71 100644 --- a/chromium/services/device/usb/usb_device_win.h +++ b/chromium/services/device/usb/usb_device_win.h @@ -28,12 +28,18 @@ class UsbDeviceWin : public UsbDevice { std::wstring path; }; + enum class DriverType { + kUnsupported, + kWinUSB, + kComposite, + }; + UsbDeviceWin(const std::wstring& device_path, const std::wstring& hub_path, const base::flat_map<int, FunctionInfo>& functions, uint32_t bus_number, uint32_t port_number, - bool is_supported); + DriverType driver_type); // UsbDevice implementation: void Open(OpenCallback callback) override; @@ -48,6 +54,7 @@ class UsbDeviceWin : public UsbDevice { const base::flat_map<int, FunctionInfo>& functions() const { return functions_; } + DriverType driver_type() const { return driver_type_; } // Opens the device's parent hub in order to read the device, configuration // and string descriptors. @@ -85,7 +92,7 @@ class UsbDeviceWin : public UsbDevice { const std::wstring device_path_; const std::wstring hub_path_; base::flat_map<int, FunctionInfo> functions_; - const bool is_supported_; + const DriverType driver_type_; DISALLOW_COPY_AND_ASSIGN(UsbDeviceWin); }; diff --git a/chromium/services/device/usb/usb_service.h b/chromium/services/device/usb/usb_service.h index 3e9df5c05ab..623f3cd3f42 100644 --- a/chromium/services/device/usb/usb_service.h +++ b/chromium/services/device/usb/usb_service.h @@ -11,7 +11,7 @@ #include <unordered_set> #include <vector> -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/check.h" #include "base/macros.h" #include "base/memory/ref_counted.h" diff --git a/chromium/services/device/usb/usb_service_impl.cc b/chromium/services/device/usb/usb_service_impl.cc index 759a3f19dc9..dd54a6da828 100644 --- a/chromium/services/device/usb/usb_service_impl.cc +++ b/chromium/services/device/usb/usb_service_impl.cc @@ -13,7 +13,7 @@ #include "base/barrier_closure.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/location.h" #include "base/memory/ref_counted_memory.h" #include "base/memory/weak_ptr.h" diff --git a/chromium/services/device/usb/usb_service_win.cc b/chromium/services/device/usb/usb_service_win.cc index 51477ef37f3..2ac1866577f 100644 --- a/chromium/services/device/usb/usb_service_win.cc +++ b/chromium/services/device/usb/usb_service_win.cc @@ -503,10 +503,10 @@ class UsbServiceWin::BlockingTaskRunnerHelper { return; } - bool is_supported = false; + auto driver_type = UsbDeviceWin::DriverType::kUnsupported; std::vector<std::pair<int, UsbDeviceWin::FunctionInfo>> functions; if (IsCompositeDevice(service_name)) { - is_supported = true; + driver_type = UsbDeviceWin::DriverType::kComposite; // For composite devices Windows a composite device driver (usually the // built-in usbccgp.sys) creates child device nodes for each device // function. The device paths for these children must be opened in order @@ -518,9 +518,9 @@ class UsbServiceWin::BlockingTaskRunnerHelper { } } } else if (base::EqualsCaseInsensitiveASCII(service_name, L"winusb")) { - is_supported = true; - // A non-composite device has a single device node for all interfaces as - // it only has a single function. + driver_type = UsbDeviceWin::DriverType::kWinUSB; + // A non-composite device has a single device node for all interfaces. It + // may still include multiple functions but they will be ignored. UsbDeviceWin::FunctionInfo info; info.driver = service_name; info.path = device_path; @@ -538,7 +538,7 @@ class UsbServiceWin::BlockingTaskRunnerHelper { FROM_HERE, base::BindOnce(&UsbServiceWin::CreateDeviceObject, service_, std::move(device_path), std::move(hub_path), std::move(functions), bus_number, port_number, - is_supported, service_name)); + driver_type, service_name)); } void EnumeratePotentialFunction( @@ -660,7 +660,7 @@ void UsbServiceWin::CreateDeviceObject( const base::flat_map<int, UsbDeviceWin::FunctionInfo>& functions, uint32_t bus_number, uint32_t port_number, - bool is_supported, + UsbDeviceWin::DriverType driver_type, const std::wstring& driver_name) { // Devices that appear during initial enumeration are gathered into the first // result returned by GetDevices() and prevent device add/remove notifications @@ -669,7 +669,7 @@ void UsbServiceWin::CreateDeviceObject( ++first_enumeration_countdown_; auto device = base::MakeRefCounted<UsbDeviceWin>( - device_path, hub_path, functions, bus_number, port_number, is_supported); + device_path, hub_path, functions, bus_number, port_number, driver_type); devices_by_path_[device->device_path()] = device; device->ReadDescriptors(base::BindOnce(&UsbServiceWin::DeviceReady, weak_factory_.GetWeakPtr(), device, diff --git a/chromium/services/device/usb/usb_service_win.h b/chromium/services/device/usb/usb_service_win.h index f8841d82aff..6b6562c54fa 100644 --- a/chromium/services/device/usb/usb_service_win.h +++ b/chromium/services/device/usb/usb_service_win.h @@ -47,7 +47,7 @@ class UsbServiceWin final : public DeviceMonitorWin::Observer, const base::flat_map<int, UsbDeviceWin::FunctionInfo>& functions, uint32_t bus_number, uint32_t port_number, - bool is_supported, + UsbDeviceWin::DriverType driver_type, const std::wstring& driver_name); void UpdateFunction(const std::wstring& device_path, int interface_number, diff --git a/chromium/services/device/vibration/DIR_METADATA b/chromium/services/device/vibration/DIR_METADATA new file mode 100644 index 00000000000..7ca00b243ff --- /dev/null +++ b/chromium/services/device/vibration/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Blink>Vibration" +}
\ No newline at end of file diff --git a/chromium/services/device/vibration/OWNERS b/chromium/services/device/vibration/OWNERS index 0834219855f..56c64582cfe 100644 --- a/chromium/services/device/vibration/OWNERS +++ b/chromium/services/device/vibration/OWNERS @@ -1,4 +1,2 @@ blundell@chromium.org timvolodine@chromium.org - -# COMPONENT: Blink>Vibration diff --git a/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn b/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn index 16468a25c7c..17bd601db84 100644 --- a/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn +++ b/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") import("//build/config/ui.gni") @@ -34,7 +35,7 @@ source_set("power_save_blocker") { sources += [ "power_save_blocker_android.cc" ] deps += [ ":jni_headers" ] public_deps += [ "//ui/android" ] - } else if (is_chromeos) { + } else if (is_ash) { sources += [ "power_save_blocker_chromeos.cc" ] deps += [ "//chromeos/dbus/power", @@ -46,15 +47,20 @@ source_set("power_save_blocker") { "//dbus", "//ui/gfx", ] + if (use_x11 || use_ozone) { + deps += [ "//ui/base:features" ] + } if (use_x11) { deps += [ - "//ui/base:features", "//ui/base/x:x", "//ui/gfx/x", ] } if (use_ozone) { - deps += [ "//ui/display:display" ] + deps += [ + "//ui/base:features", + "//ui/display:display", + ] } } else if (is_mac) { sources += [ "power_save_blocker_mac.cc" ] diff --git a/chromium/services/device/wake_lock/power_save_blocker/DIR_METADATA b/chromium/services/device/wake_lock/power_save_blocker/DIR_METADATA new file mode 100644 index 00000000000..fb07a25cf9d --- /dev/null +++ b/chromium/services/device/wake_lock/power_save_blocker/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Core" +}
\ No newline at end of file diff --git a/chromium/services/device/wake_lock/power_save_blocker/OWNERS b/chromium/services/device/wake_lock/power_save_blocker/OWNERS index fdd793c1118..df746bc6f78 100644 --- a/chromium/services/device/wake_lock/power_save_blocker/OWNERS +++ b/chromium/services/device/wake_lock/power_save_blocker/OWNERS @@ -1,4 +1,2 @@ boliu@chromium.org hashimoto@chromium.org - -# COMPONENT: Internals>Core diff --git a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc index e3e15e3640f..92e3e974cbc 100644 --- a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc +++ b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc @@ -33,7 +33,6 @@ #include "ui/base/x/x11_util.h" // nogncheck #include "ui/gfx/x/connection.h" // nogncheck #include "ui/gfx/x/screensaver.h" // nogncheck -#include "ui/gfx/x/x11_types.h" // nogncheck #endif #if defined(USE_OZONE) diff --git a/chromium/services/image_annotation/annotator_unittest.cc b/chromium/services/image_annotation/annotator_unittest.cc index 40e6b6cc239..b8e65f5c281 100644 --- a/chromium/services/image_annotation/annotator_unittest.cc +++ b/chromium/services/image_annotation/annotator_unittest.cc @@ -7,7 +7,7 @@ #include <cstring> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/optional.h" diff --git a/chromium/services/image_annotation/image_annotation_metrics.cc b/chromium/services/image_annotation/image_annotation_metrics.cc index 5bb87f0c648..d9c2e18dd81 100644 --- a/chromium/services/image_annotation/image_annotation_metrics.cc +++ b/chromium/services/image_annotation/image_annotation_metrics.cc @@ -53,7 +53,7 @@ void ReportDescAnnotation(const mojom::AnnotationType type, // We use function variants here since our histogram name is not a "runtime // constant". - base::UmaHistogramPercentage( + base::UmaHistogramPercentageObsoleteDoNotUse( base::StringPrintf(kAnnotationConfidence, type_name.c_str()), confidence_percent); base::UmaHistogramBoolean( diff --git a/chromium/services/image_annotation/public/cpp/image_processor.cc b/chromium/services/image_annotation/public/cpp/image_processor.cc index 2bedb4203e0..a1567f6b298 100644 --- a/chromium/services/image_annotation/public/cpp/image_processor.cc +++ b/chromium/services/image_annotation/public/cpp/image_processor.cc @@ -26,7 +26,7 @@ SkBitmap ScaleImage(const SkBitmap& source, const float scale) { dest.eraseColor(0); // Use a canvas to scale the source image onto the new bitmap. - SkCanvas canvas(dest); + SkCanvas canvas(dest, SkSurfaceProps{}); canvas.scale(scale, scale); canvas.drawBitmap(source, 0, 0, nullptr /* paint */); diff --git a/chromium/services/media_session/BUILD.gn b/chromium/services/media_session/BUILD.gn index 7942cf55c36..9ee525f224f 100644 --- a/chromium/services/media_session/BUILD.gn +++ b/chromium/services/media_session/BUILD.gn @@ -15,8 +15,8 @@ source_set("lib") { "audio_focus_request.h", "media_controller.cc", "media_controller.h", - "media_session_service.cc", - "media_session_service.h", + "media_session_service_impl.cc", + "media_session_service_impl.h", ] configs += [ "//build/config/compiler:wexit_time_destructors" ] @@ -36,13 +36,14 @@ source_set("tests") { sources = [ "audio_focus_manager_unittest.cc", "media_controller_unittest.cc", - "media_session_service_unittest.cc", + "media_session_service_impl_unittest.cc", ] deps = [ ":lib", "//base", "//base/test:test_support", + "//build:chromeos_buildflags", "//services/media_session/public/cpp", "//services/media_session/public/cpp/test:test_support", "//services/media_session/public/mojom", diff --git a/chromium/services/media_session/DIR_METADATA b/chromium/services/media_session/DIR_METADATA new file mode 100644 index 00000000000..e278b5a0390 --- /dev/null +++ b/chromium/services/media_session/DIR_METADATA @@ -0,0 +1,12 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Media>Session" +} +team_email: "media-dev@chromium.org"
\ No newline at end of file diff --git a/chromium/services/media_session/OWNERS b/chromium/services/media_session/OWNERS index 0728e3a928d..70313512d0c 100644 --- a/chromium/services/media_session/OWNERS +++ b/chromium/services/media_session/OWNERS @@ -1,7 +1,2 @@ beccahughes@chromium.org mlamouri@chromium.org - - - -# COMPONENT: Internals>Media>Session -# TEAM: media-dev@chromium.org diff --git a/chromium/services/media_session/audio_focus_manager_unittest.cc b/chromium/services/media_session/audio_focus_manager_unittest.cc index 91f79d16f77..4aa4125493e 100644 --- a/chromium/services/media_session/audio_focus_manager_unittest.cc +++ b/chromium/services/media_session/audio_focus_manager_unittest.cc @@ -14,14 +14,14 @@ #include "base/test/power_monitor_test_base.h" #include "base/test/task_environment.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/media_session/audio_focus_request.h" -#include "services/media_session/media_session_service.h" +#include "services/media_session/media_session_service_impl.h" #include "services/media_session/public/cpp/test/audio_focus_test_util.h" #include "services/media_session/public/cpp/test/mock_media_session.h" #include "services/media_session/public/mojom/audio_focus.mojom.h" #include "services/media_session/public/mojom/media_session.mojom.h" -#include "services/media_session/public/mojom/media_session_service.mojom.h" #include "testing/gtest/include/gtest/gtest.h" namespace media_session { @@ -47,13 +47,12 @@ class AudioFocusManagerTest base::PowerMonitor::Initialize(std::move(power_source)); // Create an instance of the MediaSessionService. - service_ = std::make_unique<MediaSessionService>( - service_remote_.BindNewPipeAndPassReceiver()); - service_remote_->BindAudioFocusManager( + service_ = std::make_unique<MediaSessionServiceImpl>(); + service_->BindAudioFocusManager( audio_focus_remote_.BindNewPipeAndPassReceiver()); - service_remote_->BindAudioFocusManagerDebug( + service_->BindAudioFocusManagerDebug( audio_focus_debug_remote_.BindNewPipeAndPassReceiver()); - service_remote_->BindMediaControllerManager( + service_->BindMediaControllerManager( controller_manager_remote_.BindNewPipeAndPassReceiver()); audio_focus_remote_->SetEnforcementMode(GetParam()); @@ -65,7 +64,6 @@ class AudioFocusManagerTest base::RunLoop().RunUntilIdle(); service_.reset(); - service_remote_.reset(); base::PowerMonitor::ShutdownForTesting(); } @@ -183,7 +181,7 @@ class AudioFocusManagerTest mojo::Remote<mojom::AudioFocusManager> CreateAudioFocusManagerRemote() { mojo::Remote<mojom::AudioFocusManager> remote; - service_remote_->BindAudioFocusManager(remote.BindNewPipeAndPassReceiver()); + service_->BindAudioFocusManager(remote.BindNewPipeAndPassReceiver()); return remote; } @@ -194,7 +192,7 @@ class AudioFocusManagerTest } bool IsEnforcementEnabled() const { -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // Enforcement is enabled by default on Chrome OS. if (GetParam() == mojom::EnforcementMode::kDefault) return true; @@ -281,8 +279,7 @@ class AudioFocusManagerTest base::test::TaskEnvironment task_environment_; - std::unique_ptr<MediaSessionService> service_; - mojo::Remote<mojom::MediaSessionService> service_remote_; + std::unique_ptr<MediaSessionServiceImpl> service_; mojo::Remote<mojom::AudioFocusManager> audio_focus_remote_; mojo::Remote<mojom::AudioFocusManagerDebug> audio_focus_debug_remote_; diff --git a/chromium/services/media_session/media_controller_unittest.cc b/chromium/services/media_session/media_controller_unittest.cc index 164cd397457..77b608d0a5c 100644 --- a/chromium/services/media_session/media_controller_unittest.cc +++ b/chromium/services/media_session/media_controller_unittest.cc @@ -14,13 +14,12 @@ #include "base/time/time.h" #include "base/unguessable_token.h" #include "mojo/public/cpp/bindings/remote.h" -#include "services/media_session/media_session_service.h" +#include "services/media_session/media_session_service_impl.h" #include "services/media_session/public/cpp/media_metadata.h" #include "services/media_session/public/cpp/test/mock_media_session.h" #include "services/media_session/public/cpp/test/test_media_controller.h" #include "services/media_session/public/mojom/constants.mojom.h" #include "services/media_session/public/mojom/media_session.mojom.h" -#include "services/media_session/public/mojom/media_session_service.mojom.h" #include "testing/gtest/include/gtest/gtest.h" namespace media_session { @@ -31,11 +30,10 @@ class MediaControllerTest : public testing::Test { void SetUp() override { // Create an instance of the MediaSessionService and bind some interfaces. - service_ = std::make_unique<MediaSessionService>( - service_remote_.BindNewPipeAndPassReceiver()); - service_remote_->BindAudioFocusManager( + service_ = std::make_unique<MediaSessionServiceImpl>(); + service_->BindAudioFocusManager( audio_focus_remote_.BindNewPipeAndPassReceiver()); - service_remote_->BindMediaControllerManager( + service_->BindMediaControllerManager( controller_manager_remote_.BindNewPipeAndPassReceiver()); controller_manager_remote_->CreateActiveMediaController( @@ -72,7 +70,6 @@ class MediaControllerTest : public testing::Test { private: base::test::TaskEnvironment task_environment_; std::unique_ptr<MediaSessionService> service_; - mojo::Remote<mojom::MediaSessionService> service_remote_; mojo::Remote<mojom::AudioFocusManager> audio_focus_remote_; mojo::Remote<mojom::MediaController> media_controller_remote_; mojo::Remote<mojom::MediaControllerManager> controller_manager_remote_; diff --git a/chromium/services/media_session/media_session_service.cc b/chromium/services/media_session/media_session_service_impl.cc index 7672a8d0703..27534e2cc1a 100644 --- a/chromium/services/media_session/media_session_service.cc +++ b/chromium/services/media_session/media_session_service_impl.cc @@ -2,31 +2,29 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "services/media_session/media_session_service.h" +#include "services/media_session/media_session_service_impl.h" #include "base/bind.h" #include "services/media_session/audio_focus_manager.h" namespace media_session { -MediaSessionService::MediaSessionService( - mojo::PendingReceiver<mojom::MediaSessionService> receiver) - : receiver_(this, std::move(receiver)), - audio_focus_manager_(std::make_unique<AudioFocusManager>()) {} +MediaSessionServiceImpl::MediaSessionServiceImpl() + : audio_focus_manager_(std::make_unique<AudioFocusManager>()) {} -MediaSessionService::~MediaSessionService() = default; +MediaSessionServiceImpl::~MediaSessionServiceImpl() = default; -void MediaSessionService::BindAudioFocusManager( +void MediaSessionServiceImpl::BindAudioFocusManager( mojo::PendingReceiver<mojom::AudioFocusManager> receiver) { audio_focus_manager_->BindToInterface(std::move(receiver)); } -void MediaSessionService::BindAudioFocusManagerDebug( +void MediaSessionServiceImpl::BindAudioFocusManagerDebug( mojo::PendingReceiver<mojom::AudioFocusManagerDebug> receiver) { audio_focus_manager_->BindToDebugInterface(std::move(receiver)); } -void MediaSessionService::BindMediaControllerManager( +void MediaSessionServiceImpl::BindMediaControllerManager( mojo::PendingReceiver<mojom::MediaControllerManager> receiver) { audio_focus_manager_->BindToControllerManagerInterface(std::move(receiver)); } diff --git a/chromium/services/media_session/media_session_service.h b/chromium/services/media_session/media_session_service_impl.h index 947c92b2c34..c608ab181b1 100644 --- a/chromium/services/media_session/media_session_service.h +++ b/chromium/services/media_session/media_session_service_impl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SERVICES_MEDIA_SESSION_MEDIA_SESSION_SERVICE_H_ -#define SERVICES_MEDIA_SESSION_MEDIA_SESSION_SERVICE_H_ +#ifndef SERVICES_MEDIA_SESSION_MEDIA_SESSION_SERVICE_IMPL_H_ +#define SERVICES_MEDIA_SESSION_MEDIA_SESSION_SERVICE_IMPL_H_ #include <memory> #include <string> @@ -11,24 +11,20 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" -#include "services/media_session/public/mojom/media_session_service.mojom.h" +#include "services/media_session/public/cpp/media_session_service.h" namespace media_session { class AudioFocusManager; -class MediaSessionService : public mojom::MediaSessionService { +class MediaSessionServiceImpl : public MediaSessionService { public: - explicit MediaSessionService( - mojo::PendingReceiver<mojom::MediaSessionService> receiver); - ~MediaSessionService() override; + MediaSessionServiceImpl(); + ~MediaSessionServiceImpl() override; + MediaSessionServiceImpl(const MediaSessionServiceImpl&) = delete; + MediaSessionServiceImpl& operator=(const MediaSessionServiceImpl&) = delete; - const AudioFocusManager& audio_focus_manager_for_testing() const { - return *audio_focus_manager_.get(); - } - - private: - // mojom::MediaSessionService implementation: + // MediaSessionService implementation: void BindAudioFocusManager( mojo::PendingReceiver<mojom::AudioFocusManager> receiver) override; void BindAudioFocusManagerDebug( @@ -36,12 +32,14 @@ class MediaSessionService : public mojom::MediaSessionService { void BindMediaControllerManager( mojo::PendingReceiver<mojom::MediaControllerManager> receiver) override; - mojo::Receiver<mojom::MediaSessionService> receiver_; - std::unique_ptr<AudioFocusManager> audio_focus_manager_; + const AudioFocusManager& audio_focus_manager_for_testing() const { + return *audio_focus_manager_.get(); + } - DISALLOW_COPY_AND_ASSIGN(MediaSessionService); + private: + std::unique_ptr<AudioFocusManager> audio_focus_manager_; }; } // namespace media_session -#endif // SERVICES_MEDIA_SESSION_MEDIA_SESSION_SERVICE_H_ +#endif // SERVICES_MEDIA_SESSION_MEDIA_SESSION_SERVICE_IMPL_H_ diff --git a/chromium/services/media_session/media_session_service_unittest.cc b/chromium/services/media_session/media_session_service_impl_unittest.cc index 34c8597ecad..f889e7e44cd 100644 --- a/chromium/services/media_session/media_session_service_unittest.cc +++ b/chromium/services/media_session/media_session_service_impl_unittest.cc @@ -2,28 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "services/media_session/media_session_service.h" +#include "services/media_session/media_session_service_impl.h" #include "base/macros.h" #include "base/test/task_environment.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" #include "testing/gtest/include/gtest/gtest.h" namespace media_session { -class MediaSessionTest : public testing::Test { +class MediaSessionImplTest : public testing::Test { public: - MediaSessionTest() = default; - ~MediaSessionTest() override = default; + MediaSessionImplTest() = default; + ~MediaSessionImplTest() override = default; private: base::test::TaskEnvironment task_environment_; - DISALLOW_COPY_AND_ASSIGN(MediaSessionTest); + DISALLOW_COPY_AND_ASSIGN(MediaSessionImplTest); }; -TEST_F(MediaSessionTest, InstantiateService) { - MediaSessionService service{mojo::NullReceiver()}; +TEST_F(MediaSessionImplTest, InstantiateService) { + MediaSessionServiceImpl service; } } // namespace media_session diff --git a/chromium/services/media_session/public/cpp/BUILD.gn b/chromium/services/media_session/public/cpp/BUILD.gn index 448f9b86f58..93bdbb714c3 100644 --- a/chromium/services/media_session/public/cpp/BUILD.gn +++ b/chromium/services/media_session/public/cpp/BUILD.gn @@ -44,6 +44,7 @@ component("cpp") { "features.h", "media_image_manager.cc", "media_image_manager.h", + "media_session_service.h", "util.cc", "util.h", ] @@ -52,6 +53,7 @@ component("cpp") { deps = [ "//base", + "//build:chromeos_buildflags", "//services/media_session/public/mojom", "//skia", "//ui/gfx/geometry", diff --git a/chromium/services/media_session/public/cpp/features.cc b/chromium/services/media_session/public/cpp/features.cc index 7fa1bc259dc..ac8a792b5c0 100644 --- a/chromium/services/media_session/public/cpp/features.cc +++ b/chromium/services/media_session/public/cpp/features.cc @@ -5,6 +5,7 @@ #include "services/media_session/public/cpp/features.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" namespace media_session { namespace features { @@ -25,7 +26,7 @@ const base::Feature kMediaSessionService { // have audio focus at any one time. const base::Feature kAudioFocusEnforcement { "AudioFocusEnforcement", -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) base::FEATURE_ENABLED_BY_DEFAULT #else base::FEATURE_DISABLED_BY_DEFAULT @@ -36,7 +37,7 @@ const base::Feature kAudioFocusEnforcement { // share audio focus at the same time provided that they have the same group id. const base::Feature kAudioFocusSessionGrouping { "AudioFocusSessionGrouping", -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) base::FEATURE_ENABLED_BY_DEFAULT #else base::FEATURE_DISABLED_BY_DEFAULT diff --git a/chromium/services/media_session/public/cpp/media_session_service.h b/chromium/services/media_session/public/cpp/media_session_service.h new file mode 100644 index 00000000000..d1ebc60a13f --- /dev/null +++ b/chromium/services/media_session/public/cpp/media_session_service.h @@ -0,0 +1,36 @@ +// 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 SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_SERVICE_H_ +#define SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_SERVICE_H_ + +#include <memory> + +#include "base/component_export.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "services/media_session/public/mojom/audio_focus.mojom.h" +#include "services/media_session/public/mojom/media_controller.mojom.h" + +namespace media_session { + +class AudioFocusManager; + +class COMPONENT_EXPORT(MEDIA_SESSION_CPP) MediaSessionService { + public: + virtual ~MediaSessionService() = default; + + virtual void BindAudioFocusManager( + mojo::PendingReceiver<mojom::AudioFocusManager> receiver) = 0; + virtual void BindAudioFocusManagerDebug( + mojo::PendingReceiver<mojom::AudioFocusManagerDebug> receiver) = 0; + virtual void BindMediaControllerManager( + mojo::PendingReceiver<mojom::MediaControllerManager> receiver) = 0; + + protected: + MediaSessionService() = default; +}; + +} // namespace media_session + +#endif // SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_SERVICE_H_ diff --git a/chromium/services/media_session/public/mojom/BUILD.gn b/chromium/services/media_session/public/mojom/BUILD.gn index 4ee7adcc43e..00f77dd120b 100644 --- a/chromium/services/media_session/public/mojom/BUILD.gn +++ b/chromium/services/media_session/public/mojom/BUILD.gn @@ -11,7 +11,6 @@ mojom("mojom") { "constants.mojom", "media_controller.mojom", "media_session.mojom", - "media_session_service.mojom", ] public_deps = [ diff --git a/chromium/services/media_session/public/mojom/media_session_service.mojom b/chromium/services/media_session/public/mojom/media_session_service.mojom deleted file mode 100644 index 977340211c4..00000000000 --- a/chromium/services/media_session/public/mojom/media_session_service.mojom +++ /dev/null @@ -1,21 +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. - -module media_session.mojom; - -import "services/media_session/public/mojom/audio_focus.mojom"; -import "services/media_session/public/mojom/media_controller.mojom"; - -// The main interface to the Media Session service. Privileged and bound only by -// the browser process. -interface MediaSessionService { - // Binds an AudioFocusManager endpoint in the service. - BindAudioFocusManager(pending_receiver<AudioFocusManager> receiver); - - // Binds an endpoint for debugging the AudioFocusManager. - BindAudioFocusManagerDebug(pending_receiver<AudioFocusManagerDebug> receiver); - - // Binds a MediaControllerManager endpoint in the service. - BindMediaControllerManager(pending_receiver<MediaControllerManager> receiver); -}; diff --git a/chromium/services/metrics/DIR_METADATA b/chromium/services/metrics/DIR_METADATA new file mode 100644 index 00000000000..35d6bbc8c62 --- /dev/null +++ b/chromium/services/metrics/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Metrics" +}
\ No newline at end of file diff --git a/chromium/services/metrics/OWNERS b/chromium/services/metrics/OWNERS index f4be013d37d..979590497b6 100644 --- a/chromium/services/metrics/OWNERS +++ b/chromium/services/metrics/OWNERS @@ -1,5 +1 @@ file://base/metrics/OWNERS - - -# COMPONENT: Internals>Metrics -# TEAM: chromium-dev@chromium.org diff --git a/chromium/services/metrics/public/cpp/BUILD.gn b/chromium/services/metrics/public/cpp/BUILD.gn index 68bfc8ee152..e1ca96d4a2d 100644 --- a/chromium/services/metrics/public/cpp/BUILD.gn +++ b/chromium/services/metrics/public/cpp/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/python.gni") import("//mojo/public/tools/bindings/mojom.gni") component("metrics_cpp") { @@ -56,7 +57,8 @@ source_set("tests") { ] } -action("gen_ukm_builders") { +# TODO(crbug.com/1112471): Get this to run cleanly under Python 3. +python2_action("gen_ukm_builders") { script = "//tools/metrics/ukm/gen_builders.py" # Re-generate the outputs if the codegen code changes: @@ -64,7 +66,6 @@ action("gen_ukm_builders") { "//tools/metrics/ukm/builders_template.py", "//tools/metrics/ukm/decode_template.py", "//tools/metrics/ukm/codegen.py", - "//tools/metrics/ukm/gen_builders.py", ] sources = [ "//tools/metrics/ukm/ukm.xml" ] diff --git a/chromium/services/metrics/public/cpp/ukm_entry_builder_base.cc b/chromium/services/metrics/public/cpp/ukm_entry_builder_base.cc index 75c4e658a0b..0b367ab2b00 100644 --- a/chromium/services/metrics/public/cpp/ukm_entry_builder_base.cc +++ b/chromium/services/metrics/public/cpp/ukm_entry_builder_base.cc @@ -6,6 +6,7 @@ #include <memory> +#include "services/metrics/public/cpp/ukm_source_id.h" #include "services/metrics/public/mojom/ukm_interface.mojom.h" namespace ukm { @@ -19,7 +20,7 @@ UkmEntryBuilderBase::UkmEntryBuilderBase(ukm::SourceId source_id, entry_->event_hash = event_hash; } -UkmEntryBuilderBase::UkmEntryBuilderBase(base::UkmSourceId source_id, +UkmEntryBuilderBase::UkmEntryBuilderBase(ukm::SourceIdObj source_id, uint64_t event_hash) : entry_(mojom::UkmEntry::New()) { entry_->source_id = source_id.ToInt64(); diff --git a/chromium/services/metrics/public/cpp/ukm_entry_builder_base.h b/chromium/services/metrics/public/cpp/ukm_entry_builder_base.h index 81718a826eb..c9afba1c5cf 100644 --- a/chromium/services/metrics/public/cpp/ukm_entry_builder_base.h +++ b/chromium/services/metrics/public/cpp/ukm_entry_builder_base.h @@ -8,9 +8,9 @@ #include <string> #include "base/macros.h" -#include "base/metrics/ukm_source_id.h" #include "services/metrics/public/cpp/metrics_export.h" #include "services/metrics/public/cpp/ukm_recorder.h" +#include "services/metrics/public/cpp/ukm_source_id.h" #include "services/metrics/public/mojom/ukm_interface.mojom.h" namespace ukm { @@ -32,7 +32,7 @@ class METRICS_EXPORT UkmEntryBuilderBase { mojom::UkmEntryPtr TakeEntry(); protected: - UkmEntryBuilderBase(base::UkmSourceId source_id, uint64_t event_hash); + UkmEntryBuilderBase(ukm::SourceIdObj source_id, uint64_t event_hash); // TODO(crbug/873866): Remove this version once callers are migrated. UkmEntryBuilderBase(SourceId source_id, uint64_t event_hash); diff --git a/chromium/services/metrics/public/cpp/ukm_recorder.cc b/chromium/services/metrics/public/cpp/ukm_recorder.cc index 785df3db930..7e7b8247125 100644 --- a/chromium/services/metrics/public/cpp/ukm_recorder.cc +++ b/chromium/services/metrics/public/cpp/ukm_recorder.cc @@ -9,6 +9,7 @@ #include "build/build_config.h" #include "services/metrics/public/cpp/delegating_ukm_recorder.h" #include "services/metrics/public/cpp/ukm_entry_builder.h" +#include "services/metrics/public/cpp/ukm_source_id.h" namespace ukm { @@ -34,7 +35,7 @@ ukm::SourceId UkmRecorder::GetNewSourceID() { // static ukm::SourceId UkmRecorder::GetSourceIdForPaymentAppFromScope( const GURL& service_worker_scope) { - ukm::SourceId source_id = base::UkmSourceId::FromOtherId( + ukm::SourceId source_id = ukm::SourceIdObj::FromOtherId( GetNewSourceID(), SourceIdType::PAYMENT_APP_ID) .ToInt64(); ukm::UkmRecorder::Get()->UpdateSourceURL(source_id, service_worker_scope); @@ -45,7 +46,7 @@ ukm::SourceId UkmRecorder::GetSourceIdForPaymentAppFromScope( ukm::SourceId UkmRecorder::GetSourceIdForWebApkManifestUrl( const GURL& manifest_url) { ukm::SourceId source_id = - base::UkmSourceId::FromOtherId(GetNewSourceID(), SourceIdType::WEBAPK_ID) + ukm::SourceIdObj::FromOtherId(GetNewSourceID(), SourceIdType::WEBAPK_ID) .ToInt64(); ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get(); ukm_recorder->UpdateSourceURL(source_id, manifest_url); @@ -56,19 +57,19 @@ ukm::SourceId UkmRecorder::GetSourceIdForWebApkManifestUrl( ukm::SourceId UkmRecorder::GetSourceIdForDesktopWebAppStartUrl( const GURL& start_url) { ukm::SourceId source_id = - base::UkmSourceId::FromOtherId(GetNewSourceID(), - SourceIdType::DESKTOP_WEB_APP_ID) + ukm::SourceIdObj::FromOtherId(GetNewSourceID(), + SourceIdType::DESKTOP_WEB_APP_ID) .ToInt64(); ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get(); ukm_recorder->UpdateSourceURL(source_id, start_url); return source_id; } -void UkmRecorder::RecordOtherURL(base::UkmSourceId source_id, const GURL& url) { +void UkmRecorder::RecordOtherURL(ukm::SourceIdObj source_id, const GURL& url) { UpdateSourceURL(source_id.ToInt64(), url); } -void UkmRecorder::RecordAppURL(base::UkmSourceId source_id, +void UkmRecorder::RecordAppURL(ukm::SourceIdObj source_id, const GURL& url, const AppType app_type) { UpdateAppURL(source_id.ToInt64(), url, app_type); diff --git a/chromium/services/metrics/public/cpp/ukm_recorder.h b/chromium/services/metrics/public/cpp/ukm_recorder.h index 7e2ec0aee87..b37b92f4d8d 100644 --- a/chromium/services/metrics/public/cpp/ukm_recorder.h +++ b/chromium/services/metrics/public/cpp/ukm_recorder.h @@ -33,6 +33,10 @@ namespace web_app { class DesktopWebAppUkmRecorder; } +namespace weblayer { +class BackgroundSyncDelegateImpl; +} + namespace ukm { class DelegatingUkmRecorder; @@ -76,8 +80,8 @@ class METRICS_EXPORT UkmRecorder { protected: // Type-safe wrappers for Update<X> functions. - void RecordOtherURL(base::UkmSourceId source_id, const GURL& url); - void RecordAppURL(base::UkmSourceId source_id, + void RecordOtherURL(ukm::SourceIdObj source_id, const GURL& url); + void RecordAppURL(ukm::SourceIdObj source_id, const GURL& url, const AppType app_type); @@ -96,6 +100,7 @@ class METRICS_EXPORT UkmRecorder { const GURL& service_worker_scope); private: + friend weblayer::BackgroundSyncDelegateImpl; friend DelegatingUkmRecorder; friend TestRecordingHelper; friend UkmBackgroundRecorderService; diff --git a/chromium/services/metrics/public/cpp/ukm_source_id.cc b/chromium/services/metrics/public/cpp/ukm_source_id.cc index db7046aaa4c..25118ed9a9e 100644 --- a/chromium/services/metrics/public/cpp/ukm_source_id.cc +++ b/chromium/services/metrics/public/cpp/ukm_source_id.cc @@ -4,14 +4,67 @@ #include "services/metrics/public/cpp/ukm_source_id.h" +#include <cmath> + #include "base/atomic_sequence_num.h" #include "base/check.h" +#include "base/check_op.h" #include "base/rand_util.h" namespace ukm { +namespace { + +const int64_t kLowBitsMask = (INT64_C(1) << 32) - 1; + +int64_t GetNumTypeBits() { + return std::ceil( + std::log2(static_cast<int64_t>(SourceIdObj::Type::kMaxValue) + 1)); +} + +} // namespace + +// static +SourceIdObj SourceIdObj::New() { + // Generate some bits which are unique to this process, so we can generate + // IDs independently in different processes. IDs generated by this method may + // collide, but it should be sufficiently rare enough to not impact data + // quality. + const static int64_t process_id_bits = + static_cast<int64_t>(base::RandUint64()) & ~kLowBitsMask; + // Generate some bits which are unique within the process, using a counter. + static base::AtomicSequenceNumber seq; + SourceIdObj local_id = + FromOtherId(seq.GetNext() + 1, SourceIdObj::Type::DEFAULT); + // Combine the local and process bits to generate a unique ID. + return SourceIdObj((local_id.value_ & kLowBitsMask) | process_id_bits); +} + +// static +SourceIdObj SourceIdObj::FromOtherId(int64_t other_id, SourceIdObj::Type type) { + // Note on syntax: std::ceil and std::log2 are not constexpr functions thus + // these variables cannot be initialized statically in the global scope above. + // Function static initialization here is thread safe; so they are initialized + // at most once. + static const int64_t kNumTypeBits = GetNumTypeBits(); + static const int64_t kTypeMask = (INT64_C(1) << kNumTypeBits) - 1; + + const int64_t type_bits = static_cast<int64_t>(type); + DCHECK_EQ(type_bits, type_bits & kTypeMask); + // Stores the type of the source ID in its lower bits, and shift the rest of + // the ID to make room. This could cause the original ID to overflow, but + // that should be rare enough that it won't matter for UKM's purposes. + return SourceIdObj((other_id << kNumTypeBits) | type_bits); +} + +SourceIdObj::Type SourceIdObj::GetType() const { + static const int64_t kNumTypeBits = GetNumTypeBits(); + static const int64_t kTypeMask = (INT64_C(1) << kNumTypeBits) - 1; + return static_cast<SourceIdObj::Type>(value_ & kTypeMask); +} + SourceId AssignNewSourceId() { - return base::UkmSourceId::New().ToInt64(); + return ukm::SourceIdObj::New().ToInt64(); } SourceId ConvertToSourceId(int64_t other_id, SourceIdType id_type) { @@ -19,14 +72,14 @@ SourceId ConvertToSourceId(int64_t other_id, SourceIdType id_type) { // Payment apps should use |UkmRecorder::GetSourceIdForWebApkManifestUrl()| // and |UkmRecorder::GetSourceIdForPaymentAppFromScope()| instead. // TODO(crbug.com/1046964): Ideally we should restrict - // UkmSourceId::FromOtherId() as well. + // SourceIdObj::FromOtherId() as well. DCHECK(id_type != SourceIdType::WEBAPK_ID); DCHECK(id_type != SourceIdType::PAYMENT_APP_ID); - return base::UkmSourceId::FromOtherId(other_id, id_type).ToInt64(); + return ukm::SourceIdObj::FromOtherId(other_id, id_type).ToInt64(); } SourceIdType GetSourceIdType(SourceId source_id) { - return base::UkmSourceId::FromInt64(source_id).GetType(); + return ukm::SourceIdObj::FromInt64(source_id).GetType(); } } // namespace ukm diff --git a/chromium/services/metrics/public/cpp/ukm_source_id.h b/chromium/services/metrics/public/cpp/ukm_source_id.h index 098b9086c84..fcea73eb188 100644 --- a/chromium/services/metrics/public/cpp/ukm_source_id.h +++ b/chromium/services/metrics/public/cpp/ukm_source_id.h @@ -7,17 +7,111 @@ #include <stdint.h> -#include "base/metrics/ukm_source_id.h" #include "services/metrics/public/cpp/metrics_export.h" namespace ukm { typedef int64_t SourceId; -using SourceIdType = base::UkmSourceId::Type; - const SourceId kInvalidSourceId = 0; +// An ID used to identify a Source to UKM, and contains the type information. +// These objects are copyable, assignable, and occupy 64-bits per instance. +// Prefer passing them by value. When a new type is added, please also update +// the enum type in third_party/metrics_proto/ukm/source.proto and the +// conversion function ToProtobufSourceType. +// NOTES ON USAGE: if only the underlying int value is required to identify a +// Source and is used in Mojo interface, and no type conversion needs to be +// performed, use ukm::SourceId instead. +// TODO(crbug/1046951): migrate callers to use the public methods below then +// remove METRICS_EXPORT on this class. +class METRICS_EXPORT SourceIdObj { + public: + enum class Type : SourceId { + // Source ids of this type are created via ukm::AssignNewSourceId, to denote + // 'custom' source other than the types below. Source of this type has + // additional restrictions with logging, as determined by + // IsWhitelistedSourceId. + DEFAULT = 0, + // Sources created by navigation. They will be kept in memory as long as + // the associated tab is still alive and the number of sources are within + // the max threshold. + NAVIGATION_ID = 1, + // Source ID used by AppLaunchEventLogger::Log. A new source of this type + // and associated events are expected to be recorded within the same report + // interval; it will not be kept in memory between different reports. + APP_ID = 2, + // Source ID for background events that don't have an open tab but the + // associated URL is still present in the browsing history. A new source of + // this type and associated events are expected to be recorded within the + // same report interval; it will not be kept in memory between different + // reports. + HISTORY_ID = 3, + // Source ID used by WebApkUkmRecorder. A new source of this type and + // associated events are expected to be recorded within the same report + // interval; it will not be kept in memory between different reports. + WEBAPK_ID = 4, + // Source ID for service worker based payment handlers. A new source of this + // type and associated events are expected to be recorded within the same + // report interval; it will not be kept in memory between different reports. + PAYMENT_APP_ID = 5, + // Source ID for desktop web apps, based on the start_url in the web app + // manifest. A new source of this type and associated events are expected to + // be recorded within the same report interval; it will not be kept in + // memory between different reports. + DESKTOP_WEB_APP_ID = 6, + // Source ID for web workers, namely SharedWorkers and ServiceWorkers. Web + // workers may inherit a source ID from the spawner context (in the case of + // dedicated workers), or may have their own source IDs (in the case of + // shared workers and service workers). Shared workers and service workers + // can be connected to multiple clients (e.g. documents or other workers). + WORKER_ID = 7, + kMaxValue = WORKER_ID, + }; + + // Default constructor has the invalid value. + constexpr SourceIdObj() : value_(kInvalidSourceId) {} + + constexpr SourceIdObj& operator=(SourceIdObj other) { + value_ = other.value_; + return *this; + } + + // Allow identity comparisons. + constexpr bool operator==(SourceIdObj other) const { + return value_ == other.value_; + } + constexpr bool operator!=(SourceIdObj other) const { + return value_ != other.value_; + } + + // Extract the Type of the SourceId. + Type GetType() const; + + // Return the ID as an int64. + constexpr int64_t ToInt64() const { return value_; } + + // Convert an int64 ID value to an ID object. + static constexpr SourceIdObj FromInt64(int64_t internal_value) { + return SourceIdObj(internal_value); + } + + // Get a new Default-type SourceId, which is unique within the scope of a + // browser session. + static SourceIdObj New(); + + // Utility for converting other unique ids to source ids. + static SourceIdObj FromOtherId(int64_t value, Type type); + + private: + constexpr explicit SourceIdObj(int64_t value) : value_(value) {} + int64_t value_; +}; + +constexpr SourceIdObj kInvalidSourceIdObj = SourceIdObj(); + +using SourceIdType = ukm::SourceIdObj::Type; + // Get a new source ID, which is unique for the duration of a browser session. METRICS_EXPORT SourceId AssignNewSourceId(); @@ -25,7 +119,7 @@ METRICS_EXPORT SourceId AssignNewSourceId(); METRICS_EXPORT SourceId ConvertToSourceId(int64_t other_id, SourceIdType id_type); -// Get the SourceIdType of the SourceId. +// Get the SourceIdType of the SourceId object. METRICS_EXPORT SourceIdType GetSourceIdType(SourceId source_id); } // namespace ukm diff --git a/chromium/services/metrics/ukm_api.md b/chromium/services/metrics/ukm_api.md index 1d44d5963ca..9dce7d6e5a2 100644 --- a/chromium/services/metrics/ukm_api.md +++ b/chromium/services/metrics/ukm_api.md @@ -184,7 +184,9 @@ ukm::builders::MyEvent(source_id) UKM identifies navigations by their source ID and you'll need to associate an ID with your event in order to tie it to a main frame URL. Preferably, get an existing ID for the navigation from another object. -The main method for doing this is by getting a navigation ID: +Prefer using `ukm::SourceId` if only the underlying int64 value is required to identify a source and is used in Mojo interface, and no type conversion needs to be performed. If additional source type information is needed, `ukm::SourceIdObj` can be used. + +The main method for getting an existing ID is by converting from the navigation ID: ```cpp ukm::SourceId source_id = GetSourceIdForWebContentsDocument(web_contents); diff --git a/chromium/services/network/BUILD.gn b/chromium/services/network/BUILD.gn index 294695ec053..78d70dcf06f 100644 --- a/chromium/services/network/BUILD.gn +++ b/chromium/services/network/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//mojo/public/tools/bindings/mojom.gni") import("//net/features.gni") import("//services/network/public/cpp/features.gni") @@ -200,7 +201,7 @@ component("network_service") { ] } - if (is_chromeos) { + if (is_ash) { sources += [ "cert_verifier_with_trust_anchors.cc", "cert_verifier_with_trust_anchors.h", @@ -223,6 +224,7 @@ component("network_service") { deps = [ "//base", "//build:chromecast_buildflags", + "//build:chromeos_buildflags", "//components/content_settings/core/common", "//components/cookie_config", "//components/domain_reliability", @@ -364,7 +366,7 @@ source_set("tests") { ] } - if (is_chromeos) { + if (is_ash) { sources += [ "cert_verifier_with_trust_anchors_unittest.cc", "dhcp_pac_file_fetcher_mojo_unittest.cc", @@ -376,6 +378,7 @@ source_set("tests") { ":network_service", ":test_support", "//base", + "//build:chromeos_buildflags", "//components/network_session_configurator/browser", "//components/prefs:test_support", "//components/variations:test_support", @@ -453,7 +456,7 @@ source_set("test_support") { "test/udp_socket_test_util.h", ] - if (is_chromeos) { + if (is_ash) { sources += [ "mock_mojo_dhcp_wpad_url_client.cc", "mock_mojo_dhcp_wpad_url_client.h", @@ -469,6 +472,7 @@ source_set("test_support") { deps = [ "//base", + "//build:chromeos_buildflags", "//mojo/public/cpp/bindings", "//net", "//net:test_support", diff --git a/chromium/services/network/DIR_METADATA b/chromium/services/network/DIR_METADATA new file mode 100644 index 00000000000..1fd3fb96519 --- /dev/null +++ b/chromium/services/network/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Services>Network" +}
\ No newline at end of file diff --git a/chromium/services/network/OWNERS b/chromium/services/network/OWNERS index 42433e48786..39840e67834 100644 --- a/chromium/services/network/OWNERS +++ b/chromium/services/network/OWNERS @@ -39,5 +39,3 @@ per-file BUILD.gn=file://services/network/resource_scheduler/OWNERS # Content Security Policy per-file content_security_policy*=lfg@chromium.org per-file content_security_policy*=nasko@chromium.org - -# COMPONENT: Internals>Services>Network diff --git a/chromium/services/network/cert_verifier_with_trust_anchors_unittest.cc b/chromium/services/network/cert_verifier_with_trust_anchors_unittest.cc index 26acf6497ff..fca9e0adbc8 100644 --- a/chromium/services/network/cert_verifier_with_trust_anchors_unittest.cc +++ b/chromium/services/network/cert_verifier_with_trust_anchors_unittest.cc @@ -9,8 +9,8 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" #include "base/callback.h" +#include "base/callback_helpers.h" #include "base/memory/ref_counted.h" #include "base/run_loop.h" #include "base/test/task_environment.h" diff --git a/chromium/services/network/cookie_access_delegate_impl.cc b/chromium/services/network/cookie_access_delegate_impl.cc index b9900b84d19..44478b2abe6 100644 --- a/chromium/services/network/cookie_access_delegate_impl.cc +++ b/chromium/services/network/cookie_access_delegate_impl.cc @@ -5,13 +5,16 @@ #include "services/network/cookie_access_delegate_impl.h" #include "net/cookies/cookie_util.h" +#include "services/network/first_party_sets/preloaded_first_party_sets.h" namespace network { CookieAccessDelegateImpl::CookieAccessDelegateImpl( mojom::CookieAccessDelegateType type, + const PreloadedFirstPartySets* preloaded_first_party_sets, const CookieSettings* cookie_settings) : type_(type), cookie_settings_(cookie_settings) { + // TODO(crbug.com/1143756): Save and use the PreloadedFirstPartySets. if (type == mojom::CookieAccessDelegateType::USE_CONTENT_SETTINGS) { DCHECK(cookie_settings); } diff --git a/chromium/services/network/cookie_access_delegate_impl.h b/chromium/services/network/cookie_access_delegate_impl.h index 88a2bc99898..c5eb00aa829 100644 --- a/chromium/services/network/cookie_access_delegate_impl.h +++ b/chromium/services/network/cookie_access_delegate_impl.h @@ -13,6 +13,8 @@ namespace network { +class PreloadedFirstPartySets; + // This class acts as a delegate for the CookieStore to query the // CookieManager's CookieSettings for instructions on how to handle a given // cookie with respect to SameSite. @@ -22,9 +24,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CookieAccessDelegateImpl // If |type| is USE_CONTENT_SETTINGS, a non-null |cookie_settings| is // expected. |cookie_settings| contains the set of content settings that // describes which cookies should be subject to legacy access rules. - // If non-null, |cookie_settings| is expected to outlive this class. - CookieAccessDelegateImpl(mojom::CookieAccessDelegateType type, - const CookieSettings* cookie_settings = nullptr); + // If non-null, |cookie_settings| is expected to outlive this class. If + // non-null, `preloaded_first_party_sets` must outlive `this`. + CookieAccessDelegateImpl( + mojom::CookieAccessDelegateType type, + const PreloadedFirstPartySets* preloaded_first_party_sets, + const CookieSettings* cookie_settings = nullptr); ~CookieAccessDelegateImpl() override; diff --git a/chromium/services/network/cookie_manager.cc b/chromium/services/network/cookie_manager.cc index 1d988375b00..526ccf16da8 100644 --- a/chromium/services/network/cookie_manager.cc +++ b/chromium/services/network/cookie_manager.cc @@ -7,7 +7,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/process/process.h" #include "build/build_config.h" #include "components/content_settings/core/common/content_settings_pattern.h" @@ -18,6 +18,7 @@ #include "net/cookies/cookie_options.h" #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_util.h" +#include "net/url_request/url_request_context.h" #include "services/network/cookie_access_delegate_impl.h" #include "services/network/session_cleanup_cookie_store.h" #include "url/gurl.h" @@ -43,10 +44,11 @@ void CookieManager::ListenerRegistration::DispatchCookieStoreChange( } CookieManager::CookieManager( - net::CookieStore* cookie_store, + net::URLRequestContext* url_request_context, + const PreloadedFirstPartySets* preloaded_first_party_sets, scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store, mojom::CookieManagerParamsPtr params) - : cookie_store_(cookie_store), + : cookie_store_(url_request_context->cookie_store()), session_cleanup_cookie_store_(std::move(session_cleanup_cookie_store)) { mojom::CookieAccessDelegateType cookie_access_delegate_type = mojom::CookieAccessDelegateType::USE_CONTENT_SETTINGS; @@ -59,6 +61,7 @@ CookieManager::CookieManager( } cookie_store_->SetCookieAccessDelegate( std::make_unique<CookieAccessDelegateImpl>(cookie_access_delegate_type, + preloaded_first_party_sets, &cookie_settings_)); } diff --git a/chromium/services/network/cookie_manager.h b/chromium/services/network/cookie_manager.h index fa13e34067b..bffe9beb9a5 100644 --- a/chromium/services/network/cookie_manager.h +++ b/chromium/services/network/cookie_manager.h @@ -21,11 +21,13 @@ namespace net { class CookieStore; -} +class URLRequestContext; +} // namespace net class GURL; namespace network { +class PreloadedFirstPartySets; class SessionCleanupCookieStore; // Wrap a cookie store in an implementation of the mojo cookie interface. @@ -33,9 +35,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CookieManager : public mojom::CookieManager { public: // Construct a CookieService that can serve mojo requests for the underlying - // cookie store. |*cookie_store| must outlive this object. + // cookie store. |url_request_context->cookie_store()| must outlive this + // object. `*preloaded_first_party_sets` must outlive + // `url_request_context->cookie_store()`. CookieManager( - net::CookieStore* cookie_store, + net::URLRequestContext* url_request_context, + const PreloadedFirstPartySets* preloaded_first_party_sets, scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store, mojom::CookieManagerParamsPtr params); diff --git a/chromium/services/network/cookie_manager_unittest.cc b/chromium/services/network/cookie_manager_unittest.cc index 671c169a780..86e98597a3e 100644 --- a/chromium/services/network/cookie_manager_unittest.cc +++ b/chromium/services/network/cookie_manager_unittest.cc @@ -14,7 +14,7 @@ #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/task/thread_pool/thread_pool_instance.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/time/time.h" #include "net/cookies/cookie_access_result.h" @@ -26,6 +26,7 @@ #include "net/cookies/cookie_store_test_helpers.h" #include "net/cookies/cookie_util.h" #include "net/cookies/test_cookie_access_delegate.h" +#include "net/url_request/url_request_context.h" #include "services/network/public/mojom/cookie_manager.mojom.h" #include "services/network/session_cleanup_cookie_store.h" #include "testing/gmock/include/gmock/gmock.h" @@ -243,7 +244,6 @@ class SynchronousCookieManager { // No need to wrap Add*Listener and CloneInterface, since their use // is purely async. private: - mojom::CookieManager* cookie_service_; uint32_t callback_counter_; @@ -340,8 +340,11 @@ class CookieManagerTest : public testing::Test { connection_error_seen_ = false; cookie_monster_ = std::make_unique<net::CookieMonster>( std::move(store), nullptr /* netlog */); + url_request_context_ = std::make_unique<net::URLRequestContext>(); + url_request_context_->set_cookie_store(cookie_monster_.get()); cookie_service_ = std::make_unique<CookieManager>( - cookie_monster_.get(), std::move(cleanup_store), nullptr); + url_request_context_.get(), nullptr /* preloaded_first_party_sets */, + std::move(cleanup_store), nullptr); cookie_service_->AddReceiver( cookie_service_remote_.BindNewPipeAndPassReceiver()); service_wrapper_ = std::make_unique<SynchronousCookieManager>( @@ -359,6 +362,7 @@ class CookieManagerTest : public testing::Test { bool connection_error_seen_; std::unique_ptr<net::CookieMonster> cookie_monster_; + std::unique_ptr<net::URLRequestContext> url_request_context_; std::unique_ptr<CookieManager> cookie_service_; mojo::Remote<mojom::CookieManager> cookie_service_remote_; std::unique_ptr<SynchronousCookieManager> service_wrapper_; @@ -382,27 +386,34 @@ TEST_F(CookieManagerTest, GetAllCookies) { base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("C", "D", "foo_host2", "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie( "Secure", "E", kCookieDomain, "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("HttpOnly", "F", kCookieDomain, "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/true, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), + "https", true)); + EXPECT_TRUE(SetCanonicalCookie( + net::CanonicalCookie("SecureSameParty", "G", kCookieDomain, "/with/path", + base::Time(), base::Time(), base::Time(), + /*secure=*/true, + /*httponly=*/false, net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/true), "https", true)); base::Time after_creation(base::Time::Now()); @@ -410,7 +421,7 @@ TEST_F(CookieManagerTest, GetAllCookies) { std::vector<net::CanonicalCookie> cookies = service_wrapper()->GetAllCookies(); - ASSERT_EQ(4u, cookies.size()); + ASSERT_EQ(5u, cookies.size()); std::sort(cookies.begin(), cookies.end(), &CompareCanonicalCookies); EXPECT_EQ("A", cookies[0].Name()); @@ -426,6 +437,7 @@ TEST_F(CookieManagerTest, GetAllCookies) { EXPECT_FALSE(cookies[0].IsHttpOnly()); EXPECT_EQ(net::CookieSameSite::LAX_MODE, cookies[0].SameSite()); EXPECT_EQ(net::COOKIE_PRIORITY_MEDIUM, cookies[0].Priority()); + EXPECT_FALSE(cookies[0].IsSameParty()); EXPECT_EQ("C", cookies[1].Name()); EXPECT_EQ("D", cookies[1].Value()); @@ -440,6 +452,7 @@ TEST_F(CookieManagerTest, GetAllCookies) { EXPECT_FALSE(cookies[1].IsHttpOnly()); EXPECT_EQ(net::CookieSameSite::LAX_MODE, cookies[1].SameSite()); EXPECT_EQ(net::COOKIE_PRIORITY_MEDIUM, cookies[1].Priority()); + EXPECT_FALSE(cookies[1].IsSameParty()); EXPECT_EQ("HttpOnly", cookies[2].Name()); EXPECT_EQ("F", cookies[2].Value()); @@ -454,6 +467,7 @@ TEST_F(CookieManagerTest, GetAllCookies) { EXPECT_TRUE(cookies[2].IsHttpOnly()); EXPECT_EQ(net::CookieSameSite::LAX_MODE, cookies[2].SameSite()); EXPECT_EQ(net::COOKIE_PRIORITY_MEDIUM, cookies[2].Priority()); + EXPECT_FALSE(cookies[2].IsSameParty()); EXPECT_EQ("Secure", cookies[3].Name()); EXPECT_EQ("E", cookies[3].Value()); @@ -468,6 +482,22 @@ TEST_F(CookieManagerTest, GetAllCookies) { EXPECT_FALSE(cookies[3].IsHttpOnly()); EXPECT_EQ(net::CookieSameSite::NO_RESTRICTION, cookies[3].SameSite()); EXPECT_EQ(net::COOKIE_PRIORITY_MEDIUM, cookies[3].Priority()); + EXPECT_FALSE(cookies[3].IsSameParty()); + + EXPECT_EQ("SecureSameParty", cookies[4].Name()); + EXPECT_EQ("G", cookies[4].Value()); + EXPECT_EQ(kCookieDomain, cookies[4].Domain()); + EXPECT_EQ("/with/path", cookies[4].Path()); + EXPECT_LT(before_creation, cookies[4].CreationDate()); + EXPECT_LE(cookies[4].CreationDate(), after_creation); + EXPECT_EQ(cookies[4].LastAccessDate(), base::Time()); + EXPECT_EQ(cookies[4].ExpiryDate(), base::Time()); + EXPECT_FALSE(cookies[4].IsPersistent()); + EXPECT_TRUE(cookies[4].IsSecure()); + EXPECT_FALSE(cookies[4].IsHttpOnly()); + EXPECT_EQ(net::CookieSameSite::LAX_MODE, cookies[4].SameSite()); + EXPECT_EQ(net::COOKIE_PRIORITY_MEDIUM, cookies[4].Priority()); + EXPECT_TRUE(cookies[4].IsSameParty()); } TEST_F(CookieManagerTest, GetAllCookiesWithAccessSemantics) { @@ -495,14 +525,15 @@ TEST_F(CookieManagerTest, GetAllCookiesWithAccessSemantics) { base::Time(), base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // LEGACY EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "C", "D", "domain2.test", "/with/longer/path", base::Time(), - base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, - net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("C", "D", "domain2.test", "/with/longer/path", + base::Time(), base::Time(), base::Time(), + /*secure=*/true, /*httponly=*/false, + net::CookieSameSite::NO_RESTRICTION, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // not set (UNKNOWN) EXPECT_TRUE(SetCanonicalCookie( @@ -510,7 +541,7 @@ TEST_F(CookieManagerTest, GetAllCookiesWithAccessSemantics) { "HttpOnly", "F", "domain3.test", "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/true, /*httponly=*/true, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // NONLEGACY EXPECT_TRUE(SetCanonicalCookie( @@ -518,7 +549,7 @@ TEST_F(CookieManagerTest, GetAllCookiesWithAccessSemantics) { "Secure", "E", ".domainwithdot.test", "/", base::Time(), base::Time(), base::Time(), /*secure=*/true, /*httponly=*/true, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); std::vector<net::CookieAccessSemantics> access_semantics_list; @@ -546,27 +577,27 @@ TEST_F(CookieManagerTest, GetCookieList) { base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("C", "D", "foo_host2", "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("Secure", "E", kCookieDomain, "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("HttpOnly", "F", kCookieDomain, "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/true, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // Want the SameSite=lax cookies, but not httponly ones. @@ -608,7 +639,7 @@ TEST_F(CookieManagerTest, GetCookieListHttpOnly) { base::Time(), base::Time(), /*secure=*/false, /*httponly=*/true, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); ASSERT_TRUE(result); result = SetCanonicalCookie( @@ -616,7 +647,7 @@ TEST_F(CookieManagerTest, GetCookieListHttpOnly) { base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); ASSERT_TRUE(result); @@ -658,21 +689,21 @@ TEST_F(CookieManagerTest, GetCookieListSameSite) { base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); ASSERT_TRUE(result); result = SetCanonicalCookie( net::CanonicalCookie("C", "D", kCookieDomain, "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); ASSERT_TRUE(result); result = SetCanonicalCookie( net::CanonicalCookie("E", "F", kCookieDomain, "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::STRICT_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); ASSERT_TRUE(result); @@ -732,7 +763,7 @@ TEST_F(CookieManagerTest, GetCookieListAccessTime) { base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); ASSERT_TRUE(result); @@ -767,7 +798,7 @@ TEST_F(CookieManagerTest, DeleteCanonicalCookie) { net::CanonicalCookie( "A", "B", "foo_host", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); std::vector<net::CanonicalCookie> cookies = service_wrapper()->GetAllCookies(); @@ -783,27 +814,27 @@ TEST_F(CookieManagerTest, DeleteThroughSet) { base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("C", "D", "foo_host2", "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("Secure", "E", kCookieDomain, "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("HttpOnly", "F", kCookieDomain, "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/true, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); base::Time yesterday = base::Time::Now() - base::TimeDelta::FromDays(1); @@ -811,7 +842,7 @@ TEST_F(CookieManagerTest, DeleteThroughSet) { net::CanonicalCookie( "A", "E", kCookieDomain, "/", base::Time(), yesterday, base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "http", false)); std::vector<net::CanonicalCookie> cookies = @@ -837,7 +868,8 @@ TEST_F(CookieManagerTest, ConfirmSecureSetFails) { base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, + /*same_party=*/false), "http", false); EXPECT_TRUE(access_result.status.HasExactlyExclusionReasonsForTesting( @@ -857,7 +889,8 @@ TEST_F(CookieManagerTest, ConfirmHttpOnlySetFails) { base::Time(), base::Time(), /*secure=*/false, /*httponly=*/true, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, + /*same_party=*/false), "http", false); EXPECT_TRUE(access_result.status.HasExactlyExclusionReasonsForTesting( @@ -876,7 +909,7 @@ TEST_F(CookieManagerTest, ConfirmSecureOverwriteFails) { base::Time(), base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); net::CookieAccessResult access_result = @@ -885,7 +918,7 @@ TEST_F(CookieManagerTest, ConfirmSecureOverwriteFails) { "Secure", "Nope", kCookieDomain, "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "http", false); EXPECT_TRUE(access_result.status.HasExactlyExclusionReasonsForTesting( @@ -907,7 +940,7 @@ TEST_F(CookieManagerTest, ConfirmHttpOnlyOverwriteFails) { base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/true, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "http", true)); net::CookieAccessResult access_result = @@ -916,7 +949,7 @@ TEST_F(CookieManagerTest, ConfirmHttpOnlyOverwriteFails) { "HttpOnly", "Nope", kCookieDomain, "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", false); EXPECT_TRUE(access_result.status.HasExactlyExclusionReasonsForTesting( @@ -939,27 +972,27 @@ TEST_F(CookieManagerTest, DeleteEverything) { base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("C", "D", "foo_host2", "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie( "Secure", "E", kCookieDomain, "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("HttpOnly", "F", kCookieDomain, "/with/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/true, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); mojom::CookieDeletionFilter filter; @@ -979,7 +1012,7 @@ TEST_F(CookieManagerTest, DeleteByTime) { now - base::TimeDelta::FromMinutes(60), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( @@ -987,7 +1020,7 @@ TEST_F(CookieManagerTest, DeleteByTime) { "A2", "val", kCookieDomain, "/", now - base::TimeDelta::FromMinutes(120), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( @@ -995,7 +1028,7 @@ TEST_F(CookieManagerTest, DeleteByTime) { "A3", "val", kCookieDomain, "/", now - base::TimeDelta::FromMinutes(180), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); mojom::CookieDeletionFilter filter; @@ -1016,21 +1049,21 @@ TEST_F(CookieManagerTest, DeleteByExcludingDomains) { net::CanonicalCookie("A1", "val", "foo_host1", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A2", "val", "foo_host2", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A3", "val", "foo_host3", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); mojom::CookieDeletionFilter filter; @@ -1049,21 +1082,21 @@ TEST_F(CookieManagerTest, DeleteByIncludingDomains) { net::CanonicalCookie("A1", "val", "foo_host1", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A2", "val", "foo_host2", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A3", "val", "foo_host3", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); mojom::CookieDeletionFilter filter; @@ -1084,19 +1117,19 @@ TEST_F(CookieManagerTest, DeleteDetails_eTLD) { net::CanonicalCookie("A1", "val", "example.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A2", "val", "www.example.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A3", "val", "www.nonexample.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); mojom::CookieDeletionFilter filter; @@ -1115,19 +1148,20 @@ TEST_F(CookieManagerTest, DeleteDetails_eTLD) { net::CanonicalCookie("A1", "val", "example.co.uk", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A2", "val", "www.example.co.uk", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A3", "val", "www.nonexample.co.uk", "/", base::Time(), base::Time(), - base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A3", "val", "www.nonexample.co.uk", "/", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); filter.including_domains = std::vector<std::string>(); filter.including_domains->push_back("example.co.uk"); @@ -1144,19 +1178,20 @@ TEST_F(CookieManagerTest, DeleteDetails_eTLD) { net::CanonicalCookie("A1", "val", "example.co.uk", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A2", "val", "www.example.co.uk", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A3", "val", "www.nonexample.co.uk", "/", base::Time(), base::Time(), - base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A3", "val", "www.nonexample.co.uk", "/", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); filter.including_domains = std::vector<std::string>(); filter.including_domains->push_back("co.uk"); @@ -1177,25 +1212,25 @@ TEST_F(CookieManagerTest, DeleteDetails_HostDomain) { net::CanonicalCookie("A1", "val", "foo_host.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A2", "val", ".foo_host.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A3", "val", "bar.host.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A4", "val", ".bar.host.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); mojom::CookieDeletionFilter filter; @@ -1215,31 +1250,32 @@ TEST_F(CookieManagerTest, DeleteDetails_eTLDvsPrivateRegistry) { net::CanonicalCookie("A1", "val", "random.co.uk", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A2", "val", "sub.domain.random.co.uk", "/", base::Time(), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A2", "val", "sub.domain.random.co.uk", "/", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A3", "val", "random.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie( "A4", "val", "random", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A5", "val", "normal.co.uk", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); mojom::CookieDeletionFilter filter; @@ -1260,7 +1296,7 @@ TEST_F(CookieManagerTest, DeleteDetails_PrivateRegistry) { net::CanonicalCookie("A1", "val", "privatedomain", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( @@ -1269,7 +1305,8 @@ TEST_F(CookieManagerTest, DeleteDetails_PrivateRegistry) { // .com. "A2", "val", "privatedomain.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM, + /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( @@ -1278,7 +1315,8 @@ TEST_F(CookieManagerTest, DeleteDetails_PrivateRegistry) { // level "A3", "val", "subdomain.privatedomain", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM, + /*same_party=*/false), "https", true)); mojom::CookieDeletionFilter filter; @@ -1309,30 +1347,34 @@ TEST_F(CookieManagerTest, DeleteDetails_IgnoredFields) { // Value EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A01", "RandomValue", "example.com", "/", base::Time(), base::Time(), - base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A01", "RandomValue", "example.com", "/", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A02", "RandomValue", "canonical.com", "/", base::Time(), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A02", "RandomValue", "canonical.com", "/", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // Path EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A03", "val", "example.com", "/this/is/a/long/path", base::Time(), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A03", "val", "example.com", "/this/is/a/long/path", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A04", "val", "canonical.com", "/this/is/a/long/path", base::Time(), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A04", "val", "canonical.com", + "/this/is/a/long/path", base::Time(), base::Time(), + base::Time(), /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // Last_access @@ -1342,7 +1384,7 @@ TEST_F(CookieManagerTest, DeleteDetails_IgnoredFields) { base::Time::Now() - base::TimeDelta::FromDays(3), base::Time(), base::Time::Now() - base::TimeDelta::FromDays(3), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie( @@ -1350,7 +1392,7 @@ TEST_F(CookieManagerTest, DeleteDetails_IgnoredFields) { base::Time::Now() - base::TimeDelta::FromDays(3), base::Time(), base::Time::Now() - base::TimeDelta::FromDays(3), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // Same_site @@ -1358,13 +1400,13 @@ TEST_F(CookieManagerTest, DeleteDetails_IgnoredFields) { net::CanonicalCookie("A07", "val", "example.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::STRICT_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A08", "val", "canonical.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::STRICT_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // Priority @@ -1372,13 +1414,13 @@ TEST_F(CookieManagerTest, DeleteDetails_IgnoredFields) { net::CanonicalCookie("A09", "val", "example.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_HIGH), + net::COOKIE_PRIORITY_HIGH, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A10", "val", "canonical.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_HIGH), + net::COOKIE_PRIORITY_HIGH, /*same_party=*/false), "https", true)); // Use the filter and make sure the result is the expected set. @@ -1469,10 +1511,11 @@ TEST_F(CookieManagerTest, DeleteDetails_Consumer) { // Standard cookie EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A1", "val", test_cases[i].domain, test_cases[i].path, base::Time(), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A1", "val", test_cases[i].domain, + test_cases[i].path, base::Time(), base::Time(), + base::Time(), /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); if (!exclude_domain_cookie) { @@ -1482,24 +1525,26 @@ TEST_F(CookieManagerTest, DeleteDetails_Consumer) { "A2", "val", "." + test_cases[i].domain, test_cases[i].path, base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); } // Httponly cookie EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A3", "val", test_cases[i].domain, test_cases[i].path, base::Time(), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/true, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A3", "val", test_cases[i].domain, + test_cases[i].path, base::Time(), base::Time(), + base::Time(), /*secure=*/false, /*httponly=*/true, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // Httponly and secure cookie EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A4", "val", test_cases[i].domain, test_cases[i].path, base::Time(), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/true, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A4", "val", test_cases[i].domain, + test_cases[i].path, base::Time(), base::Time(), + base::Time(), /*secure=*/false, /*httponly=*/true, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); const uint32_t number_cookies = exclude_domain_cookie ? 3u : 4u; @@ -1520,28 +1565,28 @@ TEST_F(CookieManagerTest, DeleteByName) { net::CanonicalCookie("A1", "val", kCookieDomain, "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A1", "val", "bar_host", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A2", "val", kCookieDomain, "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A3", "val", "bar_host", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); mojom::CookieDeletionFilter filter; @@ -1561,36 +1606,40 @@ TEST_F(CookieManagerTest, DeleteByURL) { // Cookie that shouldn't be deleted because it's secure. EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A01", "val", "www.example.com", "/path", base::Time(), base::Time(), - base::Time(), /*secure=*/true, /*httponly=*/false, - net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A01", "val", "www.example.com", "/path", + base::Time(), base::Time(), base::Time(), + /*secure=*/true, /*httponly=*/false, + net::CookieSameSite::NO_RESTRICTION, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); // Cookie that should not be deleted because it's a host cookie in a // subdomain that doesn't exactly match the passed URL. EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A02", "val", "sub.www.example.com", "/path", base::Time(), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A02", "val", "sub.www.example.com", "/path", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); // Cookie that shouldn't be deleted because the path doesn't match. EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A03", "val", "www.example.com", "/otherpath", base::Time(), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A03", "val", "www.example.com", "/otherpath", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); // Cookie that shouldn't be deleted because the path is more specific // than the URL. EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A04", "val", "www.example.com", "/path/path2", base::Time(), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A04", "val", "www.example.com", "/path/path2", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); // Cookie that shouldn't be deleted because it's at a host cookie domain that @@ -1599,25 +1648,27 @@ TEST_F(CookieManagerTest, DeleteByURL) { net::CanonicalCookie("A05", "val", "example.com", "/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); // Cookie that should not be deleted because it's not a host cookie and // has a domain that's more specific than the URL EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A06", "val", ".sub.www.example.com", "/path", base::Time(), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A06", "val", ".sub.www.example.com", "/path", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); // Cookie that should be deleted because it's not a host cookie and has a // domain that matches the URL EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A07", "val", ".www.example.com", "/path", base::Time(), base::Time(), - base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A07", "val", ".www.example.com", "/path", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); // Cookie that should be deleted because it's not a host cookie and has a @@ -1626,15 +1677,16 @@ TEST_F(CookieManagerTest, DeleteByURL) { net::CanonicalCookie("A08", "val", ".example.com", "/path", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); // Cookie that should be deleted because it matches exactly. EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A09", "val", "www.example.com", "/path", base::Time(), base::Time(), - base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A09", "val", "www.example.com", "/path", + base::Time(), base::Time(), base::Time(), + /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); // Cookie that should be deleted because it applies to a larger set @@ -1643,7 +1695,7 @@ TEST_F(CookieManagerTest, DeleteByURL) { net::CanonicalCookie("A10", "val", "www.example.com", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true /*modify_httponly*/)); mojom::CookieDeletionFilter filter; @@ -1670,7 +1722,7 @@ TEST_F(CookieManagerTest, DeleteBySessionStatus) { net::CanonicalCookie("A1", "val", kCookieDomain, "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( @@ -1678,14 +1730,14 @@ TEST_F(CookieManagerTest, DeleteBySessionStatus) { now + base::TimeDelta::FromDays(1), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie("A3", "val", kCookieDomain, "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); mojom::CookieDeletionFilter filter; @@ -1732,13 +1784,13 @@ TEST_F(CookieManagerTest, DeleteByAll) { filter.session_control = mojom::CookieDeletionSessionControl::PERSISTENT_COOKIES; - // Architectypal cookie: + // Archetypal cookie: EXPECT_TRUE(SetCanonicalCookie( net::CanonicalCookie( "A1", "val0", "nope.com", "/path", now - base::TimeDelta::FromDays(3), now + base::TimeDelta::FromDays(3), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // Too old cookie. @@ -1747,7 +1799,7 @@ TEST_F(CookieManagerTest, DeleteByAll) { "A2", "val1", "nope.com", "/path", now - base::TimeDelta::FromDays(5), now + base::TimeDelta::FromDays(3), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // Too young cookie. @@ -1756,7 +1808,7 @@ TEST_F(CookieManagerTest, DeleteByAll) { "A3", "val2", "nope.com", "/path", now - base::TimeDelta::FromDays(1), now + base::TimeDelta::FromDays(3), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // Not in domains_and_ips_to_delete. @@ -1766,7 +1818,7 @@ TEST_F(CookieManagerTest, DeleteByAll) { now + base::TimeDelta::FromDays(3), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // In domains_and_ips_to_ignore. @@ -1775,7 +1827,7 @@ TEST_F(CookieManagerTest, DeleteByAll) { "A5", "val4", "no.com", "/path", now - base::TimeDelta::FromDays(3), now + base::TimeDelta::FromDays(3), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // Doesn't match URL (by path). @@ -1785,15 +1837,16 @@ TEST_F(CookieManagerTest, DeleteByAll) { now + base::TimeDelta::FromDays(3), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); // Session EXPECT_TRUE(SetCanonicalCookie( - net::CanonicalCookie( - "A7", "val7", "nope.com", "/path", now - base::TimeDelta::FromDays(3), - base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_MEDIUM), + net::CanonicalCookie("A7", "val7", "nope.com", "/path", + now - base::TimeDelta::FromDays(3), base::Time(), + base::Time(), /*secure=*/false, /*httponly=*/false, + net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); EXPECT_EQ(1u, service_wrapper()->DeleteCookies(filter)); @@ -1871,7 +1924,7 @@ TEST_F(CookieManagerTest, AddCookieChangeListener) { base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0u, listener.observed_changes().size()); @@ -1883,7 +1936,7 @@ TEST_F(CookieManagerTest, AddCookieChangeListener) { base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); base::RunLoop().RunUntilIdle(); @@ -1895,7 +1948,7 @@ TEST_F(CookieManagerTest, AddCookieChangeListener) { base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); // Expect asynchrony @@ -1949,7 +2002,7 @@ TEST_F(CookieManagerTest, AddGlobalChangeListener) { net::CanonicalCookie("Thing1", "val", kExampleHost, "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); // Expect asynchrony @@ -1972,13 +2025,13 @@ TEST_F(CookieManagerTest, AddGlobalChangeListener) { net::CanonicalCookie("Thing1", "val", kThisHost, "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); service_wrapper()->SetCanonicalCookie( net::CanonicalCookie("Thing2", "val", kThatHost, "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); base::RunLoop().RunUntilIdle(); @@ -2034,7 +2087,7 @@ TEST_F(CookieManagerTest, ListenerDestroyed) { base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true); EXPECT_EQ(0u, listener1->observed_changes().size()); @@ -2087,7 +2140,7 @@ TEST_F(CookieManagerTest, CloningAndClientDestructVisible) { net::CanonicalCookie("X", "Y", "www.other.host", "/", base::Time(), base::Time(), base::Time(), /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM), + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false), "https", true)); std::vector<net::CanonicalCookie> cookies = service_wrapper()->GetCookieList( @@ -2249,11 +2302,11 @@ class SessionCleanupCookieManagerTest : public CookieManagerTest { net::CanonicalCookie CreateCookie(const std::string& domain) { base::Time t = base::Time::Now(); - return net::CanonicalCookie("A", "B", domain, "/", t, - t + base::TimeDelta::FromDays(1), base::Time(), - /*secure=*/false, /*httponly=*/false, - net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_MEDIUM); + return net::CanonicalCookie( + "A", "B", domain, "/", t, t + base::TimeDelta::FromDays(1), + base::Time(), + /*secure=*/false, /*httponly=*/false, net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false); } private: diff --git a/chromium/services/network/cookie_settings.cc b/chromium/services/network/cookie_settings.cc index 581e395660e..628c8547d42 100644 --- a/chromium/services/network/cookie_settings.cc +++ b/chromium/services/network/cookie_settings.cc @@ -8,55 +8,24 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/strings/string_split.h" -#include "components/content_settings/core/common/content_settings_utils.h" #include "net/base/net_errors.h" #include "net/cookies/cookie_util.h" #include "net/cookies/static_cookie_policy.h" -#include "services/network/public/cpp/features.h" namespace network { namespace { + bool IsDefaultSetting(const ContentSettingPatternSource& setting) { return setting.primary_pattern.MatchesAllHosts() && setting.secondary_pattern.MatchesAllHosts(); } -void AppendEmergencyLegacyCookieAccess( - ContentSettingsForOneType* settings_for_legacy_cookie_access) { - if (!base::FeatureList::IsEnabled(features::kEmergencyLegacyCookieAccess)) - return; - - std::vector<std::string> patterns = - SplitString(features::kEmergencyLegacyCookieAccessParam.Get(), ",", - base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - - for (const auto& pattern_str : patterns) { - // Only primary pattern and the setting actually looked at here. - settings_for_legacy_cookie_access->push_back(ContentSettingPatternSource( - ContentSettingsPattern::FromString(pattern_str), - ContentSettingsPattern::Wildcard(), - /* legacy, see CookieSettingsBase::GetCookieAccessSemanticsForDomain */ - base::Value::FromUniquePtrValue( - content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW)), - std::string(), false)); - } -} - } // namespace -CookieSettings::CookieSettings() { - AppendEmergencyLegacyCookieAccess(&settings_for_legacy_cookie_access_); -} +CookieSettings::CookieSettings() = default; CookieSettings::~CookieSettings() = default; -void CookieSettings::set_content_settings_for_legacy_cookie_access( - const ContentSettingsForOneType& settings) { - settings_for_legacy_cookie_access_ = settings; - AppendEmergencyLegacyCookieAccess(&settings_for_legacy_cookie_access_); -} - DeleteCookiePredicate CookieSettings::CreateDeleteCookieOnExitPredicate() const { if (!HasSessionOnlyOrigins()) diff --git a/chromium/services/network/cookie_settings.h b/chromium/services/network/cookie_settings.h index 84eae422470..949ad155508 100644 --- a/chromium/services/network/cookie_settings.h +++ b/chromium/services/network/cookie_settings.h @@ -58,7 +58,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CookieSettings } void set_content_settings_for_legacy_cookie_access( - const ContentSettingsForOneType& settings); + const ContentSettingsForOneType& settings) { + settings_for_legacy_cookie_access_ = settings; + } void set_storage_access_grants(const ContentSettingsForOneType& settings) { storage_access_grants_ = settings; diff --git a/chromium/services/network/cookie_settings_unittest.cc b/chromium/services/network/cookie_settings_unittest.cc index 4e902b52288..0d0a06b4a89 100644 --- a/chromium/services/network/cookie_settings_unittest.cc +++ b/chromium/services/network/cookie_settings_unittest.cc @@ -502,45 +502,5 @@ TEST_F(CookieSettingsTest, } } -TEST_F(CookieSettingsTest, CookieAccessSemanticsEmergencyOverride) { - base::test::ScopedFeatureList feature_list; - - feature_list.InitWithFeaturesAndParameters( - {{net::features::kSameSiteByDefaultCookies, {}}, - {features::kEmergencyLegacyCookieAccess, - {{features::kEmergencyLegacyCookieAccessParamName, - "example.org, [*.]example.gov"}}}}, - {} /* disabled_features*/); - CookieSettings settings; - settings.set_content_settings_for_legacy_cookie_access( - {CreateSetting(kDomainWildcardPattern, "*", CONTENT_SETTING_ALLOW)}); - - const struct { - net::CookieAccessSemantics status; - std::string cookie_domain; - } kTestCases[] = { - // These three test cases are LEGACY because they match the setting. - {net::CookieAccessSemantics::LEGACY, kDomain}, - {net::CookieAccessSemantics::LEGACY, kDotDomain}, - // Subdomain also matches pattern. - {net::CookieAccessSemantics::LEGACY, kSubDomain}, - // This test case defaults into NONLEGACY. - {net::CookieAccessSemantics::NONLEGACY, kOtherDomain}, - - // things that got pushed via experiment config. - {net::CookieAccessSemantics::LEGACY, "example.org"}, - {net::CookieAccessSemantics::NONLEGACY, "sub.example.org"}, - {net::CookieAccessSemantics::LEGACY, "example.gov"}, - {net::CookieAccessSemantics::LEGACY, "sub.example.gov"}, - {net::CookieAccessSemantics::NONLEGACY, "example.gov.uk"}, - }; - - for (const auto& test : kTestCases) { - EXPECT_EQ(test.status, - settings.GetCookieAccessSemanticsForDomain(test.cookie_domain)) - << test.cookie_domain; - } -} - } // namespace } // namespace network diff --git a/chromium/services/network/cors/DIR_METADATA b/chromium/services/network/cors/DIR_METADATA new file mode 100644 index 00000000000..df937dae852 --- /dev/null +++ b/chromium/services/network/cors/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Blink>SecurityFeature>CORS" +}
\ No newline at end of file diff --git a/chromium/services/network/cors/OWNERS b/chromium/services/network/cors/OWNERS deleted file mode 100644 index e1d25b65190..00000000000 --- a/chromium/services/network/cors/OWNERS +++ /dev/null @@ -1 +0,0 @@ -# COMPONENT: Blink>SecurityFeature>CORS diff --git a/chromium/services/network/cors/cors_url_loader.cc b/chromium/services/network/cors/cors_url_loader.cc index d7d1d2aa2bc..dcf382dd7d1 100644 --- a/chromium/services/network/cors/cors_url_loader.cc +++ b/chromium/services/network/cors/cors_url_loader.cc @@ -545,6 +545,13 @@ void CorsURLLoader::HandleComplete(const URLLoaderCompletionStatus& status) { status.error_code); } + // TODO(crbug.com/1152550): Remove this histogram after platform apps no + // longer require relaxing CORB/CORS in their content scripts. + if (status.error_code == net::OK) { + UMA_HISTOGRAM_BOOLEAN("NetworkService.CorsForcedOffForIsolatedWorldOrigin", + has_cors_been_affected_by_isolated_world_origin_); + } + forwarding_client_->OnComplete(status); std::move(delete_callback_).Run(this); // |this| is deleted here. @@ -567,6 +574,8 @@ void CorsURLLoader::SetCorsFlagIfNeeded() { } if (HasSpecialAccessToDestination()) { + has_cors_been_affected_by_isolated_world_origin_ = + request_.isolated_world_origin.has_value(); return; } diff --git a/chromium/services/network/cors/cors_url_loader.h b/chromium/services/network/cors/cors_url_loader.h index 98de4924bdc..4fa196399a1 100644 --- a/chromium/services/network/cors/cors_url_loader.h +++ b/chromium/services/network/cors/cors_url_loader.h @@ -195,6 +195,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoader net::IsolationInfo isolation_info_; + bool has_cors_been_affected_by_isolated_world_origin_ = false; + // Used to run asynchronous class instance bound callbacks safely. base::WeakPtrFactory<CorsURLLoader> weak_factory_{this}; diff --git a/chromium/services/network/cors/cors_url_loader_factory.cc b/chromium/services/network/cors/cors_url_loader_factory.cc index 93328dbcc3f..25386af0f33 100644 --- a/chromium/services/network/cors/cors_url_loader_factory.cc +++ b/chromium/services/network/cors/cors_url_loader_factory.cc @@ -189,13 +189,12 @@ CorsURLLoaderFactory::CorsURLLoaderFactory( ignore_isolated_world_origin_(params->ignore_isolated_world_origin), trust_token_redemption_policy_(params->trust_token_redemption_policy), isolation_info_(params->isolation_info), - debug_tag_(params->debug_tag), origin_access_list_(origin_access_list) { DCHECK(context_); DCHECK(origin_access_list_); DCHECK_NE(mojom::kInvalidProcessId, process_id_); - DCHECK_EQ(net::IsolationInfo::RedirectMode::kUpdateNothing, - params->isolation_info.redirect_mode()); + DCHECK_EQ(net::IsolationInfo::RequestType::kOther, + params->isolation_info.request_type()); if (params->automatically_assign_isolation_info) { DCHECK(params->isolation_info.IsEmpty()); // Only the browser process is currently permitted to use automatically @@ -433,8 +432,6 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request, url::debug::ScopedOriginCrashKey initiator_lock_crash_key( debug::GetRequestInitiatorOriginLockCrashKey(), base::OptionalOrNullptr(request_initiator_origin_lock_)); - base::debug::ScopedCrashKeyString debug_tag_crash_key( - debug::GetFactoryDebugTagCrashKey(), debug_tag_); mojo::ReportBadMessage( "CorsURLLoaderFactory: lock VS initiator mismatch"); return false; diff --git a/chromium/services/network/cors/cors_url_loader_factory.h b/chromium/services/network/cors/cors_url_loader_factory.h index e58692fc0dd..86074799b74 100644 --- a/chromium/services/network/cors/cors_url_loader_factory.h +++ b/chromium/services/network/cors/cors_url_loader_factory.h @@ -109,7 +109,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoaderFactory final const bool ignore_isolated_world_origin_; const mojom::TrustTokenRedemptionPolicy trust_token_redemption_policy_; net::IsolationInfo isolation_info_; - const std::string debug_tag_; // Relative order of |network_loader_factory_| and |loaders_| matters - // URLLoaderFactory needs to live longer than URLLoaders created using the diff --git a/chromium/services/network/cors/cors_url_loader_factory_unittest.cc b/chromium/services/network/cors/cors_url_loader_factory_unittest.cc index 994d6f091e6..13811282f5b 100644 --- a/chromium/services/network/cors/cors_url_loader_factory_unittest.cc +++ b/chromium/services/network/cors/cors_url_loader_factory_unittest.cc @@ -5,7 +5,6 @@ #include <memory> #include "base/macros.h" -#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "mojo/public/cpp/bindings/remote.h" #include "net/proxy_resolution/configured_proxy_resolution_service.h" diff --git a/chromium/services/network/cors/cors_url_loader_unittest.cc b/chromium/services/network/cors/cors_url_loader_unittest.cc index d6e48d2531c..ed4ecad8080 100644 --- a/chromium/services/network/cors/cors_url_loader_unittest.cc +++ b/chromium/services/network/cors/cors_url_loader_unittest.cc @@ -9,7 +9,7 @@ #include <utility> #include <vector> -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/check.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -19,7 +19,6 @@ #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "mojo/public/cpp/bindings/message.h" #include "mojo/public/cpp/system/functions.h" @@ -1257,7 +1256,7 @@ TEST_F(CorsURLLoaderTest, request.update_first_party_url_on_redirect = true; request.trusted_params = ResourceRequest::TrustedParams(); request.trusted_params->isolation_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateTopFrame, + net::IsolationInfo::RequestType::kMainFrame, url_origin /* top_frame_origin */, url_origin /* frame_origin */, url_site_for_cookies); CreateLoaderAndStart(request); @@ -1286,10 +1285,10 @@ TEST_F(CorsURLLoaderTest, EXPECT_TRUE( GetRequest().site_for_cookies.IsEquivalent(new_url_site_for_cookies)); EXPECT_TRUE(GetRequest().trusted_params->isolation_info.IsEqualForTesting( - net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateTopFrame, - new_url_origin /* top_frame_origin */, - new_url_origin /* frame_origin */, new_url_site_for_cookies))); + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kMainFrame, + new_url_origin /* top_frame_origin */, + new_url_origin /* frame_origin */, + new_url_site_for_cookies))); NotifyLoaderClientOnReceiveResponse( {{"Access-Control-Allow-Origin", "https://example.com"}}); @@ -2282,8 +2281,8 @@ TEST_F(CorsURLLoaderTest, RestrictedPrefetchSucceedsWithNIK) { // Fill up the |trusted_params| NetworkIsolationKey member. url::Origin request_origin = url::Origin::Create(request.url); request.trusted_params->isolation_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, request_origin, - request_origin, net::SiteForCookies()); + net::IsolationInfo::RequestType::kOther, request_origin, request_origin, + net::SiteForCookies()); CreateLoaderAndStart(request); RunUntilCreateLoaderAndStartCalled(); diff --git a/chromium/services/network/cors/preflight_controller.cc b/chromium/services/network/cors/preflight_controller.cc index 11e1a9fad64..14e734734ec 100644 --- a/chromium/services/network/cors/preflight_controller.cc +++ b/chromium/services/network/cors/preflight_controller.cc @@ -144,6 +144,8 @@ std::unique_ptr<ResourceRequest> CreatePreflightRequest( // raw response to DevTools. preflight_request->devtools_request_id = devtools_request_id->ToString(); } + preflight_request->is_fetch_like_api = request.is_fetch_like_api; + return preflight_request; } diff --git a/chromium/services/network/cors/preflight_controller_unittest.cc b/chromium/services/network/cors/preflight_controller_unittest.cc index effbbabe67e..e0a7b05d2e9 100644 --- a/chromium/services/network/cors/preflight_controller_unittest.cc +++ b/chromium/services/network/cors/preflight_controller_unittest.cc @@ -536,9 +536,9 @@ TEST_F(PreflightControllerTest, CheckRequestNetworkIsolationKey) { const url::Origin& origin = test_initiator_origin(); request.request_initiator = origin; ResourceRequest::TrustedParams trusted_params; - trusted_params.isolation_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, origin, origin, - net::SiteForCookies()); + trusted_params.isolation_info = + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + origin, origin, net::SiteForCookies()); request.trusted_params = {trusted_params}; PerformPreflightCheck(request); @@ -554,9 +554,9 @@ TEST_F(PreflightControllerTest, CheckRequestNetworkIsolationKey) { url::Origin second_origin = url::Origin::Create(GURL("https://example.com/")); request.request_initiator = second_origin; SetAccessControlAllowOrigin(second_origin); - request.trusted_params->isolation_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, origin, second_origin, - net::SiteForCookies()); + request.trusted_params->isolation_info = + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + origin, second_origin, net::SiteForCookies()); PerformPreflightCheck(request); EXPECT_EQ(net::OK, net_error()); ASSERT_FALSE(status()); @@ -571,9 +571,9 @@ TEST_F(PreflightControllerTest, CheckFactoryNetworkIsolationKey) { const url::Origin& origin = test_initiator_origin(); request.request_initiator = origin; - const net::IsolationInfo isolation_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, origin, origin, - net::SiteForCookies()); + const net::IsolationInfo isolation_info = + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + origin, origin, net::SiteForCookies()); PerformPreflightCheck(request, false, isolation_info); EXPECT_EQ(net::OK, net_error()); diff --git a/chromium/services/network/crash_keys.cc b/chromium/services/network/crash_keys.cc index 96ecac78530..3b149820d4e 100644 --- a/chromium/services/network/crash_keys.cc +++ b/chromium/services/network/crash_keys.cc @@ -32,12 +32,6 @@ base::debug::CrashKeyString* GetRequestResourceTypeCrashKey() { return crash_key; } -base::debug::CrashKeyString* GetRequestLoadFlagsCrashKey() { - static auto* crash_key = base::debug::AllocateCrashKeyString( - "request_load_flags", base::debug::CrashKeySize::Size32); - return crash_key; -} - } // namespace base::debug::CrashKeyString* GetRequestInitiatorOriginLockCrashKey() { @@ -46,21 +40,13 @@ base::debug::CrashKeyString* GetRequestInitiatorOriginLockCrashKey() { return crash_key; } -base::debug::CrashKeyString* GetFactoryDebugTagCrashKey() { - static auto* crash_key = base::debug::AllocateCrashKeyString( - "url_loader_factory_debug_tag", base::debug::CrashKeySize::Size64); - return crash_key; -} - ScopedRequestCrashKeys::ScopedRequestCrashKeys( const network::ResourceRequest& request) : url_(GetRequestUrlCrashKey(), request.url.possibly_invalid_spec()), request_initiator_(GetRequestInitiatorCrashKey(), base::OptionalOrNullptr(request.request_initiator)), resource_type_(GetRequestResourceTypeCrashKey(), - base::NumberToString(request.resource_type)), - load_flags_(GetRequestLoadFlagsCrashKey(), - base::NumberToString(request.load_flags)) {} + base::NumberToString(request.resource_type)) {} ScopedRequestCrashKeys::~ScopedRequestCrashKeys() = default; diff --git a/chromium/services/network/crash_keys.h b/chromium/services/network/crash_keys.h index 78e7efc8b8a..580965feadb 100644 --- a/chromium/services/network/crash_keys.h +++ b/chromium/services/network/crash_keys.h @@ -16,7 +16,6 @@ struct ResourceRequest; namespace debug { base::debug::CrashKeyString* GetRequestInitiatorOriginLockCrashKey(); -base::debug::CrashKeyString* GetFactoryDebugTagCrashKey(); class ScopedRequestCrashKeys { public: @@ -29,14 +28,7 @@ class ScopedRequestCrashKeys { private: base::debug::ScopedCrashKeyString url_; url::debug::ScopedOriginCrashKey request_initiator_; - - // TODO(lukasza): https://crbug.com/1056949: Remove this diagnostic aid once - // the bug is understood. base::debug::ScopedCrashKeyString resource_type_; - - // TODO(lukasza): https://crbug.com/1056949: Remove this diagnostic aid once - // the bug is understood. - base::debug::ScopedCrashKeyString load_flags_; }; } // namespace debug diff --git a/chromium/services/network/expect_ct_reporter.cc b/chromium/services/network/expect_ct_reporter.cc index 31123b7be52..505524293b7 100644 --- a/chromium/services/network/expect_ct_reporter.cc +++ b/chromium/services/network/expect_ct_reporter.cc @@ -230,11 +230,10 @@ void ExpectCTReporter::OnResponseStarted(net::URLRequest* request, return; } - // TODO(https://crbug.com/993805): Pass in preflight->network_isolation_key, - // once reporting API accepts NetworkIsolationKeys. report_sender_->Send(preflight->report_uri, "application/expect-ct-report+json; charset=utf-8", - preflight->serialized_report, success_callback_, + preflight->serialized_report, + preflight->network_isolation_key, success_callback_, // Since |this| owns the |report_sender_|, it's safe to // use base::Unretained here: |report_sender_| will be // destroyed before |this|. @@ -271,7 +270,7 @@ void ExpectCTReporter::SendPreflight( url_request->set_allow_credentials(false); url_request->set_method(net::HttpRequestHeaders::kOptionsMethod); url_request->set_isolation_info(net::IsolationInfo::CreatePartial( - net::IsolationInfo::RedirectMode::kUpdateNothing, network_isolation_key)); + net::IsolationInfo::RequestType::kOther, network_isolation_key)); net::HttpRequestHeaders extra_headers; extra_headers.SetHeader("Origin", "null"); diff --git a/chromium/services/network/expect_ct_reporter_unittest.cc b/chromium/services/network/expect_ct_reporter_unittest.cc index e2fc979fdc7..723b562b74f 100644 --- a/chromium/services/network/expect_ct_reporter_unittest.cc +++ b/chromium/services/network/expect_ct_reporter_unittest.cc @@ -8,11 +8,11 @@ #include "base/base64.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/json/json_reader.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" @@ -52,6 +52,7 @@ class TestCertificateReportSender : public net::ReportSender { const GURL& report_uri, base::StringPiece content_type, base::StringPiece serialized_report, + const net::NetworkIsolationKey& network_isolation_key, base::OnceCallback<void()> success_callback, base::OnceCallback<void(const GURL&, int, int)> error_callback) override { sent_report_count_++; @@ -59,6 +60,7 @@ class TestCertificateReportSender : public net::ReportSender { latest_serialized_report_.assign(serialized_report.data(), serialized_report.size()); latest_content_type_.assign(content_type.data(), content_type.size()); + latest_network_isolation_key_ = network_isolation_key; if (!report_callback_.is_null()) { EXPECT_EQ(expected_report_uri_, latest_report_uri_); std::move(report_callback_).Run(); @@ -77,6 +79,10 @@ class TestCertificateReportSender : public net::ReportSender { return latest_serialized_report_; } + const net::NetworkIsolationKey latest_network_isolation_key() const { + return latest_network_isolation_key_; + } + // Can be called to wait for a single report, which is expected to be sent to // |report_uri|. Returns immediately if a report has already been sent in the // past. @@ -96,6 +102,7 @@ class TestCertificateReportSender : public net::ReportSender { GURL latest_report_uri_; std::string latest_content_type_; std::string latest_serialized_report_; + net::NetworkIsolationKey latest_network_isolation_key_; base::OnceClosure report_callback_; GURL expected_report_uri_; }; @@ -440,11 +447,13 @@ class ExpectCTReporterTest : public ::testing::Test { const GURL fail_report_uri = test_server().GetURL(fail_path); const GURL successful_report_uri = test_server().GetURL(successful_path); + const net::NetworkIsolationKey network_isolation_key = + net::NetworkIsolationKey::CreateTransient(); reporter->OnExpectCTFailed( host_port, fail_report_uri, base::Time(), ssl_info.cert.get(), ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps, - net::NetworkIsolationKey()); + network_isolation_key); bad_cors_run_loop.Run(); // The CORS preflight response may not even have been received yet, so // these expectations are mostly aspirational. @@ -459,9 +468,10 @@ class ExpectCTReporterTest : public ::testing::Test { reporter->OnExpectCTFailed( host_port, successful_report_uri, base::Time(), ssl_info.cert.get(), ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps, - net::NetworkIsolationKey()); + network_isolation_key); sender->WaitForReport(successful_report_uri); EXPECT_EQ(successful_report_uri, sender->latest_report_uri()); + EXPECT_EQ(network_isolation_key, sender->latest_network_isolation_key()); EXPECT_EQ(1, sender->sent_report_count()); } diff --git a/chromium/services/network/first_party_sets/BUILD.gn b/chromium/services/network/first_party_sets/BUILD.gn index 1194d1d7e32..e3fa641283b 100644 --- a/chromium/services/network/first_party_sets/BUILD.gn +++ b/chromium/services/network/first_party_sets/BUILD.gn @@ -60,7 +60,10 @@ source_set("tests") { defines = [ "IS_NETWORK_SERVICE_IMPL" ] - sources = [ "first_party_set_parser_unittest.cc" ] + sources = [ + "first_party_set_parser_unittest.cc", + "preloaded_first_party_sets_unittest.cc", + ] deps = [ ":first_party_sets", @@ -84,6 +87,7 @@ fuzzer_test("first_party_set_parser_fuzzer") { deps = [ ":first_party_sets", "//base", + "//net:net", "//net:net_fuzzer_test_support", ] dict = "test/first_party_set_parser_fuzzer.dict" @@ -95,6 +99,8 @@ fuzzer_test("first_party_set_parser_json_fuzzer") { deps = [ ":first_party_sets", "//base", + "//net:net", + "//net:net_fuzzer_test_support", "//testing/libfuzzer/proto:json_proto", "//testing/libfuzzer/proto:json_proto_converter", "//third_party/libprotobuf-mutator", diff --git a/chromium/services/network/first_party_sets/first_party_set_parser.cc b/chromium/services/network/first_party_sets/first_party_set_parser.cc index 70b10bb208a..cd23baff0c8 100644 --- a/chromium/services/network/first_party_sets/first_party_set_parser.cc +++ b/chromium/services/network/first_party_sets/first_party_set_parser.cc @@ -6,66 +6,125 @@ #include <iterator> #include <memory> +#include <string> +#include <utility> #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/json/json_reader.h" +#include "base/logging.h" +#include "base/optional.h" +#include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include "net/base/schemeful_site.h" +#include "url/gurl.h" +#include "url/origin.h" namespace network { namespace { +// Ensures that the string represents an origin that is non-opaque and HTTPS. +// Returns the registered domain. +base::Optional<net::SchemefulSite> Canonicalize(base::StringPiece origin_string, + bool emit_errors) { + const url::Origin origin(url::Origin::Create(GURL(origin_string))); + if (origin.opaque()) { + if (emit_errors) { + LOG(ERROR) << "First-Party Set origin " << origin_string + << " is not valid; ignoring."; + } + return base::nullopt; + } + if (origin.scheme() != "https") { + if (emit_errors) { + LOG(ERROR) << "First-Party Set origin " << origin_string + << " is not HTTPS; ignoring."; + } + return base::nullopt; + } + base::Optional<net::SchemefulSite> site = + net::SchemefulSite::CreateIfHasRegisterableDomain(origin); + if (!site.has_value()) { + if (emit_errors) { + LOG(ERROR) << "First-Party Set origin" << origin_string + << " does not have a valid registered domain; ignoring."; + } + return base::nullopt; + } + + return site; +} + const char kFirstPartySetOwnerField[] = "owner"; const char kFirstPartySetMembersField[] = "members"; // Parses a single First-Party Set into a map from member to owner (not // including the owner). Note that this is intended for use *only* on sets that // were preloaded via the component updater, so this does not check assertions -// or versions. It does not handle non-disjoint sets (i.e. sets which have -// non-empty intersections of owners and/or members).. -void ParsePreloadedSet( +// or versions. It rejects sets which are non-disjoint with +// previously-encountered sets (i.e. sets which have non-empty intersections +// with `elements`). +// +// Uses `elements` to check disjointness of sets; builds the mapping in `map`; +// and augments `elements` to include the elements of the set that was parsed. +// +// Returns true if parsing and validation were successful, false otherwise. +bool ParsePreloadedSet( const base::Value& value, - std::vector<std::pair<std::string, std::string>>& map_storage, - base::flat_set<std::string>& owners, - base::flat_set<std::string>& members) { + base::flat_map<net::SchemefulSite, net::SchemefulSite>& map, + base::flat_set<net::SchemefulSite>& elements) { if (!value.is_dict()) - return; + return false; // Confirm that the set has an owner, and the owner is a string. const std::string* maybe_owner = value.FindStringKey(kFirstPartySetOwnerField); if (!maybe_owner) - return; + return false; + + base::Optional<net::SchemefulSite> canonical_owner = + Canonicalize(std::move(*maybe_owner), false /* emit_errors */); + if (!canonical_owner.has_value()) + return false; - // An owner may only be listed once, and may not be a member of another set. - if (members.contains(*maybe_owner) || owners.contains(*maybe_owner)) - return; + // An owner may not be a member of another set. + if (elements.contains(*canonical_owner)) + return false; - owners.insert(*maybe_owner); + elements.insert(*canonical_owner); // Confirm that the members field is present, and is an array of strings. const base::Value* maybe_members_list = value.FindListKey(kFirstPartySetMembersField); if (!maybe_members_list) - return; + return false; // Add each member to our mapping (assuming the member is a string). for (const auto& item : maybe_members_list->GetList()) { // Members may not be a member of another set, and may not be an owner of // another set. - if (item.is_string()) { - std::string member = item.GetString(); - if (!members.contains(member) && !owners.contains(member)) { - map_storage.emplace_back(member, *maybe_owner); - members.insert(member); - } - } + if (!item.is_string()) + return false; + base::Optional<net::SchemefulSite> member = + Canonicalize(item.GetString(), false /* emit_errors */); + if (!member.has_value() || elements.contains(*member)) + return false; + map.emplace(*member, *canonical_owner); + elements.insert(std::move(*member)); } + return true; } } // namespace -std::unique_ptr<base::flat_map<std::string, std::string>> +base::Optional<net::SchemefulSite> +FirstPartySetParser::CanonicalizeRegisteredDomain( + const base::StringPiece origin_string, + bool emit_errors) { + return Canonicalize(origin_string, emit_errors); +} + +std::unique_ptr<base::flat_map<net::SchemefulSite, net::SchemefulSite>> FirstPartySetParser::ParsePreloadedSets(base::StringPiece raw_sets) { base::Optional<base::Value> maybe_value = base::JSONReader::Read( raw_sets, base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS); @@ -74,15 +133,15 @@ FirstPartySetParser::ParsePreloadedSets(base::StringPiece raw_sets) { if (!maybe_value->is_list()) return nullptr; - std::vector<std::pair<std::string, std::string>> map_storage; - base::flat_set<std::string> owners; - base::flat_set<std::string> members; + auto map = std::make_unique< + base::flat_map<net::SchemefulSite, net::SchemefulSite>>(); + base::flat_set<net::SchemefulSite> elements; for (const auto& value : maybe_value->GetList()) { - ParsePreloadedSet(value, map_storage, owners, members); + if (!ParsePreloadedSet(value, *map, elements)) + return nullptr; } - return std::make_unique<base::flat_map<std::string, std::string>>( - std::move(map_storage)); + return map; } } // namespace network diff --git a/chromium/services/network/first_party_sets/first_party_set_parser.h b/chromium/services/network/first_party_sets/first_party_set_parser.h index 7997dca0584..93b1ef1e66b 100644 --- a/chromium/services/network/first_party_sets/first_party_set_parser.h +++ b/chromium/services/network/first_party_sets/first_party_set_parser.h @@ -7,11 +7,18 @@ #include <map> #include <memory> +#include <string> #include "base/callback.h" #include "base/containers/flat_map.h" +#include "base/optional.h" +#include "base/strings/string_piece_forward.h" #include "base/values.h" +namespace net { +class SchemefulSite; +} + namespace network { class FirstPartySetParser { @@ -27,8 +34,17 @@ class FirstPartySetParser { // specified in this document: https://github.com/privacycg/first-party-sets. // This function does not check versions or assertions, since it is intended // only for *preloaded* sets. - static std::unique_ptr<base::flat_map<std::string, std::string>> + // + // Returns nullptr if parsing or validation of any set failed. + static std::unique_ptr<base::flat_map<net::SchemefulSite, net::SchemefulSite>> ParsePreloadedSets(base::StringPiece raw_sets); + + // Canonicalizes the passed in origin to a registered domain. In particular, + // this ensures that the origin is non-opaque, is HTTPS, and has a registered + // domain. Returns base::nullopt in case of any error. + static base::Optional<net::SchemefulSite> CanonicalizeRegisteredDomain( + const base::StringPiece origin_string, + bool emit_errors); }; } // namespace network diff --git a/chromium/services/network/first_party_sets/first_party_set_parser_unittest.cc b/chromium/services/network/first_party_sets/first_party_set_parser_unittest.cc index ff2250a7129..cb6bc9ff61a 100644 --- a/chromium/services/network/first_party_sets/first_party_set_parser_unittest.cc +++ b/chromium/services/network/first_party_sets/first_party_set_parser_unittest.cc @@ -5,15 +5,23 @@ #include "services/network/first_party_sets/first_party_set_parser.h" #include "base/json/json_reader.h" +#include "net/base/schemeful_site.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using ::testing::Eq; +using ::testing::IsEmpty; +using ::testing::IsNull; +using ::testing::Pair; using ::testing::Pointee; -using ::testing::UnorderedPointwise; +using ::testing::UnorderedElementsAre; namespace network { +MATCHER_P(SerializesTo, want, "") { + const std::string got = arg.Serialize(); + return testing::ExplainMatchResult(testing::Eq(want), got, result_listener); +} + TEST(FirstPartySetParser_Preloaded, RejectsEmpty) { // If the input isn't valid JSON, we should // reject it. In particular, we should reject @@ -48,79 +56,211 @@ TEST(FirstPartySetParser, AcceptsTrivial) { ASSERT_TRUE(base::JSONReader::Read(input)); EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise( - Eq(), base::flat_map<std::string, std::string>({})))); + Pointee(IsEmpty())); } TEST(FirstPartySetParser, AcceptsMinimal) { const std::string input = - R"( [ { "owner": "example.com", "members": ["aaaa"] } ] )"; + R"([{ + "owner": "https://example.test", + "members": ["https://aaaa.test"] + }])"; // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); - EXPECT_THAT( - FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise(Eq(), base::flat_map<std::string, std::string>( - {{"aaaa", "example.com"}})))); + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://aaaa.test"), + SerializesTo("https://example.test"))))); } TEST(FirstPartySetParser, RejectsMissingOwner) { - const std::string input = R"( [ { "members": ["aaaa"] } ] )"; + const std::string input = R"( [ { "members": ["https://aaaa.test"] } ] )"; // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); - EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise( - Eq(), base::flat_map<std::string, std::string>({})))); + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); } TEST(FirstPartySetParser, RejectsTypeUnsafeOwner) { - const std::string input = R"( [ { "owner": 3, "members": ["aaaa"] } ] )"; + const std::string input = + R"( [ { "owner": 3, "members": ["https://aaaa.test"] } ] )"; // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); - EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise( - Eq(), base::flat_map<std::string, std::string>({})))); + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); +} + +TEST(FirstPartySetParser, RejectsNonHTTPSOwner) { + const std::string input = + R"([{ + "owner": "http://example.test", + "members": ["https://aaaa.test"] + }])"; + + // Sanity check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); +} + +TEST(FirstPartySetParser, RejectsNonOriginOwner) { + const std::string input = + R"([{ + "owner": "example", + "members": ["https://aaaa.test"] + }])"; + + // Sanity check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); +} + +TEST(FirstPartySetParser, RejectsOwnerWithoutRegisteredDomain) { + const std::string input = + R"([{ + "owner": "https://example.test..", + "members": ["https://aaaa.test"] + }])"; + + // Sanity check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); } TEST(FirstPartySetParser, RejectsMissingMembers) { - const std::string input = R"( [ { "owner": "example.com" } ] )"; + const std::string input = R"( [ { "owner": "https://example.test" } ] )"; // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); - EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise( - Eq(), base::flat_map<std::string, std::string>({})))); + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); } TEST(FirstPartySetParser, RejectsTypeUnsafeMembers) { const std::string input = - R"( [ { "owner": "example.com", "members": ["aaaa", 4] } ] )"; + R"([{ + "owner": "https://example.test", + "members": ["https://aaaa.test", 4] + }])"; + + // Sanity check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); +} + +TEST(FirstPartySetParser, RejectsNonHTTPSMember) { + const std::string input = + R"([{ + "owner": "https://example.test", + "members": ["http://aaaa.test"] + }])"; + + // Sanity check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); +} + +TEST(FirstPartySetParser, RejectsNonOriginMember) { + const std::string input = + R"([{ + "owner": "https://example.test", + "members": ["aaaa"] + }])"; + + // Sanity check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); +} + +TEST(FirstPartySetParser, RejectsMemberWithoutRegisteredDomain) { + const std::string input = + R"([{ + "owner": "https://example.test", + "members": ["https://aaaa.test.."] + }])"; + + // Sanity check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); +} + +TEST(FirstPartySetParser, TruncatesSubdomain_Owner) { + const std::string input = + R"([{ + "owner": "https://subdomain.example.test", + "members": ["https://aaaa.test"] + }])"; + + // Sanity check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://aaaa.test"), + SerializesTo("https://example.test"))))); +} + +TEST(FirstPartySetParser, TruncatesSubdomain_Member) { + const std::string input = + R"([{ + "owner": "https://example.test", + "members": ["https://subdomain.aaaa.test"] + }])"; + + // Sanity check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://aaaa.test"), + SerializesTo("https://example.test"))))); +} + +TEST(FirstPartySetParser, AcceptsMultipleSets) { + const std::string input = R"( + [ + { + "owner": "https://example.test", + "members": ["https://member1.test"] + }, + { + "owner": "https://foo.test", + "members": ["https://member2.test"] + } + ] + )"; // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); EXPECT_THAT( FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise(Eq(), base::flat_map<std::string, std::string>( - {{"aaaa", "example.com"}})))); + Pointee(UnorderedElementsAre(Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member2.test"), + SerializesTo("https://foo.test"))))); } -TEST(FirstPartySetParser, AcceptsMultipleSets) { +TEST(FirstPartySetParser, RejectsInvalidSets_InvalidOwner) { const std::string input = R"( [ { - "owner": "example.com", - "members": ["member1"] + "owner": 3, + "members": ["https://member1.test"] }, { - "owner": "foo.com", - "members": ["member2"] + "owner": "https://foo.test", + "members": ["https://member2.test"] } ] )"; @@ -128,20 +268,35 @@ TEST(FirstPartySetParser, AcceptsMultipleSets) { // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); - EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise( - Eq(), base::flat_map<std::string, std::string>({ - {"member1", "example.com"}, - {"member2", "foo.com"}, - })))); + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); +} + +TEST(FirstPartySetParser, RejectsInvalidSets_InvalidMember) { + const std::string input = R"( + [ + { + "owner": "https://example.test", + "members": [3] + }, + { + "owner": "https://foo.test", + "members": ["https://member2.test"] + } + ] + )"; + + // Sanity check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); } TEST(FirstPartySetParser, AllowsTrailingCommas) { const std::string input = R"( [ { - "owner": "example.com", - "members": ["member1"], + "owner": "https://example.test", + "members": ["https://member1.test"], }, ] )"; @@ -151,22 +306,21 @@ TEST(FirstPartySetParser, AllowsTrailingCommas) { input, base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS)); EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise( - Eq(), base::flat_map<std::string, std::string>({ - {"member1", "example.com"}, - })))); + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test"))))); } -TEST(FirstPartySetParser, IgnoresSubsequent_SameOwner) { +TEST(FirstPartySetParser, Rejects_SameOwner) { const std::string input = R"( [ { - "owner": "example.com", - "members": ["member1"] + "owner": "https://example.test", + "members": ["https://member1.test"] }, { - "owner": "example.com", - "members": ["member2"] + "owner": "https://example.test", + "members": ["https://member2.test"] } ] )"; @@ -174,23 +328,19 @@ TEST(FirstPartySetParser, IgnoresSubsequent_SameOwner) { // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); - EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise( - Eq(), base::flat_map<std::string, std::string>({ - {"member1", "example.com"}, - })))); + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); } -TEST(FirstPartySetParser, IgnoresSubsequent_MemberAsOwner) { +TEST(FirstPartySetParser, Rejects_MemberAsOwner) { const std::string input = R"( [ { - "owner": "example.com", - "members": ["member1"] + "owner": "https://example.test", + "members": ["https://member1.test"] }, { - "owner": "member1", - "members": ["member2"] + "owner": "https://member1.test", + "members": ["https://member2.test"] } ] )"; @@ -198,23 +348,19 @@ TEST(FirstPartySetParser, IgnoresSubsequent_MemberAsOwner) { // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); - EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise( - Eq(), base::flat_map<std::string, std::string>({ - {"member1", "example.com"}, - })))); + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); } -TEST(FirstPartySetParser, IgnoresSubsequent_SameMember) { +TEST(FirstPartySetParser, Rejects_SameMember) { const std::string input = R"( [ { - "owner": "example.com", - "members": ["member1"] + "owner": "https://example.test", + "members": ["https://member1.test"] }, { - "owner": "foo.com", - "members": ["member1", "member2"] + "owner": "https://foo.test", + "members": ["https://member1.test", "https://member2.test"] } ] )"; @@ -222,24 +368,19 @@ TEST(FirstPartySetParser, IgnoresSubsequent_SameMember) { // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); - EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise( - Eq(), base::flat_map<std::string, std::string>({ - {"member1", "example.com"}, - {"member2", "foo.com"}, - })))); + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); } -TEST(FirstPartySetParser, IgnoresSubsequent_OwnerAsMember) { +TEST(FirstPartySetParser, Rejects_OwnerAsMember) { const std::string input = R"( [ { - "owner": "example.com", - "members": ["member1"] + "owner": "https://example.test", + "members": ["https://member1.test"] }, { - "owner": "example2.com", - "members": ["example.com", "member2"] + "owner": "https://example2.test", + "members": ["https://example.test", "https://member2.test"] } ] )"; @@ -247,12 +388,7 @@ TEST(FirstPartySetParser, IgnoresSubsequent_OwnerAsMember) { // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); - EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), - Pointee(UnorderedPointwise( - Eq(), base::flat_map<std::string, std::string>({ - {"member1", "example.com"}, - {"member2", "example2.com"}, - })))); + EXPECT_THAT(FirstPartySetParser::ParsePreloadedSets(input), IsNull()); } } // namespace network diff --git a/chromium/services/network/first_party_sets/preloaded_first_party_sets.cc b/chromium/services/network/first_party_sets/preloaded_first_party_sets.cc index d5d91a0b91e..021938ff31c 100644 --- a/chromium/services/network/first_party_sets/preloaded_first_party_sets.cc +++ b/chromium/services/network/first_party_sets/preloaded_first_party_sets.cc @@ -3,25 +3,104 @@ // found in the LICENSE file. #include "services/network/first_party_sets/preloaded_first_party_sets.h" + #include <memory> -#include "base/command_line.h" -#include "base/json/json_reader.h" -#include "base/values.h" +#include "base/logging.h" +#include "base/optional.h" +#include "base/ranges/algorithm.h" +#include "base/strings/string_split.h" +#include "net/base/schemeful_site.h" #include "services/network/first_party_sets/first_party_set_parser.h" -#include "services/network/public/cpp/network_switches.h" namespace network { +namespace { + +base::Optional< + std::pair<net::SchemefulSite, base::flat_set<net::SchemefulSite>>> +CanonicalizeSet(const std::vector<std::string>& origins) { + if (origins.empty()) + return base::nullopt; + + const base::Optional<net::SchemefulSite> maybe_owner = + FirstPartySetParser::CanonicalizeRegisteredDomain(origins[0], + true /* emit_errors */); + if (!maybe_owner.has_value()) { + LOG(ERROR) << "First-Party Set owner is not valid; aborting."; + return base::nullopt; + } + + const net::SchemefulSite& owner = *maybe_owner; + base::flat_set<net::SchemefulSite> members; + for (auto it = origins.begin() + 1; it != origins.end(); ++it) { + const base::Optional<net::SchemefulSite> maybe_member = + FirstPartySetParser::CanonicalizeRegisteredDomain( + *it, true /* emit_errors */); + if (maybe_member.has_value() && maybe_member != owner) + members.emplace(std::move(*maybe_member)); + } + + if (members.empty()) { + LOG(ERROR) << "No valid First-Party Set members were specified; aborting."; + return base::nullopt; + } + + return base::make_optional( + std::make_pair(std::move(owner), std::move(members))); +} + +} // namespace + PreloadedFirstPartySets::PreloadedFirstPartySets() = default; PreloadedFirstPartySets::~PreloadedFirstPartySets() = default; -void PreloadedFirstPartySets::ParseAndSet(base::StringPiece raw_sets) { - std::unique_ptr<base::flat_map<std::string, std::string>> parsed = - FirstPartySetParser::ParsePreloadedSets(raw_sets); - if (parsed) +void PreloadedFirstPartySets::SetManuallySpecifiedSet( + const std::string& flag_value) { + manually_specified_set_ = CanonicalizeSet(base::SplitString( + flag_value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)); + + ApplyManuallySpecifiedSet(); +} + +base::flat_map<net::SchemefulSite, net::SchemefulSite>* +PreloadedFirstPartySets::ParseAndSet(base::StringPiece raw_sets) { + std::unique_ptr<base::flat_map<net::SchemefulSite, net::SchemefulSite>> + parsed = FirstPartySetParser::ParsePreloadedSets(raw_sets); + if (parsed) { sets_.swap(*parsed); + } else { + // On any error, we clear the sets, to avoid using the old data and to make + // the failure as obvious as possible. + sets_.clear(); + } + ApplyManuallySpecifiedSet(); + return &sets_; +} + +void PreloadedFirstPartySets::ApplyManuallySpecifiedSet() { + if (!manually_specified_set_) + return; + + const net::SchemefulSite& manual_owner = manually_specified_set_->first; + const base::flat_set<net::SchemefulSite>& manual_members = + manually_specified_set_->second; + + sets_.erase( + base::ranges::remove_if(sets_, + [&manual_members, &manual_owner](const auto& p) { + return p.first == manual_owner || + p.second == manual_owner || + manual_members.contains(p.first) || + manual_members.contains(p.second); + }), + sets_.end()); + + // Next, we must add the manually-added set to the parsed value. + for (const net::SchemefulSite& member : manual_members) { + sets_.emplace(member, manual_owner); + } } } // namespace network diff --git a/chromium/services/network/first_party_sets/preloaded_first_party_sets.h b/chromium/services/network/first_party_sets/preloaded_first_party_sets.h index e38eebde9b4..8aab12706b0 100644 --- a/chromium/services/network/first_party_sets/preloaded_first_party_sets.h +++ b/chromium/services/network/first_party_sets/preloaded_first_party_sets.h @@ -10,6 +10,9 @@ #include "base/callback.h" #include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" +#include "net/base/schemeful_site.h" +#include "services/network/first_party_sets/first_party_set_parser.h" namespace network { @@ -24,14 +27,33 @@ class PreloadedFirstPartySets { PreloadedFirstPartySets(const PreloadedFirstPartySets&) = delete; PreloadedFirstPartySets& operator=(const PreloadedFirstPartySets&) = delete; - // Overwrites the current owners-to-sets map with the values in |raw_sets|, + void SetManuallySpecifiedSet(const std::string& flag_value); + + // Overwrites the current members-to-owners map with the values in |raw_sets|, // which should be the JSON-encoded string representation of a collection of // set declarations according to the format specified in this document: - // https://github.com/privacycg/first-party-sets - void ParseAndSet(base::StringPiece raw_sets); + // https://github.com/privacycg/first-party-sets. Returns a pointer to the + // mapping, for testing. + // + // In case of invalid input, clears the current members-to-owners map, but + // keeps any manually-specified set (i.e. a set provided on the command line). + base::flat_map<net::SchemefulSite, net::SchemefulSite>* ParseAndSet( + base::StringPiece raw_sets); + + int64_t size() const { return sets_.size(); } private: - base::flat_map<std::string, std::string> sets_; + // We must ensure there's no intersection between the manually-specified set + // and the sets that came from Component Updater. (When reconciling the + // manually-specified set and `sets_`, entries in the manually-specified set + // always win.) We must also ensure that `sets_` includes the set described by + // `manually_specified_set_`. + void ApplyManuallySpecifiedSet(); + + base::flat_map<net::SchemefulSite, net::SchemefulSite> sets_; + base::Optional< + std::pair<net::SchemefulSite, base::flat_set<net::SchemefulSite>>> + manually_specified_set_; }; } // namespace network diff --git a/chromium/services/network/first_party_sets/preloaded_first_party_sets_unittest.cc b/chromium/services/network/first_party_sets/preloaded_first_party_sets_unittest.cc new file mode 100644 index 00000000000..02ffb7d7100 --- /dev/null +++ b/chromium/services/network/first_party_sets/preloaded_first_party_sets_unittest.cc @@ -0,0 +1,394 @@ +// 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 "services/network/first_party_sets/preloaded_first_party_sets.h" + +#include "base/json/json_reader.h" +#include "net/base/schemeful_site.h" +#include "testing/gmock/include/gmock/gmock-matchers.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::IsEmpty; +using ::testing::Pair; +using ::testing::Pointee; +using ::testing::UnorderedElementsAre; + +// Some of these tests overlap with FirstPartySetParser unittests, but +// overlapping test coverage isn't the worst thing. + +namespace network { + +MATCHER_P(SerializesTo, want, "") { + const std::string got = arg.Serialize(); + return testing::ExplainMatchResult(testing::Eq(want), got, result_listener); +} + +TEST(PreloadedFirstPartySets, ParsesJSON) { + EXPECT_THAT(PreloadedFirstPartySets().ParseAndSet("[]"), Pointee(IsEmpty())); +} + +TEST(PreloadedFirstPartySets, AcceptsMinimal) { + const std::string input = + R"([{ + "owner": "https://example.test", + "members": ["https://aaaa.test"] + }])"; + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(PreloadedFirstPartySets().ParseAndSet(input), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://aaaa.test"), + SerializesTo("https://example.test"))))); +} + +TEST(PreloadedFirstPartySets, AcceptsMultipleSets) { + const std::string input = R"( + [ + { + "owner": "https://example.test", + "members": ["https://member1.test"] + }, + { + "owner": "https://foo.test", + "members": ["https://member2.test"] + } + ] + )"; + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT( + PreloadedFirstPartySets().ParseAndSet(input), + Pointee(UnorderedElementsAre(Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member2.test"), + SerializesTo("https://foo.test"))))); +} + +TEST(PreloadedFirstPartySets, ClearsPreloadedOnError) { + const std::string input = R"( + [ + { + "owner": "https://example.test", + "members": ["https://member1.test"] + }, + { + "owner": "https://foo.test", + "members": ["https://member2.test"] + } + ] + )"; + ASSERT_TRUE(base::JSONReader::Read(input)); + + PreloadedFirstPartySets sets; + EXPECT_THAT( + sets.ParseAndSet(input), + Pointee(UnorderedElementsAre(Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member2.test"), + SerializesTo("https://foo.test"))))); + + EXPECT_THAT(sets.ParseAndSet("{}"), Pointee(IsEmpty())); +} + +TEST(PreloadedFirstPartySets, OwnerIsOnlyMember) { + const std::string input = R"( + [ + { + "owner": "https://example.test", + "members": ["https://example.test"] + }, + { + "owner": "https://foo.test", + "members": ["https://member2.test"] + } + ] + )"; + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(PreloadedFirstPartySets().ParseAndSet(input), Pointee(IsEmpty())); +} + +TEST(PreloadedFirstPartySets, OwnerIsMember) { + const std::string input = R"( + [ + { + "owner": "https://example.test", + "members": ["https://example.test", "https://member1.test"] + }, + { + "owner": "https://foo.test", + "members": ["https://member2.test"] + } + ] + )"; + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(PreloadedFirstPartySets().ParseAndSet(input), Pointee(IsEmpty())); +} + +TEST(PreloadedFirstPartySets, RepeatedMember) { + const std::string input = R"( + [ + { + "owner": "https://example.test", + "members": [ + "https://member1.test", + "https://member2.test", + "https://member1.test" + ] + }, + { + "owner": "https://foo.test", + "members": ["https://member3.test"] + } + ] + )"; + ASSERT_TRUE(base::JSONReader::Read(input)); + + EXPECT_THAT(PreloadedFirstPartySets().ParseAndSet(input), Pointee(IsEmpty())); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_Invalid_TooSmall) { + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet("https://example.test"); + EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty())); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_Invalid_NotOrigins) { + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet("https://example.test,member1"); + EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty())); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_Invalid_NotHTTPS) { + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet("https://example.test,http://member1.test"); + EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty())); +} + +TEST(PreloadedFirstPartySets, + SetsManuallySpecified_Invalid_RegisteredDomain_Owner) { + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet( + "https://www.example.test..,https://www.member.test"); + EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty())); +} + +TEST(PreloadedFirstPartySets, + SetsManuallySpecified_Invalid_RegisteredDomain_Member) { + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet( + "https://www.example.test,https://www.member.test.."); + EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty())); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_Valid_SingleMember) { + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet("https://example.test,https://member.test"); + EXPECT_THAT(sets.ParseAndSet("[]"), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://member.test"), + SerializesTo("https://example.test"))))); +} + +TEST(PreloadedFirstPartySets, + SetsManuallySpecified_Valid_SingleMember_RegisteredDomain) { + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet( + "https://www.example.test,https://www.member.test"); + EXPECT_THAT(sets.ParseAndSet("[]"), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://member.test"), + SerializesTo("https://example.test"))))); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_Valid_MultipleMembers) { + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet( + "https://example.test,https://member1.test,https://member2.test"); + EXPECT_THAT(sets.ParseAndSet("[]"), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member2.test"), + SerializesTo("https://example.test"))))); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_Valid_OwnerIsOnlyMember) { + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet("https://example.test,https://example.test"); + EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty())); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_Valid_OwnerIsMember) { + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet( + "https://example.test,https://example.test,https://member1.test"); + EXPECT_THAT(sets.ParseAndSet("[]"), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test"))))); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_Valid_RepeatedMember) { + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet( + R"(https://example.test, + https://member1.test, + https://member2.test, + https://member1.test)"); + EXPECT_THAT(sets.ParseAndSet("[]"), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member2.test"), + SerializesTo("https://example.test"))))); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_DeduplicatesOwnerOwner) { + const std::string input = R"( + [ + { + "owner": "https://example.test", + "members": ["https://member2.test", "https://member3.test"] + }, + { + "owner": "https://bar.test", + "members": ["https://member4.test"] + } + ] + )"; + ASSERT_TRUE(base::JSONReader::Read(input)); + + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet( + "https://example.test,https://member1.test,https://member2.test"); + EXPECT_THAT( + sets.ParseAndSet(input), + Pointee(UnorderedElementsAre(Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member2.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member4.test"), + SerializesTo("https://bar.test"))))); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_DeduplicatesOwnerMember) { + const std::string input = R"( + [ + { + "owner": "https://foo.test", + "members": ["https://member1.test", "https://example.test"] + }, + { + "owner": "https://bar.test", + "members": ["https://member2.test"] + } + ] + )"; + ASSERT_TRUE(base::JSONReader::Read(input)); + + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet( + "https://example.test,https://member1.test,https://member3.test"); + EXPECT_THAT(sets.ParseAndSet(input), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member2.test"), + SerializesTo("https://bar.test")), + Pair(SerializesTo("https://member3.test"), + SerializesTo("https://example.test"))))); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_DeduplicatesMemberOwner) { + const std::string input = R"( + [ + { + "owner": "https://foo.test", + "members": ["https://member1.test", "https://member2.test"] + }, + { + "owner": "https://member3.test", + "members": ["https://member4.test"] + } + ] + )"; + ASSERT_TRUE(base::JSONReader::Read(input)); + + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet("https://example.test,https://member3.test"); + EXPECT_THAT(sets.ParseAndSet(input), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://member1.test"), + SerializesTo("https://foo.test")), + Pair(SerializesTo("https://member2.test"), + SerializesTo("https://foo.test")), + Pair(SerializesTo("https://member3.test"), + SerializesTo("https://example.test"))))); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_DeduplicatesMemberMember) { + const std::string input = R"( + [ + { + "owner": "https://foo.test", + "members": ["https://member2.test", "https://member3.test"] + }, + { + "owner": "https://bar.test", + "members": ["https://member4.test"] + } + ] + )"; + ASSERT_TRUE(base::JSONReader::Read(input)); + + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet( + "https://example.test,https://member1.test,https://member2.test"); + EXPECT_THAT( + sets.ParseAndSet(input), + Pointee(UnorderedElementsAre(Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member2.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member3.test"), + SerializesTo("https://foo.test")), + Pair(SerializesTo("https://member4.test"), + SerializesTo("https://bar.test"))))); +} + +TEST(PreloadedFirstPartySets, SetsManuallySpecified_ClearsPreloadedOnError) { + const std::string input = R"( + [ + { + "owner": "https://bar.test", + "members": ["https://member3.test"] + } + ] + )"; + ASSERT_TRUE(base::JSONReader::Read(input)); + + PreloadedFirstPartySets sets; + sets.SetManuallySpecifiedSet( + "https://example.test,https://member1.test,https://member2.test"); + EXPECT_THAT( + sets.ParseAndSet(input), + Pointee(UnorderedElementsAre(Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member2.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member3.test"), + SerializesTo("https://bar.test"))))); + + EXPECT_THAT(sets.ParseAndSet("{}"), + Pointee(UnorderedElementsAre( + Pair(SerializesTo("https://member1.test"), + SerializesTo("https://example.test")), + Pair(SerializesTo("https://member2.test"), + SerializesTo("https://example.test"))))); +} + +} // namespace network diff --git a/chromium/services/network/host_resolver_unittest.cc b/chromium/services/network/host_resolver_unittest.cc index c74df377252..8b9a4b7e9a8 100644 --- a/chromium/services/network/host_resolver_unittest.cc +++ b/chromium/services/network/host_resolver_unittest.cc @@ -11,7 +11,7 @@ #include "base/check.h" #include "base/optional.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/time/time.h" #include "mojo/public/cpp/bindings/pending_remote.h" diff --git a/chromium/services/network/http_cache_data_counter_unittest.cc b/chromium/services/network/http_cache_data_counter_unittest.cc index ea7d6c5d1a3..0ff12005ff4 100644 --- a/chromium/services/network/http_cache_data_counter_unittest.cc +++ b/chromium/services/network/http_cache_data_counter_unittest.cc @@ -14,7 +14,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" #include "base/stl_util.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "mojo/public/cpp/bindings/remote.h" diff --git a/chromium/services/network/http_server_properties_pref_delegate.cc b/chromium/services/network/http_server_properties_pref_delegate.cc index 8dda6b2bca2..1bac16b8e92 100644 --- a/chromium/services/network/http_server_properties_pref_delegate.cc +++ b/chromium/services/network/http_server_properties_pref_delegate.cc @@ -27,13 +27,13 @@ void HttpServerPropertiesPrefDelegate::RegisterPrefs( pref_registry->RegisterDictionaryPref(kPrefPath); } -const base::DictionaryValue* -HttpServerPropertiesPrefDelegate::GetServerProperties() const { - return pref_service_->GetDictionary(kPrefPath); +const base::Value* HttpServerPropertiesPrefDelegate::GetServerProperties() + const { + return pref_service_->Get(kPrefPath); } void HttpServerPropertiesPrefDelegate::SetServerProperties( - const base::DictionaryValue& value, + const base::Value& value, base::OnceClosure callback) { pref_service_->Set(kPrefPath, value); if (callback) diff --git a/chromium/services/network/http_server_properties_pref_delegate.h b/chromium/services/network/http_server_properties_pref_delegate.h index 47fd481aef0..76357102577 100644 --- a/chromium/services/network/http_server_properties_pref_delegate.h +++ b/chromium/services/network/http_server_properties_pref_delegate.h @@ -25,8 +25,8 @@ class HttpServerPropertiesPrefDelegate static void RegisterPrefs(PrefRegistrySimple* pref_registry); // net::HttpServerProperties::PrefDelegate implementation. - const base::DictionaryValue* GetServerProperties() const override; - void SetServerProperties(const base::DictionaryValue& value, + const base::Value* GetServerProperties() const override; + void SetServerProperties(const base::Value& value, base::OnceClosure callback) override; void WaitForPrefLoad(base::OnceClosure callback) override; diff --git a/chromium/services/network/mdns_responder.cc b/chromium/services/network/mdns_responder.cc index a7a2b71c1e7..ce2a56a7822 100644 --- a/chromium/services/network/mdns_responder.cc +++ b/chromium/services/network/mdns_responder.cc @@ -6,6 +6,7 @@ #include <cmath> #include <numeric> #include <queue> +#include <string> #include <utility> #include "services/network/mdns_responder.h" @@ -16,6 +17,7 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" +#include "base/optional.h" #include "base/rand_util.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" @@ -966,11 +968,12 @@ void MdnsResponderManager::OnMdnsQueryReceived( // responder only provides APIs to create address records, and hence limited // to handle only such records. Once we have expanded the API surface to // include the service publishing, the handling logic should be unified. - const std::string qname = net::DNSDomainToString(query.qname()); + const base::Optional<std::string> qname = + net::DnsDomainToString(query.qname()); if (base::FeatureList::IsEnabled( features::kMdnsResponderGeneratedNameListing)) { - if (should_respond_to_generator_service_query_ && - qname == kMdnsNameGeneratorServiceInstanceName) { + if (should_respond_to_generator_service_query_ && qname && + qname.value() == kMdnsNameGeneratorServiceInstanceName) { HandleMdnsNameGeneratorServiceQuery(query, recv_socket_handler_id); return; } @@ -1233,8 +1236,11 @@ void MdnsResponder::RemoveNameForAddress( void MdnsResponder::OnMdnsQueryReceived(const net::DnsQuery& query, uint16_t recv_socket_handler_id) { // Currently we only support a single question in DnsQuery. - std::string dotted_name_to_resolve = net::DNSDomainToString(query.qname()); - auto it = name_addr_map_.find(dotted_name_to_resolve); + base::Optional<std::string> dotted_name_to_resolve = + net::DnsDomainToString(query.qname()); + if (!dotted_name_to_resolve) + return; + auto it = name_addr_map_.find(dotted_name_to_resolve.value()); if (it == name_addr_map_.end()) return; diff --git a/chromium/services/network/mdns_responder_unittest.cc b/chromium/services/network/mdns_responder_unittest.cc index 54a89342554..8a772e35ddc 100644 --- a/chromium/services/network/mdns_responder_unittest.cc +++ b/chromium/services/network/mdns_responder_unittest.cc @@ -11,7 +11,7 @@ #include "services/network/mdns_responder.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/check_op.h" #include "base/memory/scoped_refptr.h" #include "base/strings/string_number_conversions.h" diff --git a/chromium/services/network/net_log_exporter.cc b/chromium/services/network/net_log_exporter.cc index d5694bec240..32ffd1a70a7 100644 --- a/chromium/services/network/net_log_exporter.cc +++ b/chromium/services/network/net_log_exporter.cc @@ -90,8 +90,8 @@ void NetLogExporter::Stop(base::Value polled_data_value, return; } - base::Value net_info = net::GetNetInfo( - network_context_->url_request_context(), net::NET_INFO_ALL_SOURCES); + base::Value net_info = + net::GetNetInfo(network_context_->url_request_context()); if (polled_data) net_info.MergeDictionary(polled_data); @@ -185,12 +185,12 @@ void NetLogExporter::StartWithScratchDir( if (max_file_size != kUnlimitedFileSize) { file_net_observer_ = net::FileNetLogObserver::CreateBoundedPreExisting( - scratch_dir_path, std::move(destination_), max_file_size, + scratch_dir_path, std::move(destination_), max_file_size, capture_mode, std::move(constants)); } else { DCHECK(scratch_dir_path.empty()); file_net_observer_ = net::FileNetLogObserver::CreateUnboundedPreExisting( - std::move(destination_), std::move(constants)); + std::move(destination_), capture_mode, std::move(constants)); } // There might not be a NetworkService object e.g. on iOS; in that case @@ -206,7 +206,7 @@ void NetLogExporter::StartWithScratchDir( } file_net_observer_->StartObserving( - network_context_->url_request_context()->net_log(), capture_mode); + network_context_->url_request_context()->net_log()); std::move(callback).Run(net::OK); } diff --git a/chromium/services/network/network_change_manager.cc b/chromium/services/network/network_change_manager.cc index 0c428a188ce..fb573cd71d0 100644 --- a/chromium/services/network/network_change_manager.cc +++ b/chromium/services/network/network_change_manager.cc @@ -8,6 +8,7 @@ #include <utility> #include "base/bind.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "net/base/network_change_notifier.h" #include "net/base/network_change_notifier_posix.h" @@ -48,7 +49,7 @@ void NetworkChangeManager::RequestNotifications( clients_.push_back(std::move(client_remote)); } -#if defined(OS_CHROMEOS) || defined(OS_ANDROID) +#if BUILDFLAG(IS_ASH) || defined(OS_ANDROID) void NetworkChangeManager::OnNetworkChanged( bool dns_changed, bool ip_address_changed, diff --git a/chromium/services/network/network_change_manager.h b/chromium/services/network/network_change_manager.h index 3ed329484bf..e73988a41c0 100644 --- a/chromium/services/network/network_change_manager.h +++ b/chromium/services/network/network_change_manager.h @@ -12,6 +12,7 @@ #include "base/component_export.h" #include "base/macros.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/bindings/remote.h" #include "net/base/network_change_notifier.h" @@ -43,7 +44,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkChangeManager mojo::PendingRemote<mojom::NetworkChangeManagerClient> client_remote) override; -#if defined(OS_CHROMEOS) || defined(OS_ANDROID) +#if BUILDFLAG(IS_ASH) || defined(OS_ANDROID) void OnNetworkChanged( bool dns_changed, bool ip_address_changed, diff --git a/chromium/services/network/network_context.cc b/chromium/services/network/network_context.cc index 1e9e1d93cb7..55ab0025462 100644 --- a/chromium/services/network/network_context.cc +++ b/chromium/services/network/network_context.cc @@ -31,6 +31,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "build/chromecast_buildflags.h" +#include "build/chromeos_buildflags.h" #include "components/cookie_config/cookie_store_util.h" #include "components/domain_reliability/monitor.h" #include "components/network_session_configurator/browser/network_session_configurator.h" @@ -49,7 +50,6 @@ #include "net/cert/caching_cert_verifier.h" #include "net/cert/cert_verifier.h" #include "net/cert/coalescing_cert_verifier.h" -#include "net/cert/ct_verify_result.h" #include "net/cert_net/cert_net_fetcher_url_request.h" #include "net/cookies/cookie_monster.h" #include "net/dns/host_cache.h" @@ -129,9 +129,9 @@ #include "net/ftp/ftp_auth_cache.h" #endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "services/network/cert_verifier_with_trust_anchors.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) #if !defined(OS_IOS) #include "services/network/websocket_factory.h" @@ -400,9 +400,17 @@ NetworkContext::NetworkContext( url_loader_factory_for_cert_net_fetcher .InitWithNewPipeAndPassReceiver(); + scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store = + MakeSessionCleanupCookieStore(); + url_request_context_owner_ = - MakeURLRequestContext(std::move(url_loader_factory_for_cert_net_fetcher)); + MakeURLRequestContext(std::move(url_loader_factory_for_cert_net_fetcher), + session_cleanup_cookie_store); url_request_context_ = url_request_context_owner_.url_request_context.get(); + cookie_manager_ = std::make_unique<CookieManager>( + url_request_context_, network_service_->preloaded_first_party_sets(), + std::move(session_cleanup_cookie_store), + std::move(params_->cookie_manager_params)); network_service_->RegisterNetworkContext(this); @@ -457,10 +465,11 @@ NetworkContext::NetworkContext( std::make_unique<NetworkContextApplicationStatusListener>()), #endif receiver_(this, std::move(receiver)), - cookie_manager_( - std::make_unique<CookieManager>(url_request_context->cookie_store(), - nullptr, - nullptr)), + cookie_manager_(std::make_unique<CookieManager>( + url_request_context, + nullptr, + nullptr /* preloaded_first_party_sets */, + nullptr)), socket_factory_( std::make_unique<SocketFactory>(url_request_context_->net_log(), url_request_context)), @@ -836,11 +845,16 @@ void NetworkContext::ClearNetworkErrorLogging( std::move(callback).Run(); } -void NetworkContext::QueueReport(const std::string& type, - const std::string& group, - const GURL& url, - const base::Optional<std::string>& user_agent, - base::Value body) { +void NetworkContext::QueueReport( + const std::string& type, + const std::string& group, + const GURL& url, + const net::NetworkIsolationKey& network_isolation_key, + const base::Optional<std::string>& user_agent, + base::Value body) { + // TODO(mmenke): Once all callers have been updated to send a + // NetworkIsolationKey, DCHECK network_isolation_key() is not null, when + // require_network_isolation_key() is set on the URLRequestContext. DCHECK(body.is_dict()); if (!body.is_dict()) return; @@ -862,14 +876,18 @@ void NetworkContext::QueueReport(const std::string& type, request_context->http_user_agent_settings()->GetUserAgent(); } - // Send the crash report to the Reporting API. - reporting_service->QueueReport(url, reported_user_agent, group, type, - base::Value::ToUniquePtrValue(std::move(body)), - 0 /* depth */); + reporting_service->QueueReport( + url, network_isolation_key, reported_user_agent, group, type, + base::Value::ToUniquePtrValue(std::move(body)), 0 /* depth */); } void NetworkContext::QueueSignedExchangeReport( - mojom::SignedExchangeReportPtr report) { + mojom::SignedExchangeReportPtr report, + const net::NetworkIsolationKey& network_isolation_key) { + // TODO(mmenke): Once all callers have been updated to send a + // NetworkIsolationKey, DCHECK network_isolation_key() is not null, when + // require_network_isolation_key() is set on the URLRequestContext. + net::URLRequestContext* request_context = url_request_context(); net::NetworkErrorLoggingService* logging_service = request_context->network_error_logging_service(); @@ -880,6 +898,7 @@ void NetworkContext::QueueSignedExchangeReport( user_agent = request_context->http_user_agent_settings()->GetUserAgent(); } net::NetworkErrorLoggingService::SignedExchangeReportDetails details; + details.network_isolation_key = network_isolation_key; details.success = report->success; details.type = std::move(report->type); details.outer_url = std::move(report->outer_url); @@ -914,16 +933,19 @@ void NetworkContext::ClearNetworkErrorLogging( NOTREACHED(); } -void NetworkContext::QueueReport(const std::string& type, - const std::string& group, - const GURL& url, - const base::Optional<std::string>& user_agent, - base::Value body) { +void NetworkContext::QueueReport( + const std::string& type, + const std::string& group, + const GURL& url, + const net::NetworkIsolationKey& network_isolation_key, + const base::Optional<std::string>& user_agent, + base::Value body) { NOTREACHED(); } void NetworkContext::QueueSignedExchangeReport( - mojom::SignedExchangeReportPtr report) { + mojom::SignedExchangeReportPtr report, + const net::NetworkIsolationKey& network_isolation_key) { NOTREACHED(); } #endif // BUILDFLAG(ENABLE_REPORTING) @@ -1011,7 +1033,7 @@ void NetworkContext::SetEnableReferrers(bool enable_referrers) { network_delegate_->set_enable_referrers(enable_referrers); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void NetworkContext::UpdateAdditionalCertificates( mojom::AdditionalCertificatesPtr additional_certificates) { if (!cert_verifier_with_trust_anchors_) { @@ -1028,7 +1050,7 @@ void NetworkContext::UpdateAdditionalCertificates( additional_certificates->trust_anchors, additional_certificates->all_certificates); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) #if BUILDFLAG(IS_CT_SUPPORTED) void NetworkContext::SetCTPolicy(mojom::CTPolicyPtr ct_policy) { @@ -1360,15 +1382,21 @@ void NetworkContext::CreateHostResolver( void NetworkContext::VerifyCertForSignedExchange( const scoped_refptr<net::X509Certificate>& certificate, const GURL& url, + const net::NetworkIsolationKey& network_isolation_key, const std::string& ocsp_result, const std::string& sct_list, VerifyCertForSignedExchangeCallback callback) { + // TODO(https://crbug.com/1087091): DCHECK that |network_isolation_key| is + // populated when |require_network_isolation_key| is true, once all consumers + // are passing in a NetworkIsolationKey. + int cert_verify_id = ++next_cert_verify_id_; auto pending_cert_verify = std::make_unique<PendingCertVerify>(); pending_cert_verify->callback = std::move(callback); pending_cert_verify->result = std::make_unique<net::CertVerifyResult>(); pending_cert_verify->certificate = certificate; pending_cert_verify->url = url; + pending_cert_verify->network_isolation_key = network_isolation_key; pending_cert_verify->ocsp_result = ocsp_result; pending_cert_verify->sct_list = sct_list; net::CertVerifier* cert_verifier = @@ -1379,7 +1407,7 @@ void NetworkContext::VerifyCertForSignedExchange( 0 /* cert_verify_flags */, ocsp_result, sct_list), pending_cert_verify->result.get(), - base::BindOnce(&NetworkContext::OnCertVerifyForSignedExchangeComplete, + base::BindOnce(&NetworkContext::OnVerifyCertForSignedExchangeComplete, base::Unretained(this), cert_verify_id), &pending_cert_verify->request, net::NetLogWithSource::Make(url_request_context_->net_log(), @@ -1387,7 +1415,7 @@ void NetworkContext::VerifyCertForSignedExchange( cert_verifier_requests_[cert_verify_id] = std::move(pending_cert_verify); if (result != net::ERR_IO_PENDING) - OnCertVerifyForSignedExchangeComplete(cert_verify_id, result); + OnVerifyCertForSignedExchangeComplete(cert_verify_id, result); } void NetworkContext::ParseHeaders( @@ -1400,11 +1428,13 @@ void NetworkContext::ParseHeaders( void NetworkContext::NotifyExternalCacheHit( const GURL& url, const std::string& http_method, - const net::NetworkIsolationKey& key) { + const net::NetworkIsolationKey& key, + bool is_subframe_document_resource) { net::HttpCache* cache = url_request_context_->http_transaction_factory()->GetCache(); if (cache) { - cache->OnExternalCacheHit(url, http_method, key); + cache->OnExternalCacheHit(url, http_method, key, + is_subframe_document_resource); } } @@ -1726,7 +1756,7 @@ void NetworkContext::LookupServerBasicAuthCredentials( std::move(callback).Run(base::nullopt); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void NetworkContext::LookupProxyAuthCredentials( const net::ProxyServer& proxy_server, const std::string& auth_scheme, @@ -1788,6 +1818,8 @@ void NetworkContext::OnHttpAuthDynamicParamsChanged( http_auth_dynamic_network_service_params->negotiate_disable_cname_lookup); http_auth_merged_preferences_.set_negotiate_enable_port( http_auth_dynamic_network_service_params->enable_negotiate_port); + http_auth_merged_preferences_.set_basic_over_http_enabled( + http_auth_dynamic_network_service_params->basic_over_http_enabled); #if defined(OS_POSIX) || defined(OS_FUCHSIA) http_auth_merged_preferences_.set_ntlm_v2_enabled( http_auth_dynamic_network_service_params->ntlm_v2_enabled); @@ -1798,7 +1830,7 @@ void NetworkContext::OnHttpAuthDynamicParamsChanged( http_auth_dynamic_network_service_params->android_negotiate_account_type); #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) http_auth_merged_preferences_.set_allow_gssapi_library_load( http_auth_dynamic_network_service_params->allow_gssapi_library_load); #endif @@ -1806,7 +1838,8 @@ void NetworkContext::OnHttpAuthDynamicParamsChanged( URLRequestContextOwner NetworkContext::MakeURLRequestContext( mojo::PendingRemote<mojom::URLLoaderFactory> - url_loader_factory_for_cert_net_fetcher) { + url_loader_factory_for_cert_net_fetcher, + scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store) { URLRequestContextBuilderMojo builder; const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); @@ -1858,7 +1891,7 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( std::make_unique<net::CoalescingCertVerifier>( std::move(cert_verifier))); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) cert_verifier_with_trust_anchors_ = new CertVerifierWithTrustAnchors(base::BindRepeating( &NetworkContext::TrustAnchorUsed, base::Unretained(this))); @@ -1867,7 +1900,7 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( cert_verifier_with_trust_anchors_->InitializeOnIOThread( std::move(cert_verifier)); cert_verifier = base::WrapUnique(cert_verifier_with_trust_anchors_); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) } builder.SetCertVerifier(IgnoreErrorsCertVerifier::MaybeWrapCertVerifier( @@ -1905,33 +1938,7 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( network_service_->network_quality_estimator()); } - scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store; - if (params_->cookie_path) { - scoped_refptr<base::SequencedTaskRunner> client_task_runner = - base::ThreadTaskRunnerHandle::Get(); - scoped_refptr<base::SequencedTaskRunner> background_task_runner = - base::ThreadPool::CreateSequencedTaskRunner( - {base::MayBlock(), net::GetCookieStoreBackgroundSequencePriority(), - base::TaskShutdownBehavior::BLOCK_SHUTDOWN}); - - net::CookieCryptoDelegate* crypto_delegate = nullptr; - if (params_->enable_encrypted_cookies) { -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && !BUILDFLAG(IS_CHROMECAST) - DCHECK(network_service_->os_crypt_config_set()) - << "NetworkService::SetCryptConfig must be called before creating a " - "NetworkContext with encrypted cookies."; -#endif - crypto_delegate = cookie_config::GetCookieCryptoDelegate(); - } - scoped_refptr<net::SQLitePersistentCookieStore> sqlite_store( - new net::SQLitePersistentCookieStore( - params_->cookie_path.value(), client_task_runner, - background_task_runner, params_->restore_old_session_cookies, - crypto_delegate)); - - session_cleanup_cookie_store = - base::MakeRefCounted<SessionCleanupCookieStore>(sqlite_store); - + if (session_cleanup_cookie_store) { std::unique_ptr<net::CookieMonster> cookie_store = std::make_unique<net::CookieMonster>(session_cleanup_cookie_store.get(), net_log); @@ -1939,9 +1946,6 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( cookie_store->SetPersistSessionCookies(true); builder.SetCookieStore(std::move(cookie_store)); - } else { - DCHECK(!params_->restore_old_session_cookies); - DCHECK(!params_->persist_session_cookies); } if (base::FeatureList::IsEnabled(features::kTrustTokens)) { @@ -1979,11 +1983,11 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( std::move(params_->proxy_resolver_factory)); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) if (params_->dhcp_wpad_url_client) { builder.SetDhcpWpadUrlClient(std::move(params_->dhcp_wpad_url_client)); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) if (!params_->http_cache_enabled) { builder.DisableHttpCache(); @@ -2266,17 +2270,44 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( result.url_request_context->proxy_resolution_service()); } - cookie_manager_ = std::make_unique<CookieManager>( - result.url_request_context->cookie_store(), - std::move(session_cleanup_cookie_store), - std::move(params_->cookie_manager_params)); - if (cert_net_fetcher_) cert_net_fetcher_->SetURLRequestContext(result.url_request_context.get()); return result; } +scoped_refptr<SessionCleanupCookieStore> +NetworkContext::MakeSessionCleanupCookieStore() const { + if (!params_->cookie_path) { + DCHECK(!params_->restore_old_session_cookies); + DCHECK(!params_->persist_session_cookies); + return nullptr; + } + scoped_refptr<base::SequencedTaskRunner> client_task_runner = + base::ThreadTaskRunnerHandle::Get(); + scoped_refptr<base::SequencedTaskRunner> background_task_runner = + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), net::GetCookieStoreBackgroundSequencePriority(), + base::TaskShutdownBehavior::BLOCK_SHUTDOWN}); + + net::CookieCryptoDelegate* crypto_delegate = nullptr; + if (params_->enable_encrypted_cookies) { +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && !BUILDFLAG(IS_CHROMECAST) + DCHECK(network_service_->os_crypt_config_set()) + << "NetworkService::SetCryptConfig must be called before creating a " + "NetworkContext with encrypted cookies."; +#endif + crypto_delegate = cookie_config::GetCookieCryptoDelegate(); + } + scoped_refptr<net::SQLitePersistentCookieStore> sqlite_store( + new net::SQLitePersistentCookieStore( + params_->cookie_path.value(), client_task_runner, + background_task_runner, params_->restore_old_session_cookies, + crypto_delegate)); + + return base::MakeRefCounted<SessionCleanupCookieStore>(sqlite_store); +} + void NetworkContext::OnHttpCacheCleared(ClearHttpCacheCallback callback, HttpCacheDataRemover* remover) { bool removed = false; @@ -2345,7 +2376,7 @@ void NetworkContext::CanUploadDomainReliability( std::move(callback))); } -void NetworkContext::OnCertVerifyForSignedExchangeComplete(int cert_verify_id, +void NetworkContext::OnVerifyCertForSignedExchangeComplete(int cert_verify_id, int result) { auto iter = cert_verifier_requests_.find(cert_verify_id); DCHECK(iter != cert_verifier_requests_.end()); @@ -2353,7 +2384,6 @@ void NetworkContext::OnCertVerifyForSignedExchangeComplete(int cert_verify_id, auto pending_cert_verify = std::move(iter->second); cert_verifier_requests_.erase(iter); - net::ct::CTVerifyResult ct_verify_result; #if BUILDFLAG(IS_CT_SUPPORTED) if (result == net::OK) { net::X509Certificate* verified_cert = @@ -2361,15 +2391,17 @@ void NetworkContext::OnCertVerifyForSignedExchangeComplete(int cert_verify_id, url_request_context_->cert_transparency_verifier()->Verify( pending_cert_verify->url.host(), verified_cert, pending_cert_verify->ocsp_result, pending_cert_verify->sct_list, - &ct_verify_result.scts, + &pending_cert_verify->result->scts, net::NetLogWithSource::Make( network_service_ ? url_request_context_->net_log() : nullptr, net::NetLogSourceType::CERT_VERIFIER_JOB)); - net::ct::SCTList verified_scts = net::ct::SCTsMatchingStatus( - ct_verify_result.scts, net::ct::SCT_STATUS_OK); - - ct_verify_result.policy_compliance = + net::ct::SCTList verified_scts; + for (const auto& sct_and_status : pending_cert_verify->result->scts) { + if (sct_and_status.status == net::ct::SCT_STATUS_OK) + verified_scts.push_back(sct_and_status.sct); + } + pending_cert_verify->result->policy_compliance = url_request_context_->ct_policy_enforcer()->CheckCompliance( verified_cert, verified_scts, net::NetLogWithSource::Make( @@ -2379,34 +2411,32 @@ void NetworkContext::OnCertVerifyForSignedExchangeComplete(int cert_verify_id, // TODO(https://crbug.com/803774): We should determine whether EV & SXG // should be a thing (due to the online/offline signing difference) if (pending_cert_verify->result->cert_status & net::CERT_STATUS_IS_EV && - ct_verify_result.policy_compliance != + pending_cert_verify->result->policy_compliance != net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS && - ct_verify_result.policy_compliance != + pending_cert_verify->result->policy_compliance != net::ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) { pending_cert_verify->result->cert_status |= net::CERT_STATUS_CT_COMPLIANCE_FAILED; pending_cert_verify->result->cert_status &= ~net::CERT_STATUS_IS_EV; } - // TODO(https://crbug.com/1087091): Update - // NetworkContext::VerifyCertForSignedExchange() to take a - // NetworkIsolationKey, and pass it in here. net::TransportSecurityState::CTRequirementsStatus ct_requirement_status = url_request_context_->transport_security_state()->CheckCTRequirements( net::HostPortPair::FromURL(pending_cert_verify->url), pending_cert_verify->result->is_issued_by_known_root, pending_cert_verify->result->public_key_hashes, verified_cert, - pending_cert_verify->certificate.get(), ct_verify_result.scts, + pending_cert_verify->certificate.get(), + pending_cert_verify->result->scts, net::TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, - ct_verify_result.policy_compliance, - net::NetworkIsolationKey::Todo()); + pending_cert_verify->result->policy_compliance, + pending_cert_verify->network_isolation_key); if (url_request_context_->sct_auditing_delegate() && url_request_context_->sct_auditing_delegate()->IsSCTAuditingEnabled() && pending_cert_verify->result->is_issued_by_known_root) { url_request_context_->sct_auditing_delegate()->MaybeEnqueueReport( net::HostPortPair::FromURL(pending_cert_verify->url), verified_cert, - ct_verify_result.scts); + pending_cert_verify->result->scts); } switch (ct_requirement_status) { @@ -2414,26 +2444,22 @@ void NetworkContext::OnCertVerifyForSignedExchangeComplete(int cert_verify_id, result = net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED; break; case net::TransportSecurityState::CT_REQUIREMENTS_MET: - ct_verify_result.policy_compliance_required = true; break; case net::TransportSecurityState::CT_NOT_REQUIRED: // CT is not required if the certificate does not chain to a publicly // trusted root certificate. - if (!pending_cert_verify->result->is_issued_by_known_root) { - ct_verify_result.policy_compliance_required = false; + if (!pending_cert_verify->result->is_issued_by_known_root) break; - } // For old certificates (issued before 2018-05-01), // CheckCTRequirements() may return CT_NOT_REQUIRED, so we check the // compliance status here. // TODO(https://crbug.com/851778): Remove this condition once we require // signing certificates to have CanSignHttpExchanges extension, because // such certificates should be naturally after 2018-05-01. - if (ct_verify_result.policy_compliance == + if (pending_cert_verify->result->policy_compliance == net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS || - ct_verify_result.policy_compliance == + pending_cert_verify->result->policy_compliance == net::ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) { - ct_verify_result.policy_compliance_required = true; break; } // Require CT compliance, by overriding CT_NOT_REQUIRED and treat it as @@ -2444,10 +2470,10 @@ void NetworkContext::OnCertVerifyForSignedExchangeComplete(int cert_verify_id, #endif // BUILDFLAG(IS_CT_SUPPORTED) std::move(pending_cert_verify->callback) - .Run(result, *pending_cert_verify->result.get(), ct_verify_result); + .Run(result, *pending_cert_verify->result.get()); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void NetworkContext::TrustAnchorUsed() { client_->OnTrustAnchorUsed(); } diff --git a/chromium/services/network/network_context.h b/chromium/services/network/network_context.h index e1a8746bcda..c324481d155 100644 --- a/chromium/services/network/network_context.h +++ b/chromium/services/network/network_context.h @@ -23,12 +23,14 @@ #include "base/optional.h" #include "base/time/time.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/base/big_buffer.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/unique_receiver_set.h" +#include "net/base/network_isolation_key.h" #include "net/cert/cert_verifier.h" #include "net/cert/cert_verify_result.h" #include "net/dns/host_resolver.h" @@ -57,7 +59,7 @@ #include "services/network/socket_factory.h" #include "services/network/url_request_context_owner.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "crypto/scoped_nss_types.h" #endif @@ -89,17 +91,18 @@ class CertVerifierWithTrustAnchors; class CookieManager; class ExpectCTReporter; class HostResolver; +class MdnsResponderManager; class NetworkService; class NetworkServiceNetworkDelegate; class NetworkServiceProxyDelegate; -class MdnsResponderManager; class P2PSocketManager; +class PendingTrustTokenStore; class ProxyLookupRequest; class QuicTransport; class ResourceScheduler; class ResourceSchedulerClient; +class SessionCleanupCookieStore; class SQLiteTrustTokenPersister; -class PendingTrustTokenStore; class WebSocketFactory; namespace cors { @@ -217,7 +220,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ComputeHttpCacheSizeCallback callback) override; void NotifyExternalCacheHit(const GURL& url, const std::string& http_method, - const net::NetworkIsolationKey& key) override; + const net::NetworkIsolationKey& key, + bool is_subframe_document_resource) override; void ClearHostCache(mojom::ClearDataFilterPtr filter, ClearHostCacheCallback callback) override; void ClearHttpAuthCache(base::Time start_time, @@ -243,7 +247,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext mojom::NetworkConditionsPtr conditions) override; void SetAcceptLanguage(const std::string& new_accept_language) override; void SetEnableReferrers(bool enable_referrers) override; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void UpdateAdditionalCertificates( mojom::AdditionalCertificatesPtr additional_certificates) override; #endif @@ -333,6 +337,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext void VerifyCertForSignedExchange( const scoped_refptr<net::X509Certificate>& certificate, const GURL& url, + const net::NetworkIsolationKey& network_isolation_key, const std::string& ocsp_result, const std::string& sct_list, VerifyCertForSignedExchangeCallback callback) override; @@ -380,10 +385,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext void QueueReport(const std::string& type, const std::string& group, const GURL& url, + const net::NetworkIsolationKey& network_isolation_key, const base::Optional<std::string>& user_agent, base::Value body) override; void QueueSignedExchangeReport( - mojom::SignedExchangeReportPtr report) override; + mojom::SignedExchangeReportPtr report, + const net::NetworkIsolationKey& network_isolation_key) override; void AddDomainReliabilityContextForTesting( const GURL& origin, const GURL& upload_url, @@ -407,7 +414,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext const GURL& url, const net::NetworkIsolationKey& network_isolation_key, LookupServerBasicAuthCredentialsCallback callback) override; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void LookupProxyAuthCredentials( const net::ProxyServer& proxy_server, const std::string& auth_scheme, @@ -515,7 +522,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext private: URLRequestContextOwner MakeURLRequestContext( mojo::PendingRemote<mojom::URLLoaderFactory> - url_loader_factory_for_cert_net_fetcher); + url_loader_factory_for_cert_net_fetcher, + scoped_refptr<SessionCleanupCookieStore>); + scoped_refptr<SessionCleanupCookieStore> MakeSessionCleanupCookieStore() + const; // Invoked when the HTTP cache was cleared. Invokes |callback|. void OnHttpCacheCleared(ClearHttpCacheCallback callback, @@ -540,9 +550,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext void CanUploadDomainReliability(const GURL& origin, base::OnceCallback<void(bool)> callback); - void OnCertVerifyForSignedExchangeComplete(int cert_verify_id, int result); + void OnVerifyCertForSignedExchangeComplete(int cert_verify_id, int result); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void TrustAnchorUsed(); #endif @@ -669,7 +679,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext bool is_sct_auditing_enabled_ = false; #endif // BUILDFLAG(IS_CT_SUPPORTED) -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) CertVerifierWithTrustAnchors* cert_verifier_with_trust_anchors_ = nullptr; #endif @@ -695,6 +705,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext struct PendingCertVerify { PendingCertVerify(); ~PendingCertVerify(); + // CertVerifyResult must be freed after the Request has been destructed. // So |result| must be written before |request|. std::unique_ptr<net::CertVerifyResult> result; @@ -702,6 +713,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext VerifyCertForSignedExchangeCallback callback; scoped_refptr<net::X509Certificate> certificate; GURL url; + net::NetworkIsolationKey network_isolation_key; std::string ocsp_result; std::string sct_list; }; diff --git a/chromium/services/network/network_context_unittest.cc b/chromium/services/network/network_context_unittest.cc index e7b36864f11..49bd1fa1c1a 100644 --- a/chromium/services/network/network_context_unittest.cc +++ b/chromium/services/network/network_context_unittest.cc @@ -13,7 +13,7 @@ #include "base/barrier_closure.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/containers/span.h" #include "base/files/file.h" @@ -32,7 +32,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/waitable_event.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/gtest_util.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/mock_entropy_provider.h" @@ -45,6 +45,7 @@ #include "base/time/default_tick_clock.h" #include "base/time/time.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "components/network_session_configurator/browser/network_session_configurator.h" #include "components/network_session_configurator/common/network_switches.h" #include "components/prefs/testing_pref_service.h" @@ -71,6 +72,7 @@ #include "net/cookies/cookie_options.h" #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_util.h" +#include "net/disk_cache/cache_util.h" #include "net/disk_cache/disk_cache.h" #include "net/dns/context_host_resolver.h" #include "net/dns/dns_test_util.h" @@ -153,9 +155,9 @@ #include "net/reporting/reporting_test_util.h" #endif // BUILDFLAG(ENABLE_REPORTING) -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "services/network/mock_mojo_dhcp_wpad_url_client.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) namespace network { @@ -231,7 +233,7 @@ std::unique_ptr<TestURLLoaderClient> FetchRequest( // NIK must be consistent with |site_for_cookies|. if (request.site_for_cookies.IsNull()) { params->isolation_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, + net::IsolationInfo::RequestType::kOther, url::Origin::Create(GURL("https://abc.com")), url::Origin::Create(GURL("https://xyz.com")), request.site_for_cookies); } else { @@ -910,6 +912,67 @@ TEST_F(NetworkContextTest, DiskCache) { GetBackendType(backend)); } +class DiskCacheSizeTest : public NetworkContextTest { + public: + DiskCacheSizeTest() = default; + ~DiskCacheSizeTest() override = default; + + int64_t VerifyDiskCacheSize(int scale = 100) { + base::test::ScopedFeatureList scoped_feature_list; + if (scale != 100) { + std::map<std::string, std::string> field_trial_params; + field_trial_params["percent_relative_size"] = base::NumberToString(scale); + scoped_feature_list.InitAndEnableFeatureWithParameters( + disk_cache::kChangeDiskCacheSizeExperiment, field_trial_params); + } + + base::HistogramTester histogram_tester; + + mojom::NetworkContextParamsPtr context_params = CreateContextParams(); + context_params->http_cache_enabled = true; + + base::ScopedTempDir temp_dir; + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + context_params->http_cache_path = temp_dir.GetPath(); + + std::unique_ptr<NetworkContext> network_context = + CreateContextWithParams(std::move(context_params)); + + net::HttpCache* cache = network_context->url_request_context() + ->http_transaction_factory() + ->GetCache(); + EXPECT_TRUE(cache); + + disk_cache::Backend* backend = nullptr; + net::TestCompletionCallback callback; + int rv = cache->GetBackend(&backend, callback.callback()); + EXPECT_EQ(net::OK, callback.GetResult(rv)); + EXPECT_TRUE(backend); + + EXPECT_EQ(net::DISK_CACHE, backend->GetCacheType()); + + int64_t max_file_size = backend->MaxFileSize(); + histogram_tester.ExpectTotalCount("HttpCache.MaxFileSizeOnInit", 1); + histogram_tester.ExpectUniqueSample("HttpCache.MaxFileSizeOnInit", + max_file_size / 1024, 1); + + return max_file_size; + } +}; + +TEST_F(DiskCacheSizeTest, DiskCacheSize) { + int64_t max_file_size = VerifyDiskCacheSize(); + + int64_t max_file_size_scaled = VerifyDiskCacheSize(200); + + // After scaling to 200%, the size will in most cases be twice of + // |max_file_size| but it is dependent on the available size, and since we + // cannot guarantee available size to be the same between the 2 runs to + // VerifyDiskCacheSize(), only checking for the scaled size to be >= + // max_file_size. + EXPECT_GE(max_file_size_scaled, max_file_size); +} + // This makes sure that network_session_configurator::ChooseCacheType is // connected to NetworkContext. TEST_F(NetworkContextTest, SimpleCache) { @@ -1548,7 +1611,9 @@ TEST_F(NetworkContextTest, NotifyExternalCacheHit) { GURL test_url(entry_urls[i]); net::NetworkIsolationKey key; - network_context->NotifyExternalCacheHit(test_url, test_url.scheme(), key); + network_context->NotifyExternalCacheHit( + test_url, test_url.scheme(), key, + false /* is_subframe_document_resource */); EXPECT_EQ(i + 1, mock_cache.disk_cache()->GetExternalCacheHits().size()); // Note: if this breaks check HttpCache::GenerateCacheKey() for changes. @@ -1585,12 +1650,22 @@ TEST_F(NetworkContextTest, NotifyExternalCacheHit_Split) { GURL test_url(entry_urls[i]); net::NetworkIsolationKey key = net::NetworkIsolationKey(origin_a, origin_a); - network_context->NotifyExternalCacheHit(test_url, test_url.scheme(), key); + + bool is_subframe_document_resource = false; + std::string subframe_prefix; + if (i / 2) { + is_subframe_document_resource = true; + subframe_prefix = "s_"; + } + + network_context->NotifyExternalCacheHit(test_url, test_url.scheme(), key, + is_subframe_document_resource); EXPECT_EQ(i + 1, mock_cache.disk_cache()->GetExternalCacheHits().size()); // Since this is splitting the cache, the key also includes the network - // isolation key. - EXPECT_EQ(base::StrCat({"_dk_", key.ToString(), " ", test_url.spec()}), + // isolation key and optionally, the subframe prefix. + EXPECT_EQ(base::StrCat({"_dk_", subframe_prefix, key.ToString(), " ", + test_url.spec()}), mock_cache.disk_cache()->GetExternalCacheHits().back()); } } @@ -1927,7 +2002,7 @@ TEST_F(NetworkContextTest, LookupServerBasicAuthCredentials) { EXPECT_FALSE(result.has_value()); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) base::Optional<net::AuthCredentials> GetProxyAuthCredentials( NetworkContext* network_context, const net::ProxyServer& proxy_server, @@ -2052,8 +2127,8 @@ TEST_F(NetworkContextTest, ClearReportingCacheReports) { reporting_service.get()); GURL domain("http://google.com"); - reporting_service->QueueReport(domain, "Mozilla/1.0", "group", "type", - nullptr, 0); + reporting_service->QueueReport(domain, net::NetworkIsolationKey(), + "Mozilla/1.0", "group", "type", nullptr, 0); std::vector<const net::ReportingReport*> reports; reporting_cache->GetReports(&reports); @@ -2081,12 +2156,12 @@ TEST_F(NetworkContextTest, ClearReportingCacheReportsWithFilter) { network_context->url_request_context()->set_reporting_service( reporting_service.get()); - GURL domain1("http://google.com"); - reporting_service->QueueReport(domain1, "Mozilla/1.0", "group", "type", - nullptr, 0); - GURL domain2("http://chromium.org"); - reporting_service->QueueReport(domain2, "Mozilla/1.0", "group", "type", - nullptr, 0); + GURL url1("http://google.com"); + reporting_service->QueueReport(url1, net::NetworkIsolationKey(), + "Mozilla/1.0", "group", "type", nullptr, 0); + GURL url2("http://chromium.org"); + reporting_service->QueueReport(url2, net::NetworkIsolationKey(), + "Mozilla/1.0", "group", "type", nullptr, 0); std::vector<const net::ReportingReport*> reports; reporting_cache->GetReports(&reports); @@ -2103,7 +2178,7 @@ TEST_F(NetworkContextTest, ClearReportingCacheReportsWithFilter) { reporting_cache->GetReports(&reports); EXPECT_EQ(1u, reports.size()); - EXPECT_EQ(domain2, reports.front()->url); + EXPECT_EQ(url2, reports.front()->url); } TEST_F(NetworkContextTest, @@ -2120,12 +2195,12 @@ TEST_F(NetworkContextTest, network_context->url_request_context()->set_reporting_service( reporting_service.get()); - GURL domain1("http://192.168.0.1"); - reporting_service->QueueReport(domain1, "Mozilla/1.0", "group", "type", - nullptr, 0); - GURL domain2("http://192.168.0.2"); - reporting_service->QueueReport(domain2, "Mozilla/1.0", "group", "type", - nullptr, 0); + GURL url1("http://192.168.0.1"); + reporting_service->QueueReport(url1, net::NetworkIsolationKey(), + "Mozilla/1.0", "group", "type", nullptr, 0); + GURL url2("http://192.168.0.2"); + reporting_service->QueueReport(url2, net::NetworkIsolationKey(), + "Mozilla/1.0", "group", "type", nullptr, 0); std::vector<const net::ReportingReport*> reports; reporting_cache->GetReports(&reports); @@ -2142,7 +2217,7 @@ TEST_F(NetworkContextTest, reporting_cache->GetReports(&reports); EXPECT_EQ(1u, reports.size()); - EXPECT_EQ(domain2, reports.front()->url); + EXPECT_EQ(url2, reports.front()->url); } TEST_F(NetworkContextTest, ClearEmptyReportingCacheReports) { @@ -2307,18 +2382,19 @@ TEST_F(NetworkContextTest, ClearNetworkErrorLogging) { ASSERT_TRUE(logging_service); GURL domain("https://google.com"); - logging_service->OnHeader(url::Origin::Create(domain), + logging_service->OnHeader(net::NetworkIsolationKey(), + url::Origin::Create(domain), net::IPAddress(192, 168, 0, 1), "{\"report_to\":\"group\",\"max_age\":86400}"); - ASSERT_EQ(1u, logging_service->GetPolicyOriginsForTesting().size()); + ASSERT_EQ(1u, logging_service->GetPolicyKeysForTesting().size()); base::RunLoop run_loop; network_context->ClearNetworkErrorLogging(nullptr /* filter */, run_loop.QuitClosure()); run_loop.Run(); - EXPECT_TRUE(logging_service->GetPolicyOriginsForTesting().empty()); + EXPECT_TRUE(logging_service->GetPolicyKeysForTesting().empty()); } TEST_F(NetworkContextTest, ClearNetworkErrorLoggingWithFilter) { @@ -2332,15 +2408,17 @@ TEST_F(NetworkContextTest, ClearNetworkErrorLoggingWithFilter) { ASSERT_TRUE(logging_service); GURL domain1("https://google.com"); - logging_service->OnHeader(url::Origin::Create(domain1), + logging_service->OnHeader(net::NetworkIsolationKey(), + url::Origin::Create(domain1), net::IPAddress(192, 168, 0, 1), "{\"report_to\":\"group\",\"max_age\":86400}"); GURL domain2("https://chromium.org"); - logging_service->OnHeader(url::Origin::Create(domain2), + logging_service->OnHeader(net::NetworkIsolationKey(), + url::Origin::Create(domain2), net::IPAddress(192, 168, 0, 1), "{\"report_to\":\"group\",\"max_age\":86400}"); - ASSERT_EQ(2u, logging_service->GetPolicyOriginsForTesting().size()); + ASSERT_EQ(2u, logging_service->GetPolicyKeysForTesting().size()); mojom::ClearDataFilterPtr filter = mojom::ClearDataFilter::New(); filter->type = mojom::ClearDataFilter_Type::KEEP_MATCHES; @@ -2351,11 +2429,13 @@ TEST_F(NetworkContextTest, ClearNetworkErrorLoggingWithFilter) { run_loop.QuitClosure()); run_loop.Run(); - std::set<url::Origin> policy_origins = - logging_service->GetPolicyOriginsForTesting(); - EXPECT_EQ(1u, policy_origins.size()); - EXPECT_NE(policy_origins.end(), - policy_origins.find(url::Origin::Create(domain2))); + std::set<net::NetworkErrorLoggingService::NelPolicyKey> policy_keys = + logging_service->GetPolicyKeysForTesting(); + EXPECT_EQ(1u, policy_keys.size()); + EXPECT_THAT( + policy_keys, + testing::ElementsAre(net::NetworkErrorLoggingService::NelPolicyKey( + net::NetworkIsolationKey(), url::Origin::Create(domain2)))); } TEST_F(NetworkContextTest, ClearEmptyNetworkErrorLogging) { @@ -2368,14 +2448,14 @@ TEST_F(NetworkContextTest, ClearEmptyNetworkErrorLogging) { network_context->url_request_context()->network_error_logging_service(); ASSERT_TRUE(logging_service); - ASSERT_TRUE(logging_service->GetPolicyOriginsForTesting().empty()); + ASSERT_TRUE(logging_service->GetPolicyKeysForTesting().empty()); base::RunLoop run_loop; network_context->ClearNetworkErrorLogging(nullptr /* filter */, run_loop.QuitClosure()); run_loop.Run(); - EXPECT_TRUE(logging_service->GetPolicyOriginsForTesting().empty()); + EXPECT_TRUE(logging_service->GetPolicyKeysForTesting().empty()); } TEST_F(NetworkContextTest, ClearEmptyNetworkErrorLoggingWithNoService) { @@ -2423,7 +2503,7 @@ bool SetCookieHelper(NetworkContext* network_context, net::CanonicalCookie(key, value, url.host(), "/", base::Time(), base::Time(), base::Time(), true, false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_LOW), + net::COOKIE_PRIORITY_LOW, false), url, net::CookieOptions::MakeAllInclusive(), base::BindOnce(&SetCookieCallback, &run_loop, &result)); run_loop.Run(); @@ -2444,7 +2524,7 @@ TEST_F(NetworkContextTest, CookieManager) { net::CanonicalCookie cookie("TestCookie", "1", "www.test.com", "/", base::Time(), base::Time(), base::Time(), false, false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_LOW); + net::COOKIE_PRIORITY_LOW, false); cookie_manager_remote->SetCanonicalCookie( cookie, net::cookie_util::SimulatedCookieSource(cookie, "https"), net::CookieOptions::MakeAllInclusive(), @@ -2722,11 +2802,11 @@ TEST_F(NetworkContextTest, ProxyLookupWithNetworkIsolationKey) { context_params->proxy_config_client_receiver = config_client.BindNewPipeAndPassReceiver(); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) context_params->dhcp_wpad_url_client = network::MockMojoDhcpWpadUrlClient::CreateWithSelfOwnedReceiver( std::string()); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) std::unique_ptr<NetworkContext> network_context = CreateContextWithParams(std::move(context_params)); @@ -2819,11 +2899,11 @@ TEST_F(NetworkContextTest, PacQuickCheck) { // unsupported platforms, we'd simply ignore the PAC quick check input and // default to false. mojom::NetworkContextParamsPtr context_params = CreateContextParams(); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) context_params->dhcp_wpad_url_client = network::MockMojoDhcpWpadUrlClient::CreateWithSelfOwnedReceiver( std::string()); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) context_params->proxy_resolver_factory = MockMojoProxyResolverFactory::Create(); std::unique_ptr<NetworkContext> network_context = @@ -2837,11 +2917,11 @@ TEST_F(NetworkContextTest, PacQuickCheck) { // Explicitly enable. context_params = CreateContextParams(); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) context_params->dhcp_wpad_url_client = network::MockMojoDhcpWpadUrlClient::CreateWithSelfOwnedReceiver( std::string()); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) context_params->proxy_resolver_factory = MockMojoProxyResolverFactory::Create(); context_params->pac_quick_check_enabled = true; @@ -2855,11 +2935,11 @@ TEST_F(NetworkContextTest, PacQuickCheck) { // Explicitly disable. context_params = CreateContextParams(); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) context_params->dhcp_wpad_url_client = network::MockMojoDhcpWpadUrlClient::CreateWithSelfOwnedReceiver( std::string()); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) context_params->proxy_resolver_factory = MockMojoProxyResolverFactory::Create(); context_params->pac_quick_check_enabled = false; @@ -3730,11 +3810,11 @@ TEST_F(NetworkContextTest, CreateHostResolverWithConfigOverrides) { net::IPAddress result; CHECK(result.AssignFromIPLiteral(kResult)); net::MockDnsClientRuleList rules; - rules.emplace_back(kQueryHostname, net::dns_protocol::kTypeA, - false /* secure */, - net::MockDnsClientRule::Result( - net::BuildTestDnsResponse(kQueryHostname, result)), - false /* delay */); + rules.emplace_back( + kQueryHostname, net::dns_protocol::kTypeA, false /* secure */, + net::MockDnsClientRule::Result( + net::BuildTestDnsAddressResponse(kQueryHostname, result)), + false /* delay */); rules.emplace_back( kQueryHostname, net::dns_protocol::kTypeAAAA, false /* secure */, net::MockDnsClientRule::Result(net::MockDnsClientRule::ResultType::EMPTY), @@ -3911,7 +3991,7 @@ TEST_F(NetworkContextTest, CanSetCookieFalseIfCookiesBlocked) { net::CanonicalCookie cookie("TestCookie", "1", "www.test.com", "/", base::Time(), base::Time(), base::Time(), false, false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_LOW); + net::COOKIE_PRIORITY_LOW, false); EXPECT_TRUE( network_context->url_request_context()->network_delegate()->CanSetCookie( *request, cookie, nullptr, true)); @@ -3931,7 +4011,7 @@ TEST_F(NetworkContextTest, CanSetCookieTrueIfCookiesAllowed) { net::CanonicalCookie cookie("TestCookie", "1", "www.test.com", "/", base::Time(), base::Time(), base::Time(), false, false, net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_LOW); + net::COOKIE_PRIORITY_LOW, false); SetDefaultContentSetting(CONTENT_SETTING_ALLOW, network_context.get()); EXPECT_TRUE( @@ -5061,11 +5141,11 @@ TEST_F(NetworkContextTest, ProxyErrorClientNotifiedOfPacError) { mojom::NetworkContextParams::New(); context_params->proxy_error_client = proxy_error_client.CreateRemote(); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) context_params->dhcp_wpad_url_client = network::MockMojoDhcpWpadUrlClient::CreateWithSelfOwnedReceiver( std::string()); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) // The PAC URL doesn't matter, since the test is configured to use a // mock ProxyResolverFactory which doesn't actually evaluate it. It just @@ -6443,8 +6523,8 @@ class NetworkContextSplitCacheTest : public NetworkContextTest { auto params = mojom::URLLoaderFactoryParams::New(); params->process_id = mojom::kBrowserProcessId; params->is_corb_enabled = false; - if (isolation_info.redirect_mode() == - net::IsolationInfo::RedirectMode::kUpdateNothing) { + if (isolation_info.request_type() == + net::IsolationInfo::RequestType::kOther) { params->isolation_info = isolation_info; } else { request.trusted_params = ResourceRequest::TrustedParams(); @@ -6513,18 +6593,18 @@ TEST_F(NetworkContextSplitCacheTest, NavigationResourceCachedUsingNetworkIsolationKey) { GURL url = test_server()->GetURL("othersite.test", "/main.html"); url::Origin origin_a = url::Origin::Create(url); - net::IsolationInfo info_a = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateFrameOnly, origin_a, origin_a, - net::SiteForCookies()); + net::IsolationInfo info_a = + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kSubFrame, + origin_a, origin_a, net::SiteForCookies()); LoadAndVerifyCached(url, info_a, false /* was_cached */); // Load again with a different isolation key. The cached entry should not be // loaded. GURL url_b = test_server()->GetURL("/main.html"); url::Origin origin_b = url::Origin::Create(url_b); - net::IsolationInfo info_b = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateFrameOnly, origin_b, origin_b, - net::SiteForCookies()); + net::IsolationInfo info_b = + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kSubFrame, + origin_b, origin_b, net::SiteForCookies()); LoadAndVerifyCached(url_b, info_b, false /* was_cached */); // Load again with the same isolation key. The cached entry should be loaded. @@ -6541,17 +6621,17 @@ TEST_F(NetworkContextSplitCacheTest, GURL url = test_server()->GetURL("/resource"); url::Origin origin_a = url::Origin::Create(GURL("http://a.test/")); - net::IsolationInfo info_a = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, origin_a, origin_a, - net::SiteForCookies()); + net::IsolationInfo info_a = + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + origin_a, origin_a, net::SiteForCookies()); LoadAndVerifyCached(url, info_a, false /* was_cached */); // Load again with a different isolation key. The cached entry should not be // loaded. url::Origin origin_b = url::Origin::Create(GURL("http://b.test/")); - net::IsolationInfo info_b = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, origin_a, origin_b, - net::SiteForCookies()); + net::IsolationInfo info_b = + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + origin_a, origin_b, net::SiteForCookies()); LoadAndVerifyCached(url, info_b, false /* was_cached */); } @@ -6563,7 +6643,7 @@ TEST_F(NetworkContextSplitCacheTest, test_server()->GetURL("othersite.test", "/title1.html").spec()); url::Origin origin = url::Origin::Create(url); net::IsolationInfo info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateTopFrame, origin, origin, + net::IsolationInfo::RequestType::kMainFrame, origin, origin, net::SiteForCookies::FromOrigin(origin)); LoadAndVerifyCached(url, info, false /* was_cached */, true /* expect_redirect */); @@ -6578,7 +6658,7 @@ TEST_F(NetworkContextSplitCacheTest, // A non-navigation resource with the same key and url should also be cached. net::IsolationInfo non_navigation_redirected_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, redirected_origin, + net::IsolationInfo::RequestType::kOther, redirected_origin, redirected_origin, net::SiteForCookies::FromOrigin(redirected_origin)); LoadAndVerifyCached(redirected_url, non_navigation_redirected_info, diff --git a/chromium/services/network/network_quality_estimator_manager.cc b/chromium/services/network/network_quality_estimator_manager.cc index 672fca5769e..e91eebe8c28 100644 --- a/chromium/services/network/network_quality_estimator_manager.cc +++ b/chromium/services/network/network_quality_estimator_manager.cc @@ -13,6 +13,7 @@ #include "base/command_line.h" #include "base/metrics/field_trial_params.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "net/base/features.h" #include "net/nqe/network_quality_estimator.h" #include "net/nqe/network_quality_estimator_params.h" @@ -84,7 +85,7 @@ NetworkQualityEstimatorManager::NetworkQualityEstimatorManager( network_quality_estimator_params), net_log); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // Get network id asynchronously to workaround https://crbug.com/821607 where // AddressTrackerLinux stucks with a recv() call and blocks IO thread. // TODO(https://crbug.com/821607): Remove after the bug is resolved. diff --git a/chromium/services/network/network_service.cc b/chromium/services/network/network_service.cc index da36edb0a52..4901703b899 100644 --- a/chromium/services/network/network_service.cc +++ b/chromium/services/network/network_service.cc @@ -24,16 +24,19 @@ #include "base/timer/timer.h" #include "base/values.h" #include "build/chromecast_buildflags.h" +#include "build/chromeos_buildflags.h" #include "components/network_session_configurator/common/network_features.h" #include "components/os_crypt/os_crypt.h" #include "mojo/public/cpp/bindings/scoped_message_error_crash_key.h" #include "mojo/public/cpp/system/functions.h" +#include "net/base/features.h" #include "net/base/logging_network_change_observer.h" #include "net/base/network_change_notifier.h" #include "net/base/network_change_notifier_posix.h" #include "net/base/port_util.h" #include "net/cert/cert_database.h" #include "net/cert/ct_log_response_parser.h" +#include "net/cert/internal/system_trust_store.h" #include "net/cert/signed_tree_head.h" #include "net/dns/host_resolver.h" #include "net/dns/host_resolver_manager.h" @@ -70,7 +73,7 @@ #include "third_party/boringssl/src/include/openssl/cpu.h" #endif -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && !BUILDFLAG(IS_CHROMECAST) +#if (defined(OS_LINUX) || BUILDFLAG(IS_LACROS)) && !BUILDFLAG(IS_CHROMECAST) #include "components/os_crypt/key_storage_config_linux.h" #endif @@ -321,6 +324,14 @@ void NetworkService::Initialize(mojom::NetworkServiceParamsPtr params, base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); +#if defined(OS_MAC) + if (!base::FeatureList::IsEnabled(network::features::kCertVerifierService) && + base::FeatureList::IsEnabled( + net::features::kCertVerifierBuiltinFeature)) { + net::InitializeTrustStoreMacCache(); + } +#endif + // Set-up the global port overrides. if (command_line->HasSwitch(switches::kExplicitlyAllowedPorts)) { std::string allowed_ports = @@ -374,6 +385,10 @@ void NetworkService::Initialize(mojom::NetworkServiceParamsPtr params, trust_token_key_commitments_ = std::make_unique<TrustTokenKeyCommitments>(); preloaded_first_party_sets_ = std::make_unique<PreloadedFirstPartySets>(); + if (command_line->HasSwitch(switches::kUseFirstPartySet)) { + preloaded_first_party_sets_->SetManuallySpecifiedSet( + command_line->GetSwitchValueASCII(switches::kUseFirstPartySet)); + } #if BUILDFLAG(IS_CT_SUPPORTED) constexpr size_t kMaxSCTAuditingCacheEntries = 1024; @@ -442,7 +457,7 @@ void NetworkService::DeregisterNetworkContext(NetworkContext* network_context) { network_contexts_.erase(network_context); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void NetworkService::ReinitializeLogging(mojom::LoggingSettingsPtr settings) { logging::LoggingSettings logging_settings; logging_settings.logging_dest = settings->logging_dest; @@ -482,8 +497,8 @@ void NetworkService::StartNetLog(base::File file, constants->MergeDictionary(&client_constants); file_net_log_observer_ = net::FileNetLogObserver::CreateUnboundedPreExisting( - std::move(file), std::move(constants)); - file_net_log_observer_->StartObserving(net_log_, capture_mode); + std::move(file), capture_mode, std::move(constants)); + file_net_log_observer_->StartObserving(net_log_); } void NetworkService::AttachNetLogProxy( @@ -537,13 +552,6 @@ void NetworkService::ConfigureStubHostResolver( SplitString(features::kDnsOverHttpsUpgradeDisabledProvidersParam.Get(), ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - // Because SECURE mode does not allow any fallback, allow multiple retries as - // a quick hack to increase the timeout for these requests. - // TODO(crbug.com/1105138): Rethink the timeout logic to be less aggressive in - // cases where there is no fallback, without needing to make so many retries. - if (secure_dns_mode == net::SecureDnsMode::kSecure) - overrides.doh_attempts = 3; - host_resolver_manager_->SetDnsConfigOverrides(overrides); } @@ -670,7 +678,7 @@ void NetworkService::OnCertDBChanged() { net::CertDatabase::GetInstance()->NotifyObserversCertDBChanged(); } -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +#if defined(OS_LINUX) || BUILDFLAG(IS_LACROS) void NetworkService::SetCryptConfig(mojom::CryptConfigPtr crypt_config) { #if !BUILDFLAG(IS_CHROMECAST) DCHECK(!os_crypt_config_set_); diff --git a/chromium/services/network/network_service.h b/chromium/services/network/network_service.h index 21b8da7e572..239319f6469 100644 --- a/chromium/services/network/network_service.h +++ b/chromium/services/network/network_service.h @@ -23,6 +23,7 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -151,7 +152,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService // mojom::NetworkService implementation: void SetClient(mojo::PendingRemote<mojom::NetworkServiceClient> client, mojom::NetworkServiceParamsPtr params) override; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void ReinitializeLogging(mojom::LoggingSettingsPtr settings) override; #endif void StartNetLog(base::File file, @@ -196,7 +197,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService base::span<const uint8_t> config, mojom::NetworkService::UpdateLegacyTLSConfigCallback callback) override; void OnCertDBChanged() override; -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +#if defined(OS_LINUX) || BUILDFLAG(IS_LACROS) void SetCryptConfig(mojom::CryptConfigPtr crypt_config) override; #endif #if defined(OS_WIN) || defined(OS_MAC) @@ -278,6 +279,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService return legacy_tls_config_distributor_.get(); } + const PreloadedFirstPartySets* preloaded_first_party_sets() const { + return preloaded_first_party_sets_.get(); + } + bool os_crypt_config_set() const { return os_crypt_config_set_; } void set_host_resolver_factory_for_testing( diff --git a/chromium/services/network/network_service_network_delegate.cc b/chromium/services/network/network_service_network_delegate.cc index 8199b693b81..25e64eb7c66 100644 --- a/chromium/services/network/network_service_network_delegate.cc +++ b/chromium/services/network/network_service_network_delegate.cc @@ -194,9 +194,7 @@ bool NetworkServiceNetworkDelegate::OnCanGetCookies( ->cookie_settings() .IsCookieAccessAllowed(request.url(), request.site_for_cookies().RepresentativeUrl(), - request.isolation_info() - .network_isolation_key() - .GetTopFrameOrigin()); + request.isolation_info().top_frame_origin()); if (!allowed) return false; diff --git a/chromium/services/network/network_service_unittest.cc b/chromium/services/network/network_service_unittest.cc index d2d032a534e..0ba89c7c78e 100644 --- a/chromium/services/network/network_service_unittest.cc +++ b/chromium/services/network/network_service_unittest.cc @@ -17,11 +17,12 @@ #include "base/path_service.h" #include "base/run_loop.h" #include "base/strings/string_util.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "net/base/escape.h" #include "net/base/ip_address.h" #include "net/base/ip_endpoint.h" @@ -186,7 +187,7 @@ TEST_F(NetworkServiceTest, AuthDefaultParams) { #if BUILDFLAG(USE_KERBEROS) && !defined(OS_ANDROID) ASSERT_TRUE(GetNegotiateFactory(&network_context)); -#if defined(OS_POSIX) && !defined(OS_CHROMEOS) +#if defined(OS_POSIX) && !BUILDFLAG(IS_ASH) EXPECT_EQ("", GetNegotiateFactory(&network_context)->GetLibraryNameForTesting()); #endif @@ -1172,6 +1173,8 @@ TEST_F(NetworkServiceTestWithService, SetNetworkConditions) { ResourceRequest request; request.url = test_server()->GetURL("/nocache.html"); + request.request_initiator = + url::Origin::Create(GURL("https://initiator.example.com")); request.method = "GET"; StartLoadingURL(request, 0); @@ -1213,13 +1216,14 @@ TEST_F(NetworkServiceTestWithService, SetsTrustTokenKeyCommitments) { ASSERT_TRUE(service_->trust_token_key_commitments()); auto expectation = mojom::TrustTokenKeyCommitmentResult::New(); - ASSERT_TRUE(base::Base64Decode( - "aaaa", &expectation->signed_redemption_record_verification_key)); + expectation->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + expectation->id = 1; expectation->batch_size = 5; base::RunLoop run_loop; network_service_->SetTrustTokenKeyCommitments( - R"( { "https://issuer.example": { "batchsize": 5, "srrkey": "aaaa" } } )", + R"( { "https://issuer.example": { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5 } } )", run_loop.QuitClosure()); run_loop.Run(); diff --git a/chromium/services/network/origin_policy/DIR_METADATA b/chromium/services/network/origin_policy/DIR_METADATA new file mode 100644 index 00000000000..a53fa432f3e --- /dev/null +++ b/chromium/services/network/origin_policy/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Blink>SecurityFeature" +}
\ No newline at end of file diff --git a/chromium/services/network/origin_policy/OWNERS b/chromium/services/network/origin_policy/OWNERS index f6ee74b4eb9..9d3ad846610 100644 --- a/chromium/services/network/origin_policy/OWNERS +++ b/chromium/services/network/origin_policy/OWNERS @@ -1,5 +1,3 @@ andypaicu@chromium.org vogelheim@chromium.org mkwst@chromium.org - -# COMPONENT: Blink>SecurityFeature diff --git a/chromium/services/network/origin_policy/origin_policy_fetcher.cc b/chromium/services/network/origin_policy/origin_policy_fetcher.cc index 04593e577bc..76909140624 100644 --- a/chromium/services/network/origin_policy/origin_policy_fetcher.cc +++ b/chromium/services/network/origin_policy/origin_policy_fetcher.cc @@ -29,8 +29,8 @@ OriginPolicyFetcher::OriginPolicyFetcher( DCHECK(callback_); DCHECK(!isolation_info.IsEmpty()); // Policy requests shouldn't update frame origins on redirect. - DCHECK_EQ(net::IsolationInfo::RedirectMode::kUpdateNothing, - isolation_info.redirect_mode()); + DCHECK_EQ(net::IsolationInfo::RequestType::kOther, + isolation_info.request_type()); // While they use CredentialsMode::kOmit, so it shouldn't matter, policy // requests should have a null SiteForCookies. DCHECK(isolation_info.site_for_cookies().IsNull()); diff --git a/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc b/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc index 37a759cdda9..2aa762c7da8 100644 --- a/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc +++ b/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc @@ -51,9 +51,8 @@ class OriginPolicyManagerTest : public testing::Test { const base::Optional<std::string>& header) { manager_->RetrieveOriginPolicy( origin, - net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, origin, origin, - net::SiteForCookies()), + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + origin, origin, net::SiteForCookies()), header, base::BindOnce(&OriginPolicyManagerTest::Callback, base::Unretained(this))); diff --git a/chromium/services/network/p2p/DIR_METADATA b/chromium/services/network/p2p/DIR_METADATA new file mode 100644 index 00000000000..448c614f164 --- /dev/null +++ b/chromium/services/network/p2p/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Blink>WebRTC" +}
\ No newline at end of file diff --git a/chromium/services/network/p2p/OWNERS b/chromium/services/network/p2p/OWNERS index 90532e492dd..4e94c279ac6 100644 --- a/chromium/services/network/p2p/OWNERS +++ b/chromium/services/network/p2p/OWNERS @@ -1,5 +1,3 @@ guidou@chromium.org hta@chromium.org sergeyu@chromium.org - -# COMPONENT: Blink>WebRTC diff --git a/chromium/services/network/p2p/socket_tcp_server.cc b/chromium/services/network/p2p/socket_tcp_server.cc index f9dafef98aa..ab763bcea3b 100644 --- a/chromium/services/network/p2p/socket_tcp_server.cc +++ b/chromium/services/network/p2p/socket_tcp_server.cc @@ -7,7 +7,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "mojo/public/cpp/bindings/remote.h" #include "net/base/address_list.h" #include "net/base/net_errors.h" diff --git a/chromium/services/network/p2p/socket_tcp_unittest.cc b/chromium/services/network/p2p/socket_tcp_unittest.cc index dd1f75cb2a2..8cf4c8610af 100644 --- a/chromium/services/network/p2p/socket_tcp_unittest.cc +++ b/chromium/services/network/p2p/socket_tcp_unittest.cc @@ -11,7 +11,7 @@ #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/sys_byteorder.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "jingle/glue/fake_ssl_client_socket.h" diff --git a/chromium/services/network/p2p/socket_test_utils.cc b/chromium/services/network/p2p/socket_test_utils.cc index 663202e1b89..fc0af6ebe59 100644 --- a/chromium/services/network/p2p/socket_test_utils.cc +++ b/chromium/services/network/p2p/socket_test_utils.cc @@ -10,7 +10,7 @@ #include "base/check.h" #include "base/notreached.h" #include "base/sys_byteorder.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/threading/thread_task_runner_handle.h" #include "net/base/io_buffer.h" #include "net/base/ip_address.h" diff --git a/chromium/services/network/pending_callback_chain_unittest.cc b/chromium/services/network/pending_callback_chain_unittest.cc index d7a03a4147d..5cefd185fd8 100644 --- a/chromium/services/network/pending_callback_chain_unittest.cc +++ b/chromium/services/network/pending_callback_chain_unittest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "services/network/pending_callback_chain.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "testing/gtest/include/gtest/gtest.h" namespace network { diff --git a/chromium/services/network/proxy_resolver_factory_mojo_unittest.cc b/chromium/services/network/proxy_resolver_factory_mojo_unittest.cc index c863ee06f5f..d0f581ab44a 100644 --- a/chromium/services/network/proxy_resolver_factory_mojo_unittest.cc +++ b/chromium/services/network/proxy_resolver_factory_mojo_unittest.cc @@ -12,7 +12,7 @@ #include <vector> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/containers/queue.h" #include "base/run_loop.h" #include "base/stl_util.h" diff --git a/chromium/services/network/proxy_resolving_client_socket.cc b/chromium/services/network/proxy_resolving_client_socket.cc index c1fe895100c..8a02cc3117c 100644 --- a/chromium/services/network/proxy_resolving_client_socket.cc +++ b/chromium/services/network/proxy_resolving_client_socket.cc @@ -9,7 +9,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/check_op.h" #include "base/compiler_specific.h" #include "base/notreached.h" diff --git a/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc b/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc index f840843a062..6e0eb6421f6 100644 --- a/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc +++ b/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc @@ -9,7 +9,7 @@ #include "base/containers/span.h" #include "base/macros.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "jingle/glue/fake_ssl_client_socket.h" #include "mojo/public/cpp/bindings/pending_receiver.h" diff --git a/chromium/services/network/public/DIR_METADATA b/chromium/services/network/public/DIR_METADATA new file mode 100644 index 00000000000..1fd3fb96519 --- /dev/null +++ b/chromium/services/network/public/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Services>Network" +}
\ No newline at end of file diff --git a/chromium/services/network/public/OWNERS b/chromium/services/network/public/OWNERS deleted file mode 100644 index 06c2e2b8778..00000000000 --- a/chromium/services/network/public/OWNERS +++ /dev/null @@ -1 +0,0 @@ -# COMPONENT: Internals>Services>Network diff --git a/chromium/services/network/public/cpp/BUILD.gn b/chromium/services/network/public/cpp/BUILD.gn index 3e240ba3c7a..1ba78613e28 100644 --- a/chromium/services/network/public/cpp/BUILD.gn +++ b/chromium/services/network/public/cpp/BUILD.gn @@ -103,6 +103,10 @@ component("cpp") { "source_stream_to_data_pipe.h", "spki_hash_set.cc", "spki_hash_set.h", + "supports_loading_mode/supports_loading_mode_parser.cc", + "supports_loading_mode/supports_loading_mode_parser.h", + "trust_token_http_headers.cc", + "trust_token_http_headers.h", "trust_token_operation_authorization.h", "weak_wrapper_shared_url_loader_factory.cc", "weak_wrapper_shared_url_loader_factory.h", @@ -141,6 +145,7 @@ component("cpp") { deps = [ "//base", + "//build:chromeos_buildflags", "//components/prefs", "//ipc", "//services/proxy_resolver/public/mojom", @@ -199,6 +204,21 @@ component("cross_origin_embedder_policy") { defines = [ "IS_NETWORK_CPP_BASE_IMPL" ] } +# This component is separate from cpp_base as it is a dependency of +# //services/network/public/mojom:cookies_mojom. +component("schemeful_site_mojom_support") { + sources = [ + "schemeful_site_mojom_traits.cc", + "schemeful_site_mojom_traits.h", + ] + deps = [ + "//net", + "//services/network/public/mojom:mojom_schemeful_site_shared", + "//url/mojom:url_mojom_origin", + ] + defines = [ "IS_NETWORK_CPP_BASE_IMPL" ] +} + component("cpp_base") { output_name = "network_cpp_base" @@ -260,6 +280,7 @@ component("cpp_base") { ":crash_keys", ":cross_origin_embedder_policy", ":ip_address_mojom_support", + ":schemeful_site_mojom_support", "//services/network/public/mojom:url_loader_base", "//third_party/webrtc_overrides:webrtc_component", "//url/ipc:url_ipc", @@ -322,9 +343,11 @@ source_set("tests") { "optional_trust_token_params_unittest.cc", "origin_isolation_parser_unittest.cc", "proxy_config_mojom_traits_unittest.cc", + "schemeful_site_mojom_traits_unittest.cc", "simple_url_loader_unittest.cc", "site_for_cookies_mojom_traits_unittest.cc", "source_stream_to_data_pipe_unittest.cc", + "supports_loading_mode/supports_loading_mode_parser_unittest.cc", "url_request_mojom_traits_unittest.cc", "web_sandbox_flags_unittests.cc", ] diff --git a/chromium/services/network/public/cpp/OWNERS b/chromium/services/network/public/cpp/OWNERS index 0fecc91f126..3a19139e0a4 100644 --- a/chromium/services/network/public/cpp/OWNERS +++ b/chromium/services/network/public/cpp/OWNERS @@ -15,3 +15,6 @@ per-file cross_origin_resource_policy*=lukasza@chromium.org per-file cross_origin_opener_policy*=ahemery@chromium.org per-file cross_origin_opener_policy*=clamy@chromium.org per-file cross_origin_opener_policy*=pmeuleman@chromium.org + +# Files and features related to component:Internals>Network>TrustTokens +per-file trust_token*=file://services/network/trust_tokens/OWNERS diff --git a/chromium/services/network/public/cpp/cert_verifier/BUILD.gn b/chromium/services/network/public/cpp/cert_verifier/BUILD.gn index 61197dc6bd0..cf8e80d2d6f 100644 --- a/chromium/services/network/public/cpp/cert_verifier/BUILD.gn +++ b/chromium/services/network/public/cpp/cert_verifier/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//net/features.gni") # This target provides a net::CertVerifier that transparently proxies cert @@ -26,7 +27,7 @@ source_set("cert_verifier_creation") { "cert_verifier_creation.h", ] - if (is_chromeos) { + if (is_ash) { sources += [ "system_trust_store_provider_chromeos.cc", "system_trust_store_provider_chromeos.h", @@ -42,6 +43,7 @@ source_set("cert_verifier_creation") { deps = [ "//base", + "//build:chromeos_buildflags", "//net", "//services/network/public/mojom", ] diff --git a/chromium/services/network/public/cpp/cert_verifier/DIR_METADATA b/chromium/services/network/public/cpp/cert_verifier/DIR_METADATA new file mode 100644 index 00000000000..c97d1840b0a --- /dev/null +++ b/chromium/services/network/public/cpp/cert_verifier/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Network>Certificate" +}
\ No newline at end of file diff --git a/chromium/services/network/public/cpp/cert_verifier/OWNERS b/chromium/services/network/public/cpp/cert_verifier/OWNERS index 9c3919699d8..83e4ddc9348 100644 --- a/chromium/services/network/public/cpp/cert_verifier/OWNERS +++ b/chromium/services/network/public/cpp/cert_verifier/OWNERS @@ -4,5 +4,3 @@ per-file *_mojom_traits*.*=set noparent per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS per-file *.typemap=set noparent per-file *.typemap=file://ipc/SECURITY_OWNERS - -# COMPONENT: Internals>Network>Certificate diff --git a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.cc b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.cc index db4e5013aff..c1974d1533d 100644 --- a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.cc +++ b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.cc @@ -5,11 +5,12 @@ #include "services/network/public/cpp/cert_verifier/cert_verifier_creation.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "net/base/features.h" #include "net/cert_net/cert_net_fetcher_url_request.h" #include "net/net_buildflags.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "crypto/nss_util_internal.h" #include "net/cert/cert_verify_proc.h" #include "net/cert/cert_verify_proc_builtin.h" @@ -48,7 +49,7 @@ bool UsingBuiltinCertVerifier( } #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) scoped_refptr<net::CertVerifyProc> CreateCertVerifyProcForUser( scoped_refptr<net::CertNetFetcher> net_fetcher, crypto::ScopedPK11Slot user_public_slot) { @@ -64,7 +65,7 @@ scoped_refptr<net::CertVerifyProc> CreateCertVerifyProcWithoutUserSlots( std::move(net_fetcher), std::make_unique<SystemTrustStoreProviderChromeOS>()); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) } // namespace @@ -97,7 +98,7 @@ std::unique_ptr<net::CertVerifier> CreateCertVerifier( use_builtin_cert_verifier = false; #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) scoped_refptr<net::CertVerifyProc> verify_proc; if (!creation_params || creation_params->username_hash.empty()) { verify_proc = diff --git a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc index d43349ff7bb..b95701348c8 100644 --- a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc +++ b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc @@ -7,9 +7,9 @@ #include <map> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "net/base/test_completion_callback.h" diff --git a/chromium/services/network/public/cpp/client_hints.cc b/chromium/services/network/public/cpp/client_hints.cc index 0958d28b3ab..db8bb0d2315 100644 --- a/chromium/services/network/public/cpp/client_hints.cc +++ b/chromium/services/network/public/cpp/client_hints.cc @@ -73,8 +73,8 @@ const DecodeMap& GetDecodeMap() { } // namespace -base::Optional<std::vector<network::mojom::WebClientHintsType>> ParseAcceptCH( - const std::string& header) { +base::Optional<std::vector<network::mojom::WebClientHintsType>> +ParseClientHintsHeader(const std::string& header) { // Accept-CH is an sh-list of tokens; see: // https://httpwg.org/http-extensions/client-hints.html#rfc.section.3.1 base::Optional<net::structured_headers::List> maybe_list = diff --git a/chromium/services/network/public/cpp/client_hints.h b/chromium/services/network/public/cpp/client_hints.h index a811582df39..b7615cc4d5a 100644 --- a/chromium/services/network/public/cpp/client_hints.h +++ b/chromium/services/network/public/cpp/client_hints.h @@ -26,7 +26,8 @@ COMPONENT_EXPORT(NETWORK_CPP) extern const size_t kClientHintsMappingsCount; // failed and the header should be ignored; otherwise returns a (possibly // empty) list of hints to accept. base::Optional<std::vector<network::mojom::WebClientHintsType>> - COMPONENT_EXPORT(NETWORK_CPP) ParseAcceptCH(const std::string& header); + COMPONENT_EXPORT(NETWORK_CPP) + ParseClientHintsHeader(const std::string& header); // Tries to parse Accept-CH-Lifetime. Returns base::TimeDelta() if unsuccessful. base::TimeDelta COMPONENT_EXPORT(NETWORK_CPP) diff --git a/chromium/services/network/public/cpp/client_hints_unittest.cc b/chromium/services/network/public/cpp/client_hints_unittest.cc index 3a2c0bbf1be..ec36f4f7bd6 100644 --- a/chromium/services/network/public/cpp/client_hints_unittest.cc +++ b/chromium/services/network/public/cpp/client_hints_unittest.cc @@ -17,12 +17,12 @@ TEST(ClientHintsTest, ParseAcceptCH) { base::Optional<std::vector<network::mojom::WebClientHintsType>> result; // Empty is OK. - result = ParseAcceptCH(" "); + result = ParseClientHintsHeader(" "); ASSERT_TRUE(result.has_value()); EXPECT_TRUE(result.value().empty()); // Normal case. - result = ParseAcceptCH("device-memory, rtt, lang "); + result = ParseClientHintsHeader("device-memory, rtt, lang "); ASSERT_TRUE(result.has_value()); EXPECT_THAT( result.value(), @@ -31,12 +31,12 @@ TEST(ClientHintsTest, ParseAcceptCH) { network::mojom::WebClientHintsType::kLang)); // Must be a list of tokens, not other things. - result = ParseAcceptCH("\"device-memory\", \"rtt\", \"lang\""); + result = ParseClientHintsHeader("\"device-memory\", \"rtt\", \"lang\""); EXPECT_FALSE(result.has_value()); // Parameters to the tokens are ignored, as encourageed by structured headers // spec. - result = ParseAcceptCH("device-memory;resolution=GIB, rtt, lang"); + result = ParseClientHintsHeader("device-memory;resolution=GIB, rtt, lang"); ASSERT_TRUE(result.has_value()); EXPECT_THAT( result.value(), @@ -45,7 +45,8 @@ TEST(ClientHintsTest, ParseAcceptCH) { network::mojom::WebClientHintsType::kLang)); // Unknown tokens are fine, since this meant to be extensible. - result = ParseAcceptCH("device-memory, rtt, lang , nosuchtokenwhywhywhy"); + result = ParseClientHintsHeader( + "device-memory, rtt, lang , nosuchtokenwhywhywhy"); ASSERT_TRUE(result.has_value()); EXPECT_THAT( result.value(), @@ -58,7 +59,7 @@ TEST(ClientHintsTest, ParseAcceptCHCaseInsensitive) { base::Optional<std::vector<network::mojom::WebClientHintsType>> result; // Matching is case-insensitive. - result = ParseAcceptCH("Device-meMory, Rtt, lanG "); + result = ParseClientHintsHeader("Device-meMory, Rtt, lanG "); ASSERT_TRUE(result.has_value()); EXPECT_THAT( result.value(), diff --git a/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc b/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc index 030962d28e6..d69c1fc5eda 100644 --- a/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc +++ b/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc @@ -114,6 +114,45 @@ std::string ElideURLForReportViolation(const GURL& url) { return url.spec(); } +bool SupportedInReportOnly(CSPDirectiveName directive) { + switch (directive) { + case CSPDirectiveName::Sandbox: + case CSPDirectiveName::UpgradeInsecureRequests: + case CSPDirectiveName::TreatAsPublicAddress: + return false; + + case CSPDirectiveName::BaseURI: + case CSPDirectiveName::BlockAllMixedContent: + case CSPDirectiveName::ChildSrc: + case CSPDirectiveName::ConnectSrc: + case CSPDirectiveName::DefaultSrc: + case CSPDirectiveName::FontSrc: + case CSPDirectiveName::FormAction: + case CSPDirectiveName::FrameAncestors: + case CSPDirectiveName::FrameSrc: + case CSPDirectiveName::ImgSrc: + case CSPDirectiveName::ManifestSrc: + case CSPDirectiveName::MediaSrc: + case CSPDirectiveName::NavigateTo: + case CSPDirectiveName::ObjectSrc: + case CSPDirectiveName::PluginTypes: + case CSPDirectiveName::PrefetchSrc: + case CSPDirectiveName::ReportTo: + case CSPDirectiveName::ReportURI: + case CSPDirectiveName::RequireTrustedTypesFor: + case CSPDirectiveName::ScriptSrc: + case CSPDirectiveName::ScriptSrcAttr: + case CSPDirectiveName::ScriptSrcElem: + case CSPDirectiveName::StyleSrc: + case CSPDirectiveName::StyleSrcAttr: + case CSPDirectiveName::StyleSrcElem: + case CSPDirectiveName::TrustedTypes: + case CSPDirectiveName::Unknown: + case CSPDirectiveName::WorkerSrc: + return true; + }; +} + // Return the error message specific to one CSP |directive|. // $1: Blocked URL. // $2: Blocking policy. @@ -220,12 +259,27 @@ const GURL ExtractInnerURL(const GURL& url) { return GURL(url.path()); } -bool ShouldBypassContentSecurityPolicy(CSPContext* context, const GURL& url) { - if (url.SchemeIsFileSystem() || url.SchemeIsBlob()) { - return context->SchemeShouldBypassCSP(ExtractInnerURL(url).scheme()); - } else { - return context->SchemeShouldBypassCSP(url.scheme()); - } +std::string InnermostScheme(const GURL& url) { + if (url.SchemeIsFileSystem() || url.SchemeIsBlob()) + return ExtractInnerURL(url).scheme(); + return url.scheme(); +} + +// Extensions can load their own internal content into the document. They +// shouldn't be blocked by the document's CSP. +// +// There is an exception: CSP:frame-ancestors. This one is not about allowing a +// document to embed other resources. This is about being embedded. As such +// this shouldn't be bypassed. A document should be able to deny being embedded +// inside an extension. +// See https://crbug.com/1115590 +bool ShouldBypassContentSecurityPolicy(CSPContext* context, + CSPDirectiveName directive, + const GURL& url) { + if (directive == CSPDirectiveName::FrameAncestors) + return false; + + return context->SchemeShouldBypassCSP(InnermostScheme(url)); } // Parses a "Content-Security-Policy" header. @@ -753,6 +807,15 @@ void AddContentSecurityPolicyFromHeader(base::StringPiece header, continue; } + if (type == mojom::ContentSecurityPolicyType::kReport && + !SupportedInReportOnly(directive_name)) { + out->parsing_errors.emplace_back( + base::StringPrintf("The Content Security Policy directive '%s' is " + "ignored when delivered in a report-only policy.", + directive.first.as_string().c_str())); + continue; + } + switch (directive_name) { case CSPDirectiveName::BaseURI: case CSPDirectiveName::ChildSrc: @@ -784,7 +847,7 @@ void AddContentSecurityPolicyFromHeader(base::StringPiece header, { auto sandbox = ParseWebSandboxPolicy(directive.second, mojom::WebSandboxFlags::kNone); - out->sandbox = ~sandbox.flags; + out->sandbox = sandbox.flags; out->parsing_errors.emplace_back(std::move(sandbox.error_message)); } break; @@ -982,7 +1045,7 @@ bool CheckContentSecurityPolicy(const mojom::ContentSecurityPolicyPtr& policy, CSPContext* context, const mojom::SourceLocationPtr& source_location, bool is_form_submission) { - if (ShouldBypassContentSecurityPolicy(context, url)) + if (ShouldBypassContentSecurityPolicy(context, directive_name, url)) return true; // 'navigate-to' has no effect when doing a form submission and a diff --git a/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc b/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc index 39d8c14c4d0..1913361f19b 100644 --- a/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc +++ b/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc @@ -141,6 +141,17 @@ network::mojom::SourceLocationPtr SourceLocation() { return network::mojom::SourceLocation::New(); } +mojom::ContentSecurityPolicyPtr ParseOneCspReportOnly(std::string expression) { + scoped_refptr<net::HttpResponseHeaders> headers( + new net::HttpResponseHeaders("HTTP/1.1 200 OK")); + headers->SetHeader("Content-Security-Policy-Report-Only", expression); + std::vector<mojom::ContentSecurityPolicyPtr> policies; + AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"), + &policies); + CHECK_EQ(1u, policies.size()); + return std::move(policies[0]); +} + } // namespace TEST(ContentSecurityPolicy, ParseFrameAncestors) { @@ -1014,9 +1025,9 @@ TEST(ContentSecurityPolicy, ParseSandbox) { AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"), &policies); EXPECT_EQ(policies[0]->sandbox, - mojom::WebSandboxFlags::kDownloads | - mojom::WebSandboxFlags::kScripts | - mojom::WebSandboxFlags::kAutomaticFeatures); + ~mojom::WebSandboxFlags::kDownloads & + ~mojom::WebSandboxFlags::kScripts & + ~mojom::WebSandboxFlags::kAutomaticFeatures); } TEST(ContentSecurityPolicy, ParseSerializedSourceList) { @@ -1510,4 +1521,39 @@ TEST(ContentSecurityPolicy, SubsumesPluginTypes) { } } +TEST(ContentSecurityPolicy, InvalidPolicyInReportOnlySandbox) { + mojom::ContentSecurityPolicyPtr policy = ParseOneCspReportOnly("sandbox"); + + EXPECT_EQ(mojom::WebSandboxFlags::kNone, policy->sandbox); + ASSERT_EQ(1u, policy->parsing_errors.size()); + EXPECT_EQ( + "The Content Security Policy directive 'sandbox' is ignored when " + "delivered in a report-only policy.", + policy->parsing_errors[0]); +} + +TEST(ContentSecurityPolicy, InvalidPolicyInReportOnlyUpgradeInsecureRequest) { + mojom::ContentSecurityPolicyPtr policy = + ParseOneCspReportOnly("upgrade-insecure-requests"); + + EXPECT_FALSE(policy->upgrade_insecure_requests); + ASSERT_EQ(1u, policy->parsing_errors.size()); + EXPECT_EQ( + "The Content Security Policy directive 'upgrade-insecure-requests' is " + "ignored when delivered in a report-only policy.", + policy->parsing_errors[0]); +} + +TEST(ContentSecurityPolicy, InvalidPolicyInReportTreatAsPublicAddress) { + mojom::ContentSecurityPolicyPtr policy = + ParseOneCspReportOnly("treat-as-public-address"); + + EXPECT_FALSE(policy->treat_as_public_address); + ASSERT_EQ(1u, policy->parsing_errors.size()); + EXPECT_EQ( + "The Content Security Policy directive 'treat-as-public-address' is " + "ignored when delivered in a report-only policy.", + policy->parsing_errors[0]); +} + } // namespace network diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_context.cc b/chromium/services/network/public/cpp/content_security_policy/csp_context.cc index 563f7eb5f9a..ee5a5d548c5 100644 --- a/chromium/services/network/public/cpp/content_security_policy/csp_context.cc +++ b/chromium/services/network/public/cpp/content_security_policy/csp_context.cc @@ -39,9 +39,6 @@ bool CSPContext::IsAllowedByCsp(mojom::CSPDirectiveName directive_name, const mojom::SourceLocationPtr& source_location, CheckCSPDisposition check_csp_disposition, bool is_form_submission) { - if (SchemeShouldBypassCSP(url.scheme_piece())) - return true; - bool allow = true; for (const auto& policy : policies_) { if (ShouldCheckPolicy(policy, check_csp_disposition)) { diff --git a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc index 56e5c6f6089..215258c78ac 100644 --- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc +++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc @@ -343,6 +343,18 @@ bool StructTraits<network::mojom::CookieOptionsDataView, net::CookieOptions>:: else cookie_options->unset_return_excluded_cookies(); + base::Optional<std::vector<net::SchemefulSite>> mojo_full_party_context; + if (!mojo_options.ReadFullPartyContext(&mojo_full_party_context)) + return false; + base::Optional<std::set<net::SchemefulSite>> full_party_context; + if (mojo_full_party_context.has_value()) { + full_party_context.emplace(mojo_full_party_context->begin(), + mojo_full_party_context->end()); + if (mojo_full_party_context->size() != full_party_context->size()) + return false; + } + cookie_options->set_full_party_context(full_party_context); + return true; } @@ -390,11 +402,14 @@ bool StructTraits< if (!cookie.ReadSourceScheme(&source_scheme)) return false; - *out = net::CanonicalCookie(name, value, domain, path, creation_time, - expiry_time, last_access_time, cookie.secure(), - cookie.httponly(), site_restrictions, priority, - source_scheme); - return out->IsCanonical(); + auto cc = net::CanonicalCookie::FromStorage( + name, value, domain, path, creation_time, expiry_time, last_access_time, + cookie.secure(), cookie.httponly(), site_restrictions, priority, + cookie.same_party(), source_scheme, cookie.source_port()); + if (!cc) + return false; + *out = *cc; + return true; } bool StructTraits<network::mojom::CookieInclusionStatusDataView, diff --git a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h index 9baa054951b..cde54d9247c 100644 --- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h +++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h @@ -13,8 +13,13 @@ #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_inclusion_status.h" #include "net/cookies/cookie_options.h" +#include "services/network/public/cpp/schemeful_site_mojom_traits.h" #include "services/network/public/mojom/cookie_manager.mojom.h" +namespace net { +class SchemefulSite; +} // namespace net + namespace mojo { template <> @@ -110,6 +115,11 @@ struct StructTraits<network::mojom::CookieOptionsDataView, net::CookieOptions> { return o.return_excluded_cookies(); } + static const base::Optional<std::set<net::SchemefulSite>>& full_party_context( + const net::CookieOptions& o) { + return o.full_party_context(); + } + static bool Read(network::mojom::CookieOptionsDataView mojo_options, net::CookieOptions* cookie_options); }; @@ -149,6 +159,12 @@ struct StructTraits<network::mojom::CanonicalCookieDataView, static net::CookieSourceScheme source_scheme(const net::CanonicalCookie& c) { return c.SourceScheme(); } + static bool same_party(const net::CanonicalCookie& c) { + return c.IsSameParty(); + } + static int source_port(const net::CanonicalCookie& c) { + return c.SourcePort(); + } static bool Read(network::mojom::CanonicalCookieDataView cookie, net::CanonicalCookie* out); diff --git a/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc index 94a7557da24..639592a4392 100644 --- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc +++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc @@ -4,14 +4,18 @@ #include "services/network/public/cpp/cookie_manager_mojom_traits.h" +#include <set> #include <vector> #include "base/test/gtest_util.h" #include "mojo/public/cpp/base/time_mojom_traits.h" #include "mojo/public/cpp/test_support/test_utils.h" +#include "net/base/schemeful_site.h" +#include "net/cookies/cookie_constants.h" #include "services/network/public/cpp/cookie_manager_mojom_traits.h" #include "services/network/public/mojom/cookie_manager.mojom.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/third_party/mozilla/url_parse.h" namespace network { namespace { @@ -25,7 +29,8 @@ bool SerializeAndDeserializeEnum(NativeType in, NativeType* out) { TEST(CookieManagerTraitsTest, Roundtrips_CanonicalCookie) { net::CanonicalCookie original( "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false, - false, net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW); + false, net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW, + false, net::CookieSourceScheme::kSecure, 8433); net::CanonicalCookie copied; @@ -43,6 +48,33 @@ TEST(CookieManagerTraitsTest, Roundtrips_CanonicalCookie) { EXPECT_EQ(original.IsHttpOnly(), copied.IsHttpOnly()); EXPECT_EQ(original.SameSite(), copied.SameSite()); EXPECT_EQ(original.Priority(), copied.Priority()); + EXPECT_EQ(original.IsSameParty(), copied.IsSameParty()); + EXPECT_EQ(original.SourceScheme(), copied.SourceScheme()); + EXPECT_EQ(original.SourcePort(), copied.SourcePort()); + + // Test port edge cases: unspecified. + net::CanonicalCookie original_unspecified( + "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false, + false, net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW, + false, net::CookieSourceScheme::kSecure, url::PORT_UNSPECIFIED); + net::CanonicalCookie copied_unspecified; + + EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>( + &original_unspecified, &copied_unspecified)); + + EXPECT_EQ(original_unspecified.SourcePort(), copied_unspecified.SourcePort()); + + // Test port edge cases: invalid. + net::CanonicalCookie original_invalid( + "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false, + false, net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW, + false, net::CookieSourceScheme::kSecure, url::PORT_INVALID); + net::CanonicalCookie copied_invalid; + + EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>( + &original_invalid, &copied_invalid)); + + EXPECT_EQ(original_invalid.SourcePort(), copied_invalid.SourcePort()); // Serializer returns false if cookie is non-canonical. // Example is non-canonical because of newline in name. @@ -50,7 +82,7 @@ TEST(CookieManagerTraitsTest, Roundtrips_CanonicalCookie) { original = net::CanonicalCookie("A\n", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false, false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_LOW); + net::COOKIE_PRIORITY_LOW, false); EXPECT_FALSE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>( &original, &copied)); @@ -119,7 +151,7 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieWithAccessResult) { net::CanonicalCookie original_cookie( "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), /* secure = */ true, /* http_only = */ false, - net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW); + net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW, false); net::CookieWithAccessResult original = {original_cookie, net::CookieAccessResult()}; @@ -140,6 +172,7 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieWithAccessResult) { EXPECT_EQ(original.cookie.IsHttpOnly(), copied.cookie.IsHttpOnly()); EXPECT_EQ(original.cookie.SameSite(), copied.cookie.SameSite()); EXPECT_EQ(original.cookie.Priority(), copied.cookie.Priority()); + EXPECT_EQ(original.cookie.IsSameParty(), copied.cookie.IsSameParty()); EXPECT_EQ(original.access_result.effective_same_site, copied.access_result.effective_same_site); EXPECT_EQ(original.access_result.status, copied.access_result.status); @@ -149,7 +182,7 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieAndLineWithAccessResult) { net::CanonicalCookie original_cookie( "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), /* secure = */ true, /* http_only = */ false, - net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW); + net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW, false); net::CookieAndLineWithAccessResult original(original_cookie, "cookie-string", net::CookieAccessResult()); @@ -268,6 +301,7 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieOptions) { { net::CookieOptions least_trusted, copy; EXPECT_FALSE(least_trusted.return_excluded_cookies()); + least_trusted.set_return_excluded_cookies(); // differ from default. EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieOptions>( @@ -282,9 +316,12 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieOptions) { { net::CookieOptions very_trusted, copy; + auto kPartyContext = std::set<net::SchemefulSite>{ + net::SchemefulSite(url::Origin::Create(GURL("https://a.test")))}; very_trusted.set_include_httponly(); very_trusted.set_same_site_cookie_context( net::CookieOptions::SameSiteCookieContext::MakeInclusive()); + very_trusted.set_full_party_context(kPartyContext); EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieOptions>( &very_trusted, ©)); @@ -292,6 +329,38 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieOptions) { EXPECT_EQ(net::CookieOptions::SameSiteCookieContext::MakeInclusive(), copy.same_site_cookie_context()); EXPECT_FALSE(copy.return_excluded_cookies()); + EXPECT_EQ(kPartyContext, copy.full_party_context()); + } +} + +TEST(CookieManagerTraitsTest, Roundtrips_FullPartyContext) { + { + std::vector<std::set<net::SchemefulSite>> kTestCases = { + std::set<net::SchemefulSite>(), + std::set<net::SchemefulSite>{net::SchemefulSite()}, + std::set<net::SchemefulSite>{ + net::SchemefulSite(url::Origin::Create(GURL("https://a.test")))}, + std::set<net::SchemefulSite>{ + net::SchemefulSite(url::Origin::Create(GURL("http://a.test"))), + net::SchemefulSite(url::Origin::Create(GURL("http://b.test")))}, + }; + + for (const std::set<net::SchemefulSite>& fpc : kTestCases) { + net::CookieOptions options, copy; + options.set_full_party_context(fpc); + EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieOptions>( + &options, ©)); + EXPECT_EQ(fpc, copy.full_party_context()); + } + } + { + base::Optional<std::set<net::SchemefulSite>> kFullPartyContext = + base::nullopt; + net::CookieOptions options, copy; + options.set_full_party_context(kFullPartyContext); + EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieOptions>( + &options, ©)); + EXPECT_EQ(kFullPartyContext, copy.full_party_context()); } } @@ -299,7 +368,7 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieChangeInfo) { net::CanonicalCookie original_cookie( "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), /* secure = */ false, /* http_only = */ false, - net::CookieSameSite::UNSPECIFIED, net::COOKIE_PRIORITY_LOW); + net::CookieSameSite::UNSPECIFIED, net::COOKIE_PRIORITY_LOW, false); net::CookieChangeInfo original( original_cookie, diff --git a/chromium/services/network/public/cpp/cors/cors_error_status.cc b/chromium/services/network/public/cpp/cors/cors_error_status.cc index 684de47c0e5..617424ba012 100644 --- a/chromium/services/network/public/cpp/cors/cors_error_status.cc +++ b/chromium/services/network/public/cpp/cors/cors_error_status.cc @@ -4,30 +4,45 @@ #include "services/network/public/cpp/cors/cors_error_status.h" +#include <ostream> + #include "net/base/net_errors.h" #include "services/network/public/mojom/cors.mojom-shared.h" +#include "services/network/public/mojom/ip_address_space.mojom-shared.h" namespace network { -// Note: |cors_error| is initialized to kLast to keep the value inside the -// valid enum value range. The value is meaningless and should be overriden -// immediately by IPC desrtialization code. -CorsErrorStatus::CorsErrorStatus() - : CorsErrorStatus(mojom::CorsError::kMaxValue) {} +CorsErrorStatus::CorsErrorStatus() = default; -CorsErrorStatus::CorsErrorStatus(const CorsErrorStatus& status) = default; +CorsErrorStatus::CorsErrorStatus(const CorsErrorStatus&) = default; +CorsErrorStatus& CorsErrorStatus::operator=(const CorsErrorStatus&) = default; +CorsErrorStatus::CorsErrorStatus(CorsErrorStatus&&) = default; +CorsErrorStatus& CorsErrorStatus::operator=(CorsErrorStatus&&) = default; -CorsErrorStatus::CorsErrorStatus(mojom::CorsError error) : cors_error(error) {} +CorsErrorStatus::CorsErrorStatus(mojom::CorsError cors_error) + : cors_error(cors_error) {} -CorsErrorStatus::CorsErrorStatus(mojom::CorsError error, +CorsErrorStatus::CorsErrorStatus(mojom::CorsError cors_error, const std::string& failed_parameter) - : cors_error(error), failed_parameter(failed_parameter) {} + : cors_error(cors_error), failed_parameter(failed_parameter) {} + +CorsErrorStatus::CorsErrorStatus(mojom::IPAddressSpace resource_address_space) + : cors_error(mojom::CorsError::kInsecurePrivateNetwork), + resource_address_space(resource_address_space) {} CorsErrorStatus::~CorsErrorStatus() = default; bool CorsErrorStatus::operator==(const CorsErrorStatus& rhs) const { return cors_error == rhs.cors_error && - failed_parameter == rhs.failed_parameter; + failed_parameter == rhs.failed_parameter && + resource_address_space == rhs.resource_address_space; +} + +std::ostream& operator<<(std::ostream& os, const CorsErrorStatus& status) { + return os << "CorsErrorStatus{ cors_error = " << status.cors_error + << ", failed_parameter = " << status.failed_parameter + << ", resource_address_space = " << status.resource_address_space + << " }"; } } // namespace network diff --git a/chromium/services/network/public/cpp/cors/cors_error_status.h b/chromium/services/network/public/cpp/cors/cors_error_status.h index 32d40181a58..902c995127e 100644 --- a/chromium/services/network/public/cpp/cors/cors_error_status.h +++ b/chromium/services/network/public/cpp/cors/cors_error_status.h @@ -5,18 +5,19 @@ #ifndef SERVICES_NETWORK_PUBLIC_CPP_CORS_CORS_ERROR_STATUS_H_ #define SERVICES_NETWORK_PUBLIC_CPP_CORS_CORS_ERROR_STATUS_H_ +#include <iosfwd> #include <string> #include "base/component_export.h" #include "base/memory/scoped_refptr.h" #include "net/http/http_response_headers.h" +#include "services/network/public/mojom/cors.mojom-shared.h" +#include "services/network/public/mojom/ip_address_space.mojom-shared.h" namespace network { -namespace mojom { -enum class CorsError : int32_t; -} - +// WARNING: When adding fields to this truct, do not forget to add them in +// services/network/public/cpp/network_ipc_param_traits.h too. struct COMPONENT_EXPORT(NETWORK_CPP_BASE) CorsErrorStatus { // This constructor is used by generated IPC serialization code. // Should not use this explicitly. @@ -24,22 +25,43 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) CorsErrorStatus { // only serialization code for mojo can access. CorsErrorStatus(); - CorsErrorStatus(const CorsErrorStatus& status); + // Instances of this type are copyable and efficiently movable. + CorsErrorStatus(const CorsErrorStatus&); + CorsErrorStatus& operator=(const CorsErrorStatus&); + CorsErrorStatus(CorsErrorStatus&&); + CorsErrorStatus& operator=(CorsErrorStatus&&); + + explicit CorsErrorStatus(mojom::CorsError cors_error); + CorsErrorStatus(mojom::CorsError cors_error, + const std::string& failed_parameter); - explicit CorsErrorStatus(mojom::CorsError error); - CorsErrorStatus(mojom::CorsError error, const std::string& failed_parameter); + // Constructor for CORS-RFC1918 errors. + // Sets `cors_error` to `kInsecurePrivateNetwork`. + explicit CorsErrorStatus(mojom::IPAddressSpace resource_address_space); ~CorsErrorStatus(); bool operator==(const CorsErrorStatus& rhs) const; bool operator!=(const CorsErrorStatus& rhs) const { return !(*this == rhs); } - mojom::CorsError cors_error; + // NOTE: This value is meaningless and should be overridden immediately either + // by a constructor or by IPC deserialization code. + mojom::CorsError cors_error = mojom::CorsError::kMaxValue; // Contains request method name, or header name that didn't pass a CORS check. std::string failed_parameter; + + // The address space of the requested resource. + // + // Only set if `cors_error == kInsecurePrivateNetwork`. + mojom::IPAddressSpace resource_address_space = + mojom::IPAddressSpace::kUnknown; }; +// CorsErrorStatus instances are streamable for ease of debugging. +COMPONENT_EXPORT(NETWORK_CPP_BASE) +std::ostream& operator<<(std::ostream& os, const CorsErrorStatus& status); + } // namespace network #endif // SERVICES_NETWORK_PUBLIC_CPP_CORS_CORS_ERROR_STATUS_H_ diff --git a/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.cc b/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.cc index 3d8c8b93b63..dd50f85aea2 100644 --- a/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.cc +++ b/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.cc @@ -64,6 +64,9 @@ CrossOriginOpenerPolicy ParseCrossOriginOpenerPolicy( if (coop.value == mojom::CrossOriginOpenerPolicyValue::kSameOrigin && coep.value == mojom::CrossOriginEmbedderPolicyValue::kRequireCorp) coop.value = mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep; + } else if (base::FeatureList::IsEnabled( + features::kCrossOriginOpenerPolicyByDefault)) { + coop.value = mojom::CrossOriginOpenerPolicyValue::kSameOriginAllowPopups; } if (headers.GetNormalizedHeader(kCrossOriginOpenerPolicyHeaderReportOnly, &header_value)) { diff --git a/chromium/services/network/public/cpp/cross_origin_opener_policy_parser_unittest.cc b/chromium/services/network/public/cpp/cross_origin_opener_policy_parser_unittest.cc index b84ebbe23e7..8d1e51f56d1 100644 --- a/chromium/services/network/public/cpp/cross_origin_opener_policy_parser_unittest.cc +++ b/chromium/services/network/public/cpp/cross_origin_opener_policy_parser_unittest.cc @@ -206,4 +206,48 @@ TEST(CrossOriginOpenerPolicyTest, Parse) { } } +TEST(CrossOriginOpenerPolicyTest, Default) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kCrossOriginOpenerPolicy); + network::CrossOriginEmbedderPolicy coep; + + // If no COOP header is specified: + scoped_refptr<net::HttpResponseHeaders> headers( + new net::HttpResponseHeaders("HTTP/1.1 200 OK")); + + // Then we have no policy enforced by default: + network::CrossOriginOpenerPolicy parsed_policy = + ParseCrossOriginOpenerPolicy(*headers, coep); + EXPECT_EQ(base::nullopt, parsed_policy.reporting_endpoint); + EXPECT_EQ(mojom::CrossOriginOpenerPolicyValue::kUnsafeNone, + parsed_policy.value); + EXPECT_EQ(base::nullopt, parsed_policy.report_only_reporting_endpoint); + EXPECT_EQ(mojom::CrossOriginOpenerPolicyValue::kUnsafeNone, + parsed_policy.report_only_value); +} + +TEST(CrossOriginOpenerPolicyTest, DefaultWithCOOPByDefault) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + {features::kCrossOriginOpenerPolicy, + features::kCrossOriginOpenerPolicyByDefault}, + {}); + network::CrossOriginEmbedderPolicy coep; + + // If no COOP header is specified: + scoped_refptr<net::HttpResponseHeaders> headers( + new net::HttpResponseHeaders("HTTP/1.1 200 OK")); + + // Then we have `same-origin-allow-popups` as enforced by default, but no + // policy reported on by default: + network::CrossOriginOpenerPolicy parsed_policy = + ParseCrossOriginOpenerPolicy(*headers, coep); + EXPECT_EQ(base::nullopt, parsed_policy.reporting_endpoint); + EXPECT_EQ(mojom::CrossOriginOpenerPolicyValue::kSameOriginAllowPopups, + parsed_policy.value); + EXPECT_EQ(base::nullopt, parsed_policy.report_only_reporting_endpoint); + EXPECT_EQ(mojom::CrossOriginOpenerPolicyValue::kUnsafeNone, + parsed_policy.report_only_value); +} + } // namespace network diff --git a/chromium/services/network/public/cpp/cross_origin_resource_policy.cc b/chromium/services/network/public/cpp/cross_origin_resource_policy.cc index 39791e44c24..b24addd5a5e 100644 --- a/chromium/services/network/public/cpp/cross_origin_resource_policy.cc +++ b/chromium/services/network/public/cpp/cross_origin_resource_policy.cc @@ -145,6 +145,18 @@ base::Optional<mojom::BlockedByResponseReason> IsBlockedInternal( mojom::RequestMode request_mode, base::Optional<url::Origin> request_initiator_origin_lock, mojom::CrossOriginEmbedderPolicyValue embedder_policy) { + // Browser-initiated requests are not subject to Cross-Origin-Resource-Policy. + if (!request_initiator.has_value()) { + // The DCHECK further confirm that this is a browser-initiated request. + // Note also CorsURLLoaderFactory::IsValidRequest which rejects + // renderer-initiated requests without a |request_initiator| and/or without + // a |request_initiator_origin_lock| via + // InitiatorLockCompatibility::kNoInitiator and + // InitiatorLockCompatibility::kNoLock cases. + DCHECK(!request_initiator_origin_lock.has_value()); + return base::nullopt; + } + // COEP https://mikewest.github.io/corpp/#corp-check bool upgrade_to_same_origin = false; if ((policy == CrossOriginResourcePolicy::kNoHeader || diff --git a/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory_unittest.cc b/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory_unittest.cc index 5b853b21068..a3a647f627a 100644 --- a/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory_unittest.cc +++ b/chromium/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory_unittest.cc @@ -13,7 +13,7 @@ #include "base/sequenced_task_runner.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/sequenced_task_runner_handle.h" #include "mojo/public/cpp/bindings/pending_receiver.h" diff --git a/chromium/services/network/public/cpp/data_element.cc b/chromium/services/network/public/cpp/data_element.cc index 545797ec180..32879fefe7a 100644 --- a/chromium/services/network/public/cpp/data_element.cc +++ b/chromium/services/network/public/cpp/data_element.cc @@ -40,15 +40,6 @@ void DataElement::SetToFilePathRange( expected_modification_time_ = expected_modification_time; } -void DataElement::SetToBlobRange(const std::string& blob_uuid, - uint64_t offset, - uint64_t length) { - type_ = mojom::DataElementType::kBlob; - blob_uuid_ = blob_uuid; - offset_ = offset; - length_ = length; -} - void DataElement::SetToDataPipe( mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter) { DCHECK(data_pipe_getter); @@ -90,6 +81,13 @@ mojo::PendingRemote<mojom::DataPipeGetter> DataElement::CloneDataPipeGetter() return clone; } +const mojo::PendingRemote<mojom::ChunkedDataPipeGetter>& +DataElement::chunked_data_pipe_getter() const { + DCHECK(type_ == mojom::DataElementType::kChunkedDataPipe || + type_ == mojom::DataElementType::kReadOnceStream); + return chunked_data_pipe_getter_; +} + mojo::PendingRemote<mojom::ChunkedDataPipeGetter> DataElement::ReleaseChunkedDataPipeGetter() { DCHECK(type_ == mojom::DataElementType::kChunkedDataPipe || @@ -116,9 +114,6 @@ void PrintTo(const DataElement& x, std::ostream* os) { *os << "TYPE_FILE, path: " << x.path().AsUTF8Unsafe() << ", expected_modification_time: " << x.expected_modification_time(); break; - case mojom::DataElementType::kBlob: - *os << "TYPE_BLOB, uuid: " << x.blob_uuid(); - break; case mojom::DataElementType::kDataPipe: *os << "TYPE_DATA_PIPE"; break; @@ -145,8 +140,6 @@ bool operator==(const DataElement& a, const DataElement& b) { case mojom::DataElementType::kFile: return a.path() == b.path() && a.expected_modification_time() == b.expected_modification_time(); - case mojom::DataElementType::kBlob: - return a.blob_uuid() == b.blob_uuid(); case mojom::DataElementType::kDataPipe: return false; case mojom::DataElementType::kChunkedDataPipe: diff --git a/chromium/services/network/public/cpp/data_element.h b/chromium/services/network/public/cpp/data_element.h index 42e096ac783..7eeb277b4ea 100644 --- a/chromium/services/network/public/cpp/data_element.h +++ b/chromium/services/network/public/cpp/data_element.h @@ -35,8 +35,8 @@ class FetchAPIDataElementDataView; namespace network { -// Represents part of an upload body. This could be either one of bytes, file or -// blob data. +// Represents part of an upload body. This could be one of raw bytes, file data, +// or a mojo pipe that streams data. class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElement { public: static const uint64_t kUnknownSize = std::numeric_limits<uint64_t>::max(); @@ -54,7 +54,6 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElement { return reinterpret_cast<const char*>(buf_.data()); } const base::FilePath& path() const { return path_; } - const std::string& blob_uuid() const { return blob_uuid_; } uint64_t offset() const { return offset_; } uint64_t length() const { return length_; } const base::Time& expected_modification_time() const { @@ -94,22 +93,12 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElement { length_ = buf_.size(); } - // Sets TYPE_BLOB data. - void SetToBlob(const std::string& uuid) { - SetToBlobRange(uuid, 0, std::numeric_limits<uint64_t>::max()); - } - // Sets TYPE_FILE data with range. void SetToFilePathRange(const base::FilePath& path, uint64_t offset, uint64_t length, const base::Time& expected_modification_time); - // Sets TYPE_BLOB data with range. - void SetToBlobRange(const std::string& blob_uuid, - uint64_t offset, - uint64_t length); - // Sets TYPE_DATA_PIPE data. The data pipe consumer can safely wait for the // callback passed to Read() to be invoked before reading the request body. void SetToDataPipe( @@ -132,8 +121,12 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElement { mojo::PendingRemote<mojom::DataPipeGetter> ReleaseDataPipeGetter(); mojo::PendingRemote<mojom::DataPipeGetter> CloneDataPipeGetter() const; + // Can be called only when this is of type kChunkedDataPipe or + // kReadOnceStream. + const mojo::PendingRemote<mojom::ChunkedDataPipeGetter>& + chunked_data_pipe_getter() const; // Takes ownership of the DataPipeGetter, if this is of - // TYPE_CHUNKED_DATA_PIPE. + // kChunkedDataPipe or kReadOnceStream. mojo::PendingRemote<mojom::ChunkedDataPipeGetter> ReleaseChunkedDataPipeGetter(); @@ -149,8 +142,6 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElement { std::vector<uint8_t> buf_; // For TYPE_FILE. base::FilePath path_; - // For TYPE_BLOB. - std::string blob_uuid_; // For TYPE_DATA_PIPE. mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter_; // For TYPE_CHUNKED_DATA_PIPE. diff --git a/chromium/services/network/public/cpp/features.cc b/chromium/services/network/public/cpp/features.cc index fe604dfc7a7..cd4d9239360 100644 --- a/chromium/services/network/public/cpp/features.cc +++ b/chromium/services/network/public/cpp/features.cc @@ -5,6 +5,7 @@ #include "services/network/public/cpp/features.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" namespace network { namespace features { @@ -46,12 +47,6 @@ const base::Feature kThrottleDelayable{"ThrottleDelayable", const base::Feature kDelayRequestsOnMultiplexedConnections{ "DelayRequestsOnMultiplexedConnections", base::FEATURE_ENABLED_BY_DEFAULT}; -// When kRequestInitiatorSiteLock is enabled, then CORB, CORP and Sec-Fetch-Site -// will validate network::ResourceRequest::request_initiator against -// network::mojom::URLLoaderFactoryParams::request_initiator_origin_lock. -const base::Feature kRequestInitiatorSiteLock{"RequestInitiatorSiteLock", - base::FEATURE_ENABLED_BY_DEFAULT}; - // When kPauseBrowserInitiatedHeavyTrafficForP2P is enabled, then a subset of // the browser initiated traffic may be paused if there is at least one active // P2P connection and the network is estimated to be congested. This feature is @@ -76,6 +71,7 @@ const base::Feature kProactivelyThrottleLowPriorityRequests{ // Enables Cross-Origin Opener Policy (COOP). // https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e +// https://html.spec.whatwg.org/#cross-origin-opener-policy // Currently this feature is enabled for all platforms except WebView. const base::Feature kCrossOriginOpenerPolicy{"CrossOriginOpenerPolicy", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -96,9 +92,16 @@ const base::Feature kCrossOriginOpenerPolicyReporting{ const base::Feature kCrossOriginOpenerPolicyAccessReporting{ "CrossOriginOpenerPolicyAccessReporting", base::FEATURE_ENABLED_BY_DEFAULT}; +// Shift's COOP's default from `unsafe-none` to `same-origin-allow-popups`. +// https://github.com/mikewest/coop-by-default/ +const base::Feature kCrossOriginOpenerPolicyByDefault{ + "CrossOriginOpenerPolicyByDefault", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables Cross-Origin Embedder Policy (COEP). -// https://github.com/mikewest/corpp -// Currently this feature is enabled for all platforms except WebView. +// https://html.spec.whatwg.org/#coep +// Currently this feature is enabled for all platforms (including webview). +// TODO(https://crbug.com/1140432): Remove this flag after M88 Stable + 1 week = +// 2021-02-01. const base::Feature kCrossOriginEmbedderPolicy{ "CrossOriginEmbedderPolicy", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -115,7 +118,7 @@ const base::Feature kSplitAuthCacheByNetworkIsolationKey{ // Enable usage of hardcoded DoH upgrade mapping for use in automatic mode. const base::Feature kDnsOverHttpsUpgrade { "DnsOverHttpsUpgrade", -#if defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_ANDROID) || \ +#if BUILDFLAG(IS_ASH) || defined(OS_MAC) || defined(OS_ANDROID) || \ defined(OS_WIN) base::FEATURE_ENABLED_BY_DEFAULT #else @@ -149,25 +152,6 @@ const base::Feature "DeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess", base::FEATURE_DISABLED_BY_DEFAULT}; -// Emergency switch for legacy cookie access semantics on given patterns, as -// specified by the param, comma separated. -const base::Feature kEmergencyLegacyCookieAccess{ - "EmergencyLegacyCookieAccess", base::FEATURE_DISABLED_BY_DEFAULT}; -const char kEmergencyLegacyCookieAccessParamName[] = "Patterns"; -const base::FeatureParam<std::string> kEmergencyLegacyCookieAccessParam{ - &kEmergencyLegacyCookieAccess, kEmergencyLegacyCookieAccessParamName, ""}; - -// Controls whether the CORB allowlist [1] is also applied to OOR-CORS (e.g. -// whether non-allowlisted content scripts are subject to CORS in OOR-CORS -// mode). See also: https://crbug.com/920638 -// -// [1] -// https://www.chromium.org/Home/chromium-security/extension-content-script-fetches -const base::Feature kCorbAllowlistAlsoAppliesToOorCors = { - "CorbAllowlistAlsoAppliesToOorCors", base::FEATURE_ENABLED_BY_DEFAULT}; -const char kCorbAllowlistAlsoAppliesToOorCorsParamName[] = - "AllowlistForCorbAndCors"; - // Controls whether a |request_initiator| that mismatches // |request_initiator_origin_lock| leads to 1) failing the HTTP request and 2) // calling mojo::ReportBadMessage (on desktop platforms, where NetworkService @@ -225,6 +209,12 @@ const base::FeatureParam<TrustTokenOriginTrialSpec> TrustTokenOriginTrialSpec::kOriginTrialNotRequired, &kTrustTokenOriginTrialParamOptions}; +// Determines whether Trust Tokens issuance requests should be diverted, at the +// corresponding issuers' request, to the operating system instead of sent +// to the issuers' servers. +const base::FeatureParam<bool> kPlatformProvidedTrustTokenIssuance{ + &kTrustTokens, "PlatformProvidedTrustTokenIssuance", false}; + // Enables the Content Security Policy Embedded Enforcement check out of blink const base::Feature kOutOfBlinkCSPEE{"OutOfBlinkCSPEE", base::FEATURE_ENABLED_BY_DEFAULT}; diff --git a/chromium/services/network/public/cpp/features.h b/chromium/services/network/public/cpp/features.h index 6f117fac688..a836a51eadc 100644 --- a/chromium/services/network/public/cpp/features.h +++ b/chromium/services/network/public/cpp/features.h @@ -25,8 +25,6 @@ extern const base::Feature kThrottleDelayable; COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kDelayRequestsOnMultiplexedConnections; COMPONENT_EXPORT(NETWORK_CPP) -extern const base::Feature kRequestInitiatorSiteLock; -COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kPauseBrowserInitiatedHeavyTrafficForP2P; COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kCORBProtectionSniffing; @@ -41,6 +39,8 @@ extern const base::Feature kCrossOriginOpenerPolicyReportingOriginTrial; COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kCrossOriginOpenerPolicyAccessReporting; COMPONENT_EXPORT(NETWORK_CPP) +extern const base::Feature kCrossOriginOpenerPolicyByDefault; +COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kCrossOriginEmbedderPolicy; COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kCrossOriginIsolated; @@ -59,17 +59,6 @@ COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess; COMPONENT_EXPORT(NETWORK_CPP) -extern const base::Feature kEmergencyLegacyCookieAccess; -COMPONENT_EXPORT(NETWORK_CPP) -extern const char kEmergencyLegacyCookieAccessParamName[]; -COMPONENT_EXPORT(NETWORK_CPP) -extern const base::FeatureParam<std::string> kEmergencyLegacyCookieAccessParam; - -COMPONENT_EXPORT(NETWORK_CPP) -extern const base::Feature kCorbAllowlistAlsoAppliesToOorCors; -COMPONENT_EXPORT(NETWORK_CPP) -extern const char kCorbAllowlistAlsoAppliesToOorCorsParamName[]; -COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kRequestInitiatorSiteLockEnfocement; COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kCertVerifierService; @@ -86,6 +75,8 @@ enum class TrustTokenOriginTrialSpec { COMPONENT_EXPORT(NETWORK_CPP) extern const base::FeatureParam<TrustTokenOriginTrialSpec> kTrustTokenOperationsRequiringOriginTrial; +COMPONENT_EXPORT(NETWORK_CPP) +extern const base::FeatureParam<bool> kPlatformProvidedTrustTokenIssuance; COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kOutOfBlinkCSPEE; diff --git a/chromium/services/network/public/cpp/host_resolver_mojom_traits.cc b/chromium/services/network/public/cpp/host_resolver_mojom_traits.cc index 56c05a5d33f..37b8a86b770 100644 --- a/chromium/services/network/public/cpp/host_resolver_mojom_traits.cc +++ b/chromium/services/network/public/cpp/host_resolver_mojom_traits.cc @@ -167,7 +167,7 @@ bool StructTraits<DnsConfigOverridesDataView, net::DnsConfigOverrides>::Read( out->ndots = data.ndots(); // if == -1, leave nullopt. - if (!data.ReadTimeout(&out->timeout)) + if (!data.ReadFallbackPeriod(&out->fallback_period)) return false; if (data.attempts() < -1) @@ -214,6 +214,8 @@ DnsQueryType EnumTraits<DnsQueryType, net::DnsQueryType>::ToMojom( return DnsQueryType::PTR; case net::DnsQueryType::SRV: return DnsQueryType::SRV; + case net::DnsQueryType::HTTPS: + return DnsQueryType::HTTPS; case net::DnsQueryType::INTEGRITY: NOTIMPLEMENTED(); return DnsQueryType::UNSPECIFIED; @@ -243,6 +245,9 @@ bool EnumTraits<DnsQueryType, net::DnsQueryType>::FromMojom( case DnsQueryType::SRV: *output = net::DnsQueryType::SRV; return true; + case DnsQueryType::HTTPS: + *output = net::DnsQueryType::HTTPS; + return true; } } diff --git a/chromium/services/network/public/cpp/host_resolver_mojom_traits.h b/chromium/services/network/public/cpp/host_resolver_mojom_traits.h index 76e1fc8b53b..4b3a9d9fc96 100644 --- a/chromium/services/network/public/cpp/host_resolver_mojom_traits.h +++ b/chromium/services/network/public/cpp/host_resolver_mojom_traits.h @@ -52,9 +52,9 @@ struct StructTraits<network::mojom::DnsConfigOverridesDataView, return overrides.ndots.value_or(-1); } - static const base::Optional<base::TimeDelta>& timeout( + static const base::Optional<base::TimeDelta>& fallback_period( const net::DnsConfigOverrides& overrides) { - return overrides.timeout; + return overrides.fallback_period; } static int attempts(const net::DnsConfigOverrides& overrides) { diff --git a/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc index 0a0e0945cbe..81792349e33 100644 --- a/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc +++ b/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc @@ -33,7 +33,7 @@ TEST(HostResolverMojomTraitsTest, DnsConfigOverridesRoundtrip_FullySpecified) { original.search.emplace({std::string("str")}); original.append_to_multi_label_name = true; original.ndots = 2; - original.timeout = base::TimeDelta::FromHours(4); + original.fallback_period = base::TimeDelta::FromHours(4); original.attempts = 1; original.rotate = true; original.use_local_ipv6 = false; diff --git a/chromium/services/network/public/cpp/initiator_lock_compatibility.cc b/chromium/services/network/public/cpp/initiator_lock_compatibility.cc index 0068639a1ff..d55a6f55a9c 100644 --- a/chromium/services/network/public/cpp/initiator_lock_compatibility.cc +++ b/chromium/services/network/public/cpp/initiator_lock_compatibility.cc @@ -7,10 +7,8 @@ #include <string> #include "base/containers/flat_set.h" -#include "base/feature_list.h" #include "base/no_destructor.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" -#include "services/network/public/cpp/features.h" #include "services/network/public/cpp/resource_request.h" #include "services/network/public/mojom/network_context.mojom.h" #include "url/gurl.h" @@ -56,9 +54,6 @@ url::Origin GetTrustworthyInitiator( if (!request_initiator.has_value()) return unique_origin_fallback; - if (!base::FeatureList::IsEnabled(features::kRequestInitiatorSiteLock)) - return request_initiator.value(); - InitiatorLockCompatibility initiator_compatibility = VerifyRequestInitiatorLock(request_initiator_origin_lock, request_initiator); diff --git a/chromium/services/network/public/cpp/ip_address_space_util.cc b/chromium/services/network/public/cpp/ip_address_space_util.cc index a9824b1f17f..00eeef595da 100644 --- a/chromium/services/network/public/cpp/ip_address_space_util.cc +++ b/chromium/services/network/public/cpp/ip_address_space_util.cc @@ -5,6 +5,9 @@ #include "services/network/public/cpp/ip_address_space_util.h" #include "net/base/ip_address.h" +#include "services/network/public/cpp/content_security_policy/content_security_policy.h" +#include "services/network/public/mojom/url_response_head.mojom.h" +#include "url/gurl.h" namespace network { @@ -41,4 +44,46 @@ bool IsLessPublicAddressSpace(IPAddressSpace lhs, IPAddressSpace rhs) { return CollapseUnknown(lhs) < CollapseUnknown(rhs); } +// Helper for CalculateClientAddressSpace() with the same arguments. +// +// If the response was fetched via service workers, returns the last URL in the +// list. Otherwise returns |request_url|. +// +// See: https://fetch.spec.whatwg.org/#concept-response-url-list +const GURL& ResponseUrl(const GURL& request_url, + const mojom::URLResponseHead* response_head) { + if (response_head && !response_head->url_list_via_service_worker.empty()) { + return response_head->url_list_via_service_worker.back(); + } + + return request_url; +} + +IPAddressSpace CalculateClientAddressSpace( + const GURL& url, + const mojom::URLResponseHead* response_head) { + if (ResponseUrl(url, response_head).SchemeIsFile()) { + // See: https://wicg.github.io/cors-rfc1918/#file-url. + return IPAddressSpace::kLocal; + } + + if (!response_head) { + return IPAddressSpace::kUnknown; + } + + // First, check whether the response forces itself into a public address space + // as per https://wicg.github.io/cors-rfc1918/#csp. + DCHECK(response_head->parsed_headers) + << "CalculateIPAddressSpace() called for URL " << url + << " with null parsed_headers."; + if (response_head->parsed_headers && + ShouldTreatAsPublicAddress( + response_head->parsed_headers->content_security_policy)) { + return IPAddressSpace::kPublic; + } + + // Otherwise, calculate the address space via the provided IP address. + return IPAddressToIPAddressSpace(response_head->remote_endpoint.address()); +} + } // namespace network diff --git a/chromium/services/network/public/cpp/ip_address_space_util.h b/chromium/services/network/public/cpp/ip_address_space_util.h index d16f8f981eb..4e8423ca1db 100644 --- a/chromium/services/network/public/cpp/ip_address_space_util.h +++ b/chromium/services/network/public/cpp/ip_address_space_util.h @@ -6,6 +6,9 @@ #define SERVICES_NETWORK_PUBLIC_CPP_IP_ADDRESS_SPACE_UTIL_H_ #include "services/network/public/mojom/ip_address_space.mojom.h" +#include "services/network/public/mojom/url_response_head.mojom-forward.h" + +class GURL; namespace net { @@ -17,8 +20,8 @@ namespace network { // Returns the IPAddressSpace from an IPAddress. // -// This can be used as-is for subresource requests. For documents, also take -// into account the 'treat-as-public-address' CSP directive. +// WARNING: This can only be used as-is for subresource requests loaded over the +// network. For other cases, see the Calculate*AddressSpace() functions below. mojom::IPAddressSpace COMPONENT_EXPORT(NETWORK_CPP) IPAddressToIPAddressSpace(const net::IPAddress& address); @@ -36,6 +39,30 @@ bool COMPONENT_EXPORT(NETWORK_CPP) IsLessPublicAddressSpace(mojom::IPAddressSpace lhs, mojom::IPAddressSpace rhs); +// Given a request URL and response information, this function calculates the +// IPAddressSpace which should be associated with documents or worker global +// scopes (collectively: request clients) instantiated from this resource. +// +// |response_head| may be nullptr. Caller retains ownership. If not nullptr, +// then |response_head->parsed_headers| must be populated with the result of +// parsing |response->headers|. +// +// WARNING: This function is defined here for proximity with related code and +// the data structures involved. However since it deals with higher-level +// concepts too (documents and worker global scopes), it should probably only be +// used at the content/ layer or above. +// +// See: https://wicg.github.io/cors-rfc1918/#address-space +// +// TODO(https://crbug.com/1134601): This implementation treats requests that +// don't use a URL loader (`about:blank`), as well as requests whose IP address +// is invalid (`about:srcdoc`, `blob:`, etc.) as `kUnknown`. This is incorrect. +// We'll eventually want to make sure we inherit from the client's creator +// in some cases), but safe, as `kUnknown` is treated the same as `kPublic`. +mojom::IPAddressSpace COMPONENT_EXPORT(NETWORK_CPP) + CalculateClientAddressSpace(const GURL& url, + const mojom::URLResponseHead* response_head); + } // namespace network #endif // SERVICES_NETWORK_PUBLIC_CPP_IP_ADDRESS_SPACE_UTIL_H_ diff --git a/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc b/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc index c29491b3a14..de54b30f8a9 100644 --- a/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc +++ b/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc @@ -4,15 +4,30 @@ #include "services/network/public/cpp/ip_address_space_util.h" +#include <utility> + #include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" +#include "services/network/public/mojom/parsed_headers.mojom.h" +#include "services/network/public/mojom/url_response_head.mojom.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" namespace network { namespace { +using mojom::ContentSecurityPolicy; using mojom::IPAddressSpace; +using mojom::ParsedHeaders; +using mojom::URLResponseHead; using net::IPAddress; using net::IPAddressBytes; +using net::IPEndPoint; + +IPAddress PrivateIPv4Address() { + return IPAddress(192, 168, 1, 1); +} TEST(IPAddressSpaceTest, IPAddressToIPAddressSpacev4) { EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress()), IPAddressSpace::kUnknown); @@ -20,12 +35,12 @@ TEST(IPAddressSpaceTest, IPAddressToIPAddressSpacev4) { EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress(64, 233, 160, 0)), IPAddressSpace::kPublic); - EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress(192, 168, 1, 1)), + EXPECT_EQ(IPAddressToIPAddressSpace(PrivateIPv4Address()), IPAddressSpace::kPrivate); EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress(10, 1, 1, 1)), IPAddressSpace::kPrivate); - EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress(127, 0, 0, 1)), + EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress::IPv4Localhost()), IPAddressSpace::kLocal); } @@ -93,5 +108,82 @@ TEST(IPAddressSpaceTest, IsLessPublicAddressSpaceThanUnknown) { IPAddressSpace::kUnknown)); } +TEST(IPAddressSpaceTest, CalculateClientAddressSpaceFileURL) { + EXPECT_EQ(IPAddressSpace::kLocal, + CalculateClientAddressSpace(GURL("file:///foo"), nullptr)); +} + +TEST(IPAddressSpaceTest, + CalculateIPAddressSpaceFetchedViaServiceWorkerFromFile) { + URLResponseHead response_head; + response_head.url_list_via_service_worker.emplace_back("http://bar.test"); + response_head.url_list_via_service_worker.emplace_back("file:///foo"); + response_head.parsed_headers = ParsedHeaders::New(); + + EXPECT_EQ( + IPAddressSpace::kLocal, + CalculateClientAddressSpace(GURL("http://foo.test"), &response_head)); +} + +TEST(IPAddressSpaceTest, + CalculateIPAddressSpaceFetchedViaServiceWorkerFromHttp) { + URLResponseHead response_head; + response_head.url_list_via_service_worker.emplace_back("file:///foo"); + response_head.url_list_via_service_worker.emplace_back("http://bar.test"); + response_head.parsed_headers = ParsedHeaders::New(); + + EXPECT_EQ( + IPAddressSpace::kUnknown, + CalculateClientAddressSpace(GURL("http://foo.test"), &response_head)); +} + +TEST(IPAddressSpaceTest, + CalculateIPAddressSpaceFetchedViaServiceWorkerFromHttpInsteadOfFile) { + URLResponseHead response_head; + response_head.url_list_via_service_worker.emplace_back("http://bar.test"); + response_head.parsed_headers = ParsedHeaders::New(); + + EXPECT_EQ(IPAddressSpace::kUnknown, + CalculateClientAddressSpace(GURL("file:///foo"), &response_head)); +} + +TEST(IPAddressSpaceTest, CalculateClientAddressSpaceNullResponseHead) { + EXPECT_EQ(IPAddressSpace::kUnknown, + CalculateClientAddressSpace(GURL("http://foo.test"), nullptr)); +} + +TEST(IPAddressSpaceTest, CalculateClientAddressSpaceEmptyResponseHead) { + URLResponseHead response_head; + response_head.parsed_headers = ParsedHeaders::New(); + EXPECT_EQ( + IPAddressSpace::kUnknown, + CalculateClientAddressSpace(GURL("http://foo.test"), &response_head)); +} + +TEST(IPAddressSpaceTest, CalculateClientAddressSpaceIPAddress) { + URLResponseHead response_head; + response_head.remote_endpoint = IPEndPoint(PrivateIPv4Address(), 1234); + response_head.parsed_headers = ParsedHeaders::New(); + + EXPECT_EQ( + IPAddressSpace::kPrivate, + CalculateClientAddressSpace(GURL("http://foo.test"), &response_head)); +} + +TEST(IPAddressSpaceTest, CalculateClientAddressSpaceTreatAsPublicAddress) { + URLResponseHead response_head; + response_head.remote_endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 1234); + + auto csp = ContentSecurityPolicy::New(); + csp->treat_as_public_address = true; + response_head.parsed_headers = ParsedHeaders::New(); + response_head.parsed_headers->content_security_policy.push_back( + std::move(csp)); + + EXPECT_EQ( + IPAddressSpace::kPublic, + CalculateClientAddressSpace(GURL("http://foo.test"), &response_head)); +} + } // namespace } // namespace network diff --git a/chromium/services/network/public/cpp/is_potentially_trustworthy.cc b/chromium/services/network/public/cpp/is_potentially_trustworthy.cc index f9995d39390..37f6fd35b01 100644 --- a/chromium/services/network/public/cpp/is_potentially_trustworthy.cc +++ b/chromium/services/network/public/cpp/is_potentially_trustworthy.cc @@ -19,6 +19,7 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/url_util.h" #include "services/network/public/cpp/network_switches.h" @@ -175,7 +176,7 @@ std::vector<std::string> ParseSecureOriginAllowlistFromCmdline() { std::vector<std::string> origin_patterns = ParseSecureOriginAllowlist(origins_str); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // For Crostini, we allow access to the default VM/container as a secure // origin via the hostname penguin.linux.test. We are required to use a // wildcard for the prefix because we do not know what the port number is. diff --git a/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc b/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc index 8f797b5bd00..b9434b1a64e 100644 --- a/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc +++ b/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc @@ -10,39 +10,39 @@ namespace mojo { -bool EnumTraits<network::mojom::IsolationInfoRedirectMode, - net::IsolationInfo::RedirectMode>:: - FromMojom(network::mojom::IsolationInfoRedirectMode redirect_mode, - net::IsolationInfo::RedirectMode* out) { - switch (redirect_mode) { - case network::mojom::IsolationInfoRedirectMode::kUpdateTopFrame: - *out = net::IsolationInfo::RedirectMode::kUpdateTopFrame; +bool EnumTraits<network::mojom::IsolationInfoRequestType, + net::IsolationInfo::RequestType>:: + FromMojom(network::mojom::IsolationInfoRequestType request_type, + net::IsolationInfo::RequestType* out) { + switch (request_type) { + case network::mojom::IsolationInfoRequestType::kMainFrame: + *out = net::IsolationInfo::RequestType::kMainFrame; return true; - case network::mojom::IsolationInfoRedirectMode::kUpdateFrameOnly: - *out = net::IsolationInfo::RedirectMode::kUpdateFrameOnly; + case network::mojom::IsolationInfoRequestType::kSubFrame: + *out = net::IsolationInfo::RequestType::kSubFrame; return true; - case network::mojom::IsolationInfoRedirectMode::kUpdateNothing: - *out = net::IsolationInfo::RedirectMode::kUpdateNothing; + case network::mojom::IsolationInfoRequestType::kOther: + *out = net::IsolationInfo::RequestType::kOther; return true; } return false; } -network::mojom::IsolationInfoRedirectMode EnumTraits< - network::mojom::IsolationInfoRedirectMode, - net::IsolationInfo::RedirectMode>::ToMojom(net::IsolationInfo::RedirectMode - redirect_mode) { - switch (redirect_mode) { - case net::IsolationInfo::RedirectMode::kUpdateTopFrame: - return network::mojom::IsolationInfoRedirectMode::kUpdateTopFrame; - case net::IsolationInfo::RedirectMode::kUpdateFrameOnly: - return network::mojom::IsolationInfoRedirectMode::kUpdateFrameOnly; - case net::IsolationInfo::RedirectMode::kUpdateNothing: - return network::mojom::IsolationInfoRedirectMode::kUpdateNothing; +network::mojom::IsolationInfoRequestType EnumTraits< + network::mojom::IsolationInfoRequestType, + net::IsolationInfo::RequestType>::ToMojom(net::IsolationInfo::RequestType + request_type) { + switch (request_type) { + case net::IsolationInfo::RequestType::kMainFrame: + return network::mojom::IsolationInfoRequestType::kMainFrame; + case net::IsolationInfo::RequestType::kSubFrame: + return network::mojom::IsolationInfoRequestType::kSubFrame; + case net::IsolationInfo::RequestType::kOther: + return network::mojom::IsolationInfoRequestType::kOther; } NOTREACHED(); - return network::mojom::IsolationInfoRedirectMode::kUpdateNothing; + return network::mojom::IsolationInfoRequestType::kOther; } bool StructTraits<network::mojom::IsolationInfoDataView, net::IsolationInfo>:: @@ -50,7 +50,7 @@ bool StructTraits<network::mojom::IsolationInfoDataView, net::IsolationInfo>:: base::Optional<url::Origin> top_frame_origin; base::Optional<url::Origin> frame_origin; net::SiteForCookies site_for_cookies; - net::IsolationInfo::RedirectMode redirect_mode; + net::IsolationInfo::RequestType request_type; if (!data.ReadTopFrameOrigin(&top_frame_origin)) { network::debug::SetDeserializationCrashKeyString("isolation_top_origin"); @@ -61,12 +61,12 @@ bool StructTraits<network::mojom::IsolationInfoDataView, net::IsolationInfo>:: return false; } if (!data.ReadSiteForCookies(&site_for_cookies) || - !data.ReadRedirectMode(&redirect_mode)) { + !data.ReadRequestType(&request_type)) { return false; } base::Optional<net::IsolationInfo> isolation_info = - net::IsolationInfo::CreateIfConsistent(redirect_mode, top_frame_origin, + net::IsolationInfo::CreateIfConsistent(request_type, top_frame_origin, frame_origin, site_for_cookies, data.opaque_and_non_transient()); if (!isolation_info) { diff --git a/chromium/services/network/public/cpp/isolation_info_mojom_traits.h b/chromium/services/network/public/cpp/isolation_info_mojom_traits.h index fee49ca73cf..44a123f8e8a 100644 --- a/chromium/services/network/public/cpp/isolation_info_mojom_traits.h +++ b/chromium/services/network/public/cpp/isolation_info_mojom_traits.h @@ -17,20 +17,20 @@ namespace mojo { template <> struct COMPONENT_EXPORT(NETWORK_CPP_BASE) - EnumTraits<network::mojom::IsolationInfoRedirectMode, - net::IsolationInfo::RedirectMode> { - static network::mojom::IsolationInfoRedirectMode ToMojom( - net::IsolationInfo::RedirectMode redirect_mode); - static bool FromMojom(network::mojom::IsolationInfoRedirectMode redirect_mode, - net::IsolationInfo::RedirectMode* out); + EnumTraits<network::mojom::IsolationInfoRequestType, + net::IsolationInfo::RequestType> { + static network::mojom::IsolationInfoRequestType ToMojom( + net::IsolationInfo::RequestType request_type); + static bool FromMojom(network::mojom::IsolationInfoRequestType request_type, + net::IsolationInfo::RequestType* out); }; template <> struct COMPONENT_EXPORT(NETWORK_CPP_BASE) StructTraits<network::mojom::IsolationInfoDataView, net::IsolationInfo> { - static net::IsolationInfo::RedirectMode redirect_mode( + static net::IsolationInfo::RequestType request_type( const net::IsolationInfo& input) { - return input.redirect_mode(); + return input.request_type(); } static const base::Optional<url::Origin>& top_frame_origin( diff --git a/chromium/services/network/public/cpp/isolation_info_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/isolation_info_mojom_traits_unittest.cc index f79d4a56526..7e2b034d1ce 100644 --- a/chromium/services/network/public/cpp/isolation_info_mojom_traits_unittest.cc +++ b/chromium/services/network/public/cpp/isolation_info_mojom_traits_unittest.cc @@ -24,21 +24,20 @@ TEST(IsolationInfoMojomTraitsTest, SerializeAndDeserialize) { net::IsolationInfo(), net::IsolationInfo::CreateTransient(), net::IsolationInfo::CreateOpaqueAndNonTransient(), - net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateTopFrame, kOrigin1, kOrigin1, - net::SiteForCookies::FromOrigin(kOrigin1)), - net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateFrameOnly, kOrigin1, - kOrigin2, net::SiteForCookies::FromOrigin(kOrigin1)), - net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateFrameOnly, kOrigin1, - kOrigin2, net::SiteForCookies()), - net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, kOrigin1, kOrigin1, - net::SiteForCookies::FromOrigin(kOrigin1)), - net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, url::Origin(), - url::Origin(), net::SiteForCookies()), + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kMainFrame, + kOrigin1, kOrigin1, + net::SiteForCookies::FromOrigin(kOrigin1)), + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kSubFrame, + kOrigin1, kOrigin2, + net::SiteForCookies::FromOrigin(kOrigin1)), + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kSubFrame, + kOrigin1, kOrigin2, net::SiteForCookies()), + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + kOrigin1, kOrigin1, + net::SiteForCookies::FromOrigin(kOrigin1)), + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + url::Origin(), url::Origin(), + net::SiteForCookies()), }; for (auto original : keys) { diff --git a/chromium/services/network/public/cpp/net_ipc_param_traits.cc b/chromium/services/network/public/cpp/net_ipc_param_traits.cc index bb2f1be0aa0..9567cfd9c8e 100644 --- a/chromium/services/network/public/cpp/net_ipc_param_traits.cc +++ b/chromium/services/network/public/cpp/net_ipc_param_traits.cc @@ -74,6 +74,8 @@ void ParamTraits<net::CertVerifyResult>::Write(base::Pickle* m, WriteParam(m, p.is_issued_by_known_root); WriteParam(m, p.is_issued_by_additional_trust_anchor); WriteParam(m, p.ocsp_result); + WriteParam(m, p.scts); + WriteParam(m, p.policy_compliance); } bool ParamTraits<net::CertVerifyResult>::Read(const base::Pickle* m, @@ -87,7 +89,8 @@ bool ParamTraits<net::CertVerifyResult>::Read(const base::Pickle* m, ReadParam(m, iter, &r->public_key_hashes) && ReadParam(m, iter, &r->is_issued_by_known_root) && ReadParam(m, iter, &r->is_issued_by_additional_trust_anchor) && - ReadParam(m, iter, &r->ocsp_result); + ReadParam(m, iter, &r->ocsp_result) && ReadParam(m, iter, &r->scts) && + ReadParam(m, iter, &r->policy_compliance); } void ParamTraits<net::CertVerifyResult>::Log(const param_type& p, @@ -95,26 +98,6 @@ void ParamTraits<net::CertVerifyResult>::Log(const param_type& p, l->append("<CertVerifyResult>"); } -void ParamTraits<net::ct::CTVerifyResult>::Write(base::Pickle* m, - const param_type& p) { - WriteParam(m, p.scts); - WriteParam(m, p.policy_compliance); - WriteParam(m, p.policy_compliance_required); -} - -bool ParamTraits<net::ct::CTVerifyResult>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return ReadParam(m, iter, &r->scts) && - ReadParam(m, iter, &r->policy_compliance) && - ReadParam(m, iter, &r->policy_compliance_required); -} - -void ParamTraits<net::ct::CTVerifyResult>::Log(const param_type& p, - std::string* l) { - l->append("<CTVerifyResult>"); -} - void ParamTraits<net::HashValue>::Write(base::Pickle* m, const param_type& p) { WriteParam(m, p.ToString()); } diff --git a/chromium/services/network/public/cpp/net_ipc_param_traits.h b/chromium/services/network/public/cpp/net_ipc_param_traits.h index c3835ff3efa..53f744155be 100644 --- a/chromium/services/network/public/cpp/net_ipc_param_traits.h +++ b/chromium/services/network/public/cpp/net_ipc_param_traits.h @@ -21,7 +21,6 @@ #include "net/base/request_priority.h" #include "net/cert/cert_verify_result.h" #include "net/cert/ct_policy_status.h" -#include "net/cert/ct_verify_result.h" #include "net/cert/signed_certificate_timestamp.h" #include "net/cert/signed_certificate_timestamp_and_status.h" #include "net/cert/x509_certificate.h" @@ -82,16 +81,6 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<net::CertVerifyResult> { }; template <> -struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<net::ct::CTVerifyResult> { - typedef net::ct::CTVerifyResult param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<net::HashValue> { typedef net::HashValue param_type; static void Write(base::Pickle* m, const param_type& p); diff --git a/chromium/services/network/public/cpp/network_connection_tracker_unittest.cc b/chromium/services/network/public/cpp/network_connection_tracker_unittest.cc index a4c324b4ed4..8eb730f2150 100644 --- a/chromium/services/network/public/cpp/network_connection_tracker_unittest.cc +++ b/chromium/services/network/public/cpp/network_connection_tracker_unittest.cc @@ -5,7 +5,7 @@ #include "services/network/public/cpp/network_connection_tracker.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "base/run_loop.h" #include "base/test/task_environment.h" diff --git a/chromium/services/network/public/cpp/network_ipc_param_traits.cc b/chromium/services/network/public/cpp/network_ipc_param_traits.cc index 61ebf3756ee..edab086e7d1 100644 --- a/chromium/services/network/public/cpp/network_ipc_param_traits.cc +++ b/chromium/services/network/public/cpp/network_ipc_param_traits.cc @@ -30,12 +30,6 @@ void ParamTraits<network::DataElement>::Write(base::Pickle* m, WriteParam(m, p.expected_modification_time()); break; } - case network::mojom::DataElementType::kBlob: { - WriteParam(m, p.blob_uuid()); - WriteParam(m, p.offset()); - WriteParam(m, p.length()); - break; - } case network::mojom::DataElementType::kDataPipe: { WriteParam(m, p.CloneDataPipeGetter().PassPipe().release()); break; @@ -86,18 +80,6 @@ bool ParamTraits<network::DataElement>::Read(const base::Pickle* m, expected_modification_time); return true; } - case network::mojom::DataElementType::kBlob: { - std::string blob_uuid; - uint64_t offset, length; - if (!ReadParam(m, iter, &blob_uuid)) - return false; - if (!ReadParam(m, iter, &offset)) - return false; - if (!ReadParam(m, iter, &length)) - return false; - r->SetToBlobRange(blob_uuid, offset, length); - return true; - } case network::mojom::DataElementType::kDataPipe: { mojo::MessagePipeHandle message_pipe; if (!ReadParam(m, iter, &message_pipe)) diff --git a/chromium/services/network/public/cpp/network_ipc_param_traits.h b/chromium/services/network/public/cpp/network_ipc_param_traits.h index b8ee874ba32..a898d3f7ad7 100644 --- a/chromium/services/network/public/cpp/network_ipc_param_traits.h +++ b/chromium/services/network/public/cpp/network_ipc_param_traits.h @@ -33,6 +33,7 @@ #include "services/network/public/mojom/blocked_by_response_reason.mojom-shared.h" #include "services/network/public/mojom/cors.mojom-shared.h" #include "services/network/public/mojom/fetch_api.mojom-shared.h" +#include "services/network/public/mojom/ip_address_space.mojom-shared.h" #include "services/network/public/mojom/trust_tokens.mojom-shared.h" #include "url/ipc/url_param_traits.h" #include "url/origin.h" @@ -95,9 +96,13 @@ IPC_ENUM_TRAITS_MAX_VALUE(network::mojom::CorsPreflightPolicy, IPC_ENUM_TRAITS_MAX_VALUE(network::mojom::BlockedByResponseReason, network::mojom::BlockedByResponseReason::kMaxValue) +IPC_ENUM_TRAITS_MAX_VALUE(network::mojom::IPAddressSpace, + network::mojom::IPAddressSpace::kMaxValue) + IPC_STRUCT_TRAITS_BEGIN(network::CorsErrorStatus) IPC_STRUCT_TRAITS_MEMBER(cors_error) IPC_STRUCT_TRAITS_MEMBER(failed_parameter) + IPC_STRUCT_TRAITS_MEMBER(resource_address_space) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(network::URLLoaderCompletionStatus) diff --git a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.cc b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.cc index 57be57a58f6..e0e75a8009b 100644 --- a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.cc +++ b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.cc @@ -11,24 +11,23 @@ bool StructTraits<network::mojom::NetworkIsolationKeyDataView, net::NetworkIsolationKey>:: Read(network::mojom::NetworkIsolationKeyDataView data, net::NetworkIsolationKey* out) { - base::Optional<url::Origin> top_frame_origin, frame_origin; - if (!data.ReadTopFrameOrigin(&top_frame_origin)) + base::Optional<url::Origin> top_frame_site, frame_site; + if (!data.ReadTopFrameSite(&top_frame_site)) return false; - if (!data.ReadFrameOrigin(&frame_origin)) + if (!data.ReadFrameSite(&frame_site)) return false; // A key is either fully empty or fully populated (for all fields relevant // given the flags set). The constructor verifies this, so if the top-frame // origin is populated, we call the full constructor, otherwise, the empty. - if (top_frame_origin.has_value()) { + if (top_frame_site.has_value()) { // We need a dummy value when the initiating_frame_origin is empty, // indicating that the flag to popuate it in the key was not set. - if (!frame_origin.has_value()) { + if (!frame_site.has_value()) { DCHECK(!base::FeatureList::IsEnabled( net::features::kAppendFrameOriginToNetworkIsolationKey)); - frame_origin = url::Origin(); + frame_site = url::Origin(); } - *out = net::NetworkIsolationKey(top_frame_origin.value(), - frame_origin.value()); + *out = net::NetworkIsolationKey(top_frame_site.value(), frame_site.value()); } else { *out = net::NetworkIsolationKey(); } diff --git a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.h b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.h index 59d44a4ab3c..80043f328e3 100644 --- a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.h +++ b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.h @@ -17,14 +17,14 @@ template <> struct COMPONENT_EXPORT(NETWORK_CPP_BASE) StructTraits<network::mojom::NetworkIsolationKeyDataView, net::NetworkIsolationKey> { - static const base::Optional<url::Origin>& top_frame_origin( + static const base::Optional<url::Origin>& top_frame_site( const net::NetworkIsolationKey& input) { - return input.GetTopFrameOrigin(); + return input.GetTopFrameSite(); } - static const base::Optional<url::Origin>& frame_origin( + static const base::Optional<url::Origin>& frame_site( const net::NetworkIsolationKey& input) { - return input.GetFrameOrigin(); + return input.GetFrameSite(); } static bool opaque_and_non_transient(const net::NetworkIsolationKey& input) { diff --git a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits_unittest.cc index 024ec4e5c82..4482335ea0b 100644 --- a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits_unittest.cc +++ b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits_unittest.cc @@ -48,7 +48,10 @@ TEST_F(NetworkIsolationKeyMojomTraitsWithFrameOriginTest, net::NetworkIsolationKey(), net::NetworkIsolationKey::CreateTransient(), net::NetworkIsolationKey::CreateOpaqueAndNonTransient(), net::NetworkIsolationKey(url::Origin::Create(GURL("http://a.test/")), - url::Origin::Create(GURL("http://b.test/")))}; + url::Origin::Create(GURL("http://b.test/"))), + net::NetworkIsolationKey( + url::Origin::Create(GURL("http://foo.a.test/")), + url::Origin::Create(GURL("http://bar.b.test/")))}; for (auto original : keys) { SCOPED_TRACE(original.ToDebugString()); @@ -56,29 +59,10 @@ TEST_F(NetworkIsolationKeyMojomTraitsWithFrameOriginTest, EXPECT_TRUE(mojo::test::SerializeAndDeserialize< network::mojom::NetworkIsolationKey>(&original, &copied)); EXPECT_EQ(original, copied); - EXPECT_EQ(original.GetTopFrameOrigin(), copied.GetTopFrameOrigin()); - EXPECT_EQ(original.GetFrameOrigin(), copied.GetFrameOrigin()); + EXPECT_EQ(original.GetTopFrameSite(), copied.GetTopFrameSite()); + EXPECT_EQ(original.GetFrameSite(), copied.GetFrameSite()); EXPECT_EQ(original.IsTransient(), copied.IsTransient()); } - - // Test case where registerable domain does not match origin passed in to - // NetworkIsolationKey's constructor. - - url::Origin origin_a = url::Origin::Create(GURL("http://a.foo.test/")); - url::Origin origin_b = url::Origin::Create(GURL("http://b.foo.test/")); - url::Origin domain = url::Origin::Create(GURL("http://foo.test/")); - net::NetworkIsolationKey original(origin_a, origin_b); - EXPECT_EQ(origin_a, original.GetTopFrameOrigin()); - EXPECT_EQ(origin_b, original.GetFrameOrigin()); - - net::NetworkIsolationKey copied; - EXPECT_TRUE( - mojo::test::SerializeAndDeserialize<network::mojom::NetworkIsolationKey>( - &original, &copied)); - EXPECT_EQ(original, copied); - - EXPECT_EQ(origin_a, copied.GetTopFrameOrigin()); - EXPECT_EQ(origin_b, copied.GetFrameOrigin()); } } // namespace mojo diff --git a/chromium/services/network/public/cpp/network_switches.cc b/chromium/services/network/public/cpp/network_switches.cc index 19c75f1e234..d1e0a09d9e0 100644 --- a/chromium/services/network/public/cpp/network_switches.cc +++ b/chromium/services/network/public/cpp/network_switches.cc @@ -87,6 +87,11 @@ const char kUnsafelyTreatInsecureOriginAsSecure[] = const char kAdditionalTrustTokenKeyCommitments[] = "additional-trust-token-key-commitments"; +// Allows the manual specification of a First-Party Set, as a comma-separated +// list of origins. The first origin in the list is treated as the owner of the +// set. +const char kUseFirstPartySet[] = "use-first-party-set"; + } // namespace switches } // namespace network diff --git a/chromium/services/network/public/cpp/network_switches.h b/chromium/services/network/public/cpp/network_switches.h index 41264fd8416..705971b3434 100644 --- a/chromium/services/network/public/cpp/network_switches.h +++ b/chromium/services/network/public/cpp/network_switches.h @@ -25,6 +25,7 @@ COMPONENT_EXPORT(NETWORK_CPP) extern const char kUnsafelyTreatInsecureOriginAsSecure[]; COMPONENT_EXPORT(NETWORK_CPP) extern const char kAdditionalTrustTokenKeyCommitments[]; +COMPONENT_EXPORT(NETWORK_CPP) extern const char kUseFirstPartySet[]; } // namespace switches diff --git a/chromium/services/network/public/cpp/parsed_headers.cc b/chromium/services/network/public/cpp/parsed_headers.cc index 2ce3770b3a6..2fb31bb4a91 100644 --- a/chromium/services/network/public/cpp/parsed_headers.cc +++ b/chromium/services/network/public/cpp/parsed_headers.cc @@ -31,13 +31,16 @@ mojom::ParsedHeadersPtr PopulateParsedHeaders( parsed_headers->cross_origin_opener_policy = ParseCrossOriginOpenerPolicy( *headers, parsed_headers->cross_origin_embedder_policy); + // TODO(https://crbug.com/1157917): we implement the change at + // https://github.com/whatwg/html/pull/6214 but all the class and function + // names are not yet updated. std::string origin_isolation; - if (headers->GetNormalizedHeader("Origin-Isolation", &origin_isolation)) + if (headers->GetNormalizedHeader("Origin-Agent-Cluster", &origin_isolation)) parsed_headers->origin_isolation = ParseOriginIsolation(origin_isolation); std::string accept_ch; if (headers->GetNormalizedHeader("Accept-CH", &accept_ch)) - parsed_headers->accept_ch = ParseAcceptCH(accept_ch); + parsed_headers->accept_ch = ParseClientHintsHeader(accept_ch); std::string accept_ch_lifetime; if (headers->GetNormalizedHeader("Accept-CH-Lifetime", &accept_ch_lifetime)) { @@ -45,6 +48,10 @@ mojom::ParsedHeadersPtr PopulateParsedHeaders( ParseAcceptCHLifetime(accept_ch_lifetime); } + std::string critical_ch; + if (headers->GetNormalizedHeader("Critical-CH", &critical_ch)) + parsed_headers->critical_ch = ParseClientHintsHeader(critical_ch); + return parsed_headers; } diff --git a/chromium/services/network/public/cpp/resource_request.cc b/chromium/services/network/public/cpp/resource_request.cc index 8f1b36b6bef..ee0150fbd6d 100644 --- a/chromium/services/network/public/cpp/resource_request.cc +++ b/chromium/services/network/public/cpp/resource_request.cc @@ -84,6 +84,7 @@ bool ResourceRequest::EqualsForTesting(const ResourceRequest& request) const { load_flags == request.load_flags && resource_type == request.resource_type && priority == request.priority && + devtools_stack_id == request.devtools_stack_id && should_reset_appcache == request.should_reset_appcache && is_external_request == request.is_external_request && cors_preflight_policy == request.cors_preflight_policy && @@ -118,6 +119,7 @@ bool ResourceRequest::EqualsForTesting(const ResourceRequest& request) const { devtools_request_id == request.devtools_request_id && is_signed_exchange_prefetch_cache_enabled == request.is_signed_exchange_prefetch_cache_enabled && + is_fetch_like_api == request.is_fetch_like_api && obey_origin_policy == request.obey_origin_policy && recursive_prefetch_token == request.recursive_prefetch_token && OptionalTrustedParamsEqualsForTesting(trusted_params, diff --git a/chromium/services/network/public/cpp/resource_request.h b/chromium/services/network/public/cpp/resource_request.h index 000ff16bbd6..fb4d30c234d 100644 --- a/chromium/services/network/public/cpp/resource_request.h +++ b/chromium/services/network/public/cpp/resource_request.h @@ -116,7 +116,9 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest { net::HttpRequestHeaders custom_proxy_post_cache_headers; base::Optional<base::UnguessableToken> fetch_window_id; base::Optional<std::string> devtools_request_id; + base::Optional<std::string> devtools_stack_id; bool is_signed_exchange_prefetch_cache_enabled = false; + bool is_fetch_like_api = false; bool obey_origin_policy = false; base::Optional<base::UnguessableToken> recursive_prefetch_token; base::Optional<TrustedParams> trusted_params; diff --git a/chromium/services/network/public/cpp/resource_request_body.cc b/chromium/services/network/public/cpp/resource_request_body.cc index 6c3df6d62f5..59c1b3566ff 100644 --- a/chromium/services/network/public/cpp/resource_request_body.cc +++ b/chromium/services/network/public/cpp/resource_request_body.cc @@ -57,17 +57,6 @@ void ResourceRequestBody::AppendFileRange( expected_modification_time); } -void ResourceRequestBody::AppendBlob(const std::string& uuid) { - AppendBlob(uuid, std::numeric_limits<uint64_t>::max()); -} - -void ResourceRequestBody::AppendBlob(const std::string& uuid, uint64_t length) { - DCHECK(EnableToAppendElement()); - - elements_.push_back(DataElement()); - elements_.back().SetToBlobRange(uuid, 0 /* offset */, length); -} - void ResourceRequestBody::AppendDataPipe( mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter) { DCHECK(EnableToAppendElement()); diff --git a/chromium/services/network/public/cpp/resource_request_body.h b/chromium/services/network/public/cpp/resource_request_body.h index 466d64f98fd..8c8517369f9 100644 --- a/chromium/services/network/public/cpp/resource_request_body.h +++ b/chromium/services/network/public/cpp/resource_request_body.h @@ -45,19 +45,6 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequestBody uint64_t length, const base::Time& expected_modification_time); - // Appends a blob. If the 2-parameter version is used, the resulting body can - // be read by Blink, which is needed when the body is sent to Blink, e.g., for - // service worker interception. The length must be size of the entire blob, - // not a subrange of it. If the length is unknown, use the 1-parameter - // version, but this means the body/blob won't be readable by Blink (that's OK - // if this ResourceRequestBody will only be sent to the browser process and - // won't be sent to Blink). - // - // TODO(crbug.com/846167): Remove these functions when NetworkService is - // enabled, as blobs are passed via AppendDataPipe in that case. - void AppendBlob(const std::string& uuid); - void AppendBlob(const std::string& uuid, uint64_t length); - void AppendDataPipe( mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter); diff --git a/chromium/services/network/public/cpp/schemeful_site_mojom_traits.cc b/chromium/services/network/public/cpp/schemeful_site_mojom_traits.cc new file mode 100644 index 00000000000..fb0a0957876 --- /dev/null +++ b/chromium/services/network/public/cpp/schemeful_site_mojom_traits.cc @@ -0,0 +1,29 @@ +// 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 "services/network/public/cpp/schemeful_site_mojom_traits.h" + +#include "url/origin.h" + +namespace mojo { + +bool StructTraits<network::mojom::SchemefulSiteDataView, net::SchemefulSite>:: + Read(network::mojom::SchemefulSiteDataView data, net::SchemefulSite* out) { + url::Origin site_as_origin; + if (!data.ReadSiteAsOrigin(&site_as_origin)) + return false; + + // The origin passed into this constructor may not match the + // `site_as_origin_` used as the internal representation of the schemeful + // site. However, a valid SchemefulSite's internal origin should result in a + // match if used to construct another SchemefulSite. Thus, if there is a + // mismatch here, we must indicate a failure. + net::SchemefulSite ss(site_as_origin); + bool success = site_as_origin == ss.site_as_origin_; + if (success) + *out = std::move(ss); + return success; +} + +} // namespace mojo diff --git a/chromium/services/network/public/cpp/schemeful_site_mojom_traits.h b/chromium/services/network/public/cpp/schemeful_site_mojom_traits.h new file mode 100644 index 00000000000..0848e1c3640 --- /dev/null +++ b/chromium/services/network/public/cpp/schemeful_site_mojom_traits.h @@ -0,0 +1,32 @@ +// 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 SERVICES_NETWORK_PUBLIC_CPP_SCHEMEFUL_SITE_MOJOM_TRAITS_H_ +#define SERVICES_NETWORK_PUBLIC_CPP_SCHEMEFUL_SITE_MOJOM_TRAITS_H_ + +#include "mojo/public/cpp/bindings/struct_traits.h" +#include "net/base/schemeful_site.h" +#include "services/network/public/mojom/schemeful_site.mojom-shared.h" +#include "url/mojom/origin_mojom_traits.h" + +namespace url { +class Origin; +} // namespace url + +namespace mojo { + +template <> +struct COMPONENT_EXPORT(NETWORK_CPP_BASE) + StructTraits<network::mojom::SchemefulSiteDataView, net::SchemefulSite> { + static const url::Origin& site_as_origin(const net::SchemefulSite& input) { + return input.site_as_origin_; + } + + static bool Read(network::mojom::SchemefulSiteDataView data, + net::SchemefulSite* out); +}; + +} // namespace mojo + +#endif // SERVICES_NETWORK_PUBLIC_CPP_SCHEMEFUL_SITE_MOJOM_TRAITS_H_ diff --git a/chromium/services/network/public/cpp/schemeful_site_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/schemeful_site_mojom_traits_unittest.cc new file mode 100644 index 00000000000..135c92a8c2b --- /dev/null +++ b/chromium/services/network/public/cpp/schemeful_site_mojom_traits_unittest.cc @@ -0,0 +1,61 @@ +// 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 "services/network/public/cpp/schemeful_site_mojom_traits.h" + +#include "base/stl_util.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "services/network/public/mojom/schemeful_site.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" +#include "url/origin.h" +#include "url/url_util.h" + +namespace network { +namespace { + +TEST(SchemefulSiteMojomTraitsTest, SerializeAndDeserialize) { + url::ScopedSchemeRegistryForTests scoped_registry; + url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST); + + std::vector<net::SchemefulSite> keys = { + net::SchemefulSite(), + net::SchemefulSite(url::Origin()), + net::SchemefulSite(url::Origin::Create(GURL("http://a.test"))), + net::SchemefulSite(url::Origin::Create(GURL("https://a.test"))), + net::SchemefulSite(url::Origin::Create(GURL("https://subdomain.a.test"))), + net::SchemefulSite(url::Origin::Create(GURL("https://127.0.0.1"))), + net::SchemefulSite(url::Origin::Create(GURL("https://127.0.0.1:5000"))), + net::SchemefulSite(url::Origin::Create(GURL("https://a.test:1337"))), + net::SchemefulSite(url::Origin::Create(GURL("file:///"))), + net::SchemefulSite(url::Origin::Create(GURL("file:///path"))), + net::SchemefulSite(url::Origin::Create(GURL("file://foo.test/path"))), + net::SchemefulSite( + url::Origin::Create(GURL("chrome-extension://abcdefghi"))), + net::SchemefulSite(url::Origin::Create(GURL("data:text/plain,foo")))}; + + for (auto original : keys) { + net::SchemefulSite copied; + EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SchemefulSite>( + &original, &copied)); + EXPECT_EQ(original, copied); + } +} + +TEST(SchemefulSiteMojomTraitsTest, DeserializeFailure) { + mojom::SchemefulSitePtr schemeful_site = mojom::SchemefulSite::New(); + // This origin could never be the internal `site_as_origin_` of a cromulent + // SchemefulSite, so should fail deserialization. + schemeful_site->site_as_origin = + url::Origin::Create(GURL("https://not.a.registrable.domain.test:1337")); + + std::vector<uint8_t> serialized = + mojom::SchemefulSite::Serialize(&schemeful_site); + + net::SchemefulSite deserialized; + EXPECT_FALSE(mojom::SchemefulSite::Deserialize(serialized, &deserialized)); +} + +} // namespace +} // namespace network diff --git a/chromium/services/network/public/cpp/simple_url_loader_unittest.cc b/chromium/services/network/public/cpp/simple_url_loader_unittest.cc index 4e6405ad99f..2b9a8a21413 100644 --- a/chromium/services/network/public/cpp/simple_url_loader_unittest.cc +++ b/chromium/services/network/public/cpp/simple_url_loader_unittest.cc @@ -28,7 +28,7 @@ #include "base/sequenced_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/test/test_timeouts.h" #include "base/time/time.h" @@ -703,9 +703,9 @@ class SimpleURLLoaderTest network::ResourceRequest::TrustedParams(); url::Origin request_origin = url::Origin::Create(url); resource_request->trusted_params->isolation_info = - net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, request_origin, - request_origin, net::SiteForCookies()); + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + request_origin, request_origin, + net::SiteForCookies()); return std::make_unique<SimpleLoaderTestHelper>(std::move(resource_request), GetParam()); } @@ -1852,7 +1852,7 @@ TEST_P(SimpleURLLoaderTest, UploadFileWithRetry) { EXPECT_EQ(1, test_helper->download_as_stream_retries()); } -TEST_P(SimpleURLLoaderTest, UploadNonexistantFile) { +TEST_P(SimpleURLLoaderTest, UploadNonexistentFile) { std::unique_ptr<SimpleLoaderTestHelper> test_helper = CreateHelperForURL(test_server_.GetURL("/echo"), "POST"); // Path to a file that doesn't exist. Start with the test directory just to diff --git a/chromium/services/network/public/cpp/supports_loading_mode/README.md b/chromium/services/network/public/cpp/supports_loading_mode/README.md new file mode 100644 index 00000000000..4760d0778d0 --- /dev/null +++ b/chromium/services/network/public/cpp/supports_loading_mode/README.md @@ -0,0 +1,2 @@ +This is a parser for the Supports-Loading-Mode header, described here: + https://github.com/jeremyroman/alternate-loading-modes/blob/gh-pages/opt-in.md diff --git a/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.cc b/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.cc new file mode 100644 index 00000000000..06220b11334 --- /dev/null +++ b/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.cc @@ -0,0 +1,78 @@ +// 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 "services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.h" + +#include "base/optional.h" +#include "base/ranges/algorithm.h" +#include "base/strings/string_piece.h" +#include "net/http/http_response_headers.h" +#include "net/http/structured_headers.h" +#include "services/network/public/mojom/supports_loading_mode.mojom.h" + +namespace network { + +namespace { + +constexpr base::StringPiece kSupportsLoadingMode = "Supports-Loading-Mode"; +constexpr struct KnownLoadingMode { + base::StringPiece token; + mojom::LoadingMode enumerator; +} kKnownLoadingModes[] = { + {"default", mojom::LoadingMode::kDefault}, + {"uncredentialed-prefetch", mojom::LoadingMode::kUncredentialedPrefetch}, + {"uncredentialed-prerender", mojom::LoadingMode::kUncredentialedPrerender}, +}; + +} // namespace + +mojom::SupportsLoadingModePtr ParseSupportsLoadingMode( + base::StringPiece header_value) { + // A parse error in the HTTP structured headers syntax is a parse error for + // the header value as a whole. + auto list = net::structured_headers::ParseList(header_value); + if (!list) + return nullptr; + + // The default loading mode is assumed to be supported. + std::vector<mojom::LoadingMode> modes{mojom::LoadingMode::kDefault}; + + for (const net::structured_headers::ParameterizedMember& member : *list) { + // No supported mode currently is specified as an inner list or takes + // parameters. + if (member.member_is_inner_list || !member.params.empty()) + continue; + + // All supported modes are tokens. + const net::structured_headers::ParameterizedItem& item = member.member[0]; + DCHECK(item.params.empty()); + if (!item.item.is_token()) + continue; + + // Each supported token maps 1:1 to an enumerator. + const auto& token = item.item.GetString(); + const auto* it = + base::ranges::find(kKnownLoadingModes, token, &KnownLoadingMode::token); + if (it == base::ranges::end(kKnownLoadingModes)) + continue; + + modes.push_back(it->enumerator); + } + + // Order and repetition are not significant. + // Canonicalize by making the vector sorted and unique. + base::ranges::sort(modes); + modes.erase(base::ranges::unique(modes), modes.end()); + return mojom::SupportsLoadingMode::New(std::move(modes)); +} + +mojom::SupportsLoadingModePtr ParseSupportsLoadingMode( + const net::HttpResponseHeaders& headers) { + std::string header_value; + if (!headers.GetNormalizedHeader(kSupportsLoadingMode, &header_value)) + return nullptr; + return ParseSupportsLoadingMode(header_value); +} + +} // namespace network diff --git a/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.h b/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.h new file mode 100644 index 00000000000..51dddf08bc4 --- /dev/null +++ b/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.h @@ -0,0 +1,39 @@ +// 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 SERVICES_NETWORK_PUBLIC_CPP_SUPPORTS_LOADING_MODE_SUPPORTS_LOADING_MODE_PARSER_H_ +#define SERVICES_NETWORK_PUBLIC_CPP_SUPPORTS_LOADING_MODE_SUPPORTS_LOADING_MODE_PARSER_H_ + +#include "base/component_export.h" +#include "base/strings/string_piece_forward.h" +#include "services/network/public/mojom/supports_loading_mode.mojom-forward.h" + +namespace net { +class HttpResponseHeaders; +} + +namespace network { + +// This parser is intended to run in a relatively unprivileged process, such as +// the network process or a renderer process. + +// Parse one or more supported loading modes from a string. +// +// Returns nullptr if the header syntax was invalid. +COMPONENT_EXPORT(NETWORK_CPP) +mojom::SupportsLoadingModePtr ParseSupportsLoadingMode( + base::StringPiece header_value); + +// Parse Supports-Loading-Modes from HTTP response headers. If multiple headers +// are found, they are assumed to be canonicalized by joining them with commas, +// as typical for HTTP. +// +// Returns nullptr if the header syntax was invalid. +COMPONENT_EXPORT(NETWORK_CPP) +mojom::SupportsLoadingModePtr ParseSupportsLoadingMode( + const net::HttpResponseHeaders& headers); + +} // namespace network + +#endif // SERVICES_NETWORK_PUBLIC_CPP_SUPPORTS_LOADING_MODE_SUPPORTS_LOADING_MODE_PARSER_H_ diff --git a/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser_unittest.cc b/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser_unittest.cc new file mode 100644 index 00000000000..87628c3093a --- /dev/null +++ b/chromium/services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser_unittest.cc @@ -0,0 +1,98 @@ +// 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 "services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.h" + +#include "base/strings/string_piece.h" +#include "net/http/http_response_headers.h" +#include "services/network/public/mojom/supports_loading_mode.mojom.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace network { +namespace { + +template <typename... ModeMatchers> +::testing::Matcher<mojom::SupportsLoadingModePtr> SupportedModesAre( + ModeMatchers&&... modes) { + return ::testing::Pointee(::testing::Field( + "supported_modes", &mojom::SupportsLoadingMode::supported_modes, + ::testing::UnorderedElementsAre(modes...))); +} + +TEST(SupportsLoadingModeParserTest, Valid) { + EXPECT_THAT(ParseSupportsLoadingMode(""), + SupportedModesAre(mojom::LoadingMode::kDefault)); + EXPECT_THAT(ParseSupportsLoadingMode("default"), + SupportedModesAre(mojom::LoadingMode::kDefault)); + EXPECT_THAT(ParseSupportsLoadingMode("uncredentialed-prefetch"), + SupportedModesAre(mojom::LoadingMode::kDefault, + mojom::LoadingMode::kUncredentialedPrefetch)); + EXPECT_THAT(ParseSupportsLoadingMode( + "uncredentialed-prefetch, uncredentialed-prefetch"), + SupportedModesAre(mojom::LoadingMode::kDefault, + mojom::LoadingMode::kUncredentialedPrefetch)); + EXPECT_THAT(ParseSupportsLoadingMode( + "uncredentialed-prerender, uncredentialed-prefetch"), + SupportedModesAre(mojom::LoadingMode::kDefault, + mojom::LoadingMode::kUncredentialedPrerender, + mojom::LoadingMode::kUncredentialedPrefetch)); +} + +TEST(SupportsLoadingModeParserTest, IgnoresUnknown) { + EXPECT_THAT(ParseSupportsLoadingMode("quantum-entanglement"), + SupportedModesAre(mojom::LoadingMode::kDefault)); + EXPECT_THAT( + ParseSupportsLoadingMode("quantum-entanglement, uncredentialed-prefetch"), + SupportedModesAre(mojom::LoadingMode::kDefault, + mojom::LoadingMode::kUncredentialedPrefetch)); + EXPECT_THAT(ParseSupportsLoadingMode("uncredentialed-prefetch; via=mars"), + SupportedModesAre(mojom::LoadingMode::kDefault)); + EXPECT_THAT(ParseSupportsLoadingMode("\"uncredentialed-prefetch\""), + SupportedModesAre(mojom::LoadingMode::kDefault)); + EXPECT_THAT(ParseSupportsLoadingMode("(uncredentialed-prefetch default)"), + SupportedModesAre(mojom::LoadingMode::kDefault)); +} + +TEST(SupportsLoadingModeParserTest, InvalidHttpStructuredHeaderList) { + EXPECT_TRUE(ParseSupportsLoadingMode("---------------").is_null()); + EXPECT_TRUE(ParseSupportsLoadingMode(",,").is_null()); +} + +TEST(SupportsLoadingModeParserTest, ValidFromResponseHeaders) { + EXPECT_TRUE(ParseSupportsLoadingMode( + *net::HttpResponseHeaders::TryToCreate("HTTP/1.1 200 OK\n")) + .is_null()); + EXPECT_THAT(ParseSupportsLoadingMode(*net::HttpResponseHeaders::TryToCreate( + "HTTP/1.1 200 OK\n" + "Supports-Loading-Mode: \n")), + SupportedModesAre(mojom::LoadingMode::kDefault)); + EXPECT_THAT(ParseSupportsLoadingMode(*net::HttpResponseHeaders::TryToCreate( + "HTTP/1.1 200 OK\n" + "supports-loading-mode: uncredentialed-prefetch\n")), + SupportedModesAre(mojom::LoadingMode::kDefault, + mojom::LoadingMode::kUncredentialedPrefetch)); + EXPECT_THAT(ParseSupportsLoadingMode(*net::HttpResponseHeaders::TryToCreate( + "HTTP/1.1 200 OK\n" + "supports-loading-mode: uncredentialed-prefetch\n")), + SupportedModesAre(mojom::LoadingMode::kDefault, + mojom::LoadingMode::kUncredentialedPrefetch)); + EXPECT_THAT(ParseSupportsLoadingMode(*net::HttpResponseHeaders::TryToCreate( + "HTTP/1.1 200 OK\n" + "Supports-Loading-Mode: default,\n" + " uncredentialed-prerender")), + SupportedModesAre(mojom::LoadingMode::kDefault, + mojom::LoadingMode::kUncredentialedPrerender)); + EXPECT_THAT(ParseSupportsLoadingMode(*net::HttpResponseHeaders::TryToCreate( + "HTTP/1.1 200 OK\n" + "Supports-Loading-Mode: uncredentialed-prefetch\n" + "Content-Type: text/html; charset=utf8\n" + "supports-loading-mode: uncredentialed-prerender\n")), + SupportedModesAre(mojom::LoadingMode::kDefault, + mojom::LoadingMode::kUncredentialedPrefetch, + mojom::LoadingMode::kUncredentialedPrerender)); +} + +} // namespace +} // namespace network diff --git a/chromium/services/network/trust_tokens/trust_token_http_headers.cc b/chromium/services/network/public/cpp/trust_token_http_headers.cc index 9a29a03306a..4436e846a68 100644 --- a/chromium/services/network/trust_tokens/trust_token_http_headers.cc +++ b/chromium/services/network/public/cpp/trust_token_http_headers.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 "services/network/trust_tokens/trust_token_http_headers.h" +#include "services/network/public/cpp/trust_token_http_headers.h" #include "base/no_destructor.h" #include "base/strings/string_piece.h" @@ -12,8 +12,9 @@ namespace network { const std::vector<base::StringPiece>& TrustTokensRequestHeaders() { static base::NoDestructor<std::vector<base::StringPiece>> headers{ {kTrustTokensRequestHeaderSecSignature, - kTrustTokensRequestHeaderSecSignedRedemptionRecord, + kTrustTokensRequestHeaderSecRedemptionRecord, kTrustTokensRequestHeaderSecTime, kTrustTokensSecTrustTokenHeader, + kTrustTokensSecTrustTokenVersionHeader, kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData}}; return *headers; } diff --git a/chromium/services/network/trust_tokens/trust_token_http_headers.h b/chromium/services/network/public/cpp/trust_token_http_headers.h index 4bb6247c946..ed6fcfb78f5 100644 --- a/chromium/services/network/trust_tokens/trust_token_http_headers.h +++ b/chromium/services/network/public/cpp/trust_token_http_headers.h @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SERVICES_NETWORK_TRUST_TOKENS_TRUST_TOKEN_HTTP_HEADERS_H_ -#define SERVICES_NETWORK_TRUST_TOKENS_TRUST_TOKEN_HTTP_HEADERS_H_ +#ifndef SERVICES_NETWORK_PUBLIC_CPP_TRUST_TOKEN_HTTP_HEADERS_H_ +#define SERVICES_NETWORK_PUBLIC_CPP_TRUST_TOKEN_HTTP_HEADERS_H_ #include <vector> +#include "base/component_export.h" #include "base/strings/string_piece_forward.h" namespace network { @@ -25,6 +26,11 @@ namespace network { // Record. constexpr char kTrustTokensSecTrustTokenHeader[] = "Sec-Trust-Token"; +// As a request header, provides the version of Trust Token being used in the +// Sec-Trust-Token header. +constexpr char kTrustTokensSecTrustTokenVersionHeader[] = + "Sec-Trust-Token-Version"; + // As a request header, provides a timestamp associated with a // particular Trust Tokens signature-bearing request. constexpr char kTrustTokensRequestHeaderSecTime[] = "Sec-Time"; @@ -34,10 +40,10 @@ constexpr char kTrustTokensRequestHeaderSecTime[] = "Sec-Time"; // collection of headers; and, optionally, the request's body). constexpr char kTrustTokensRequestHeaderSecSignature[] = "Sec-Signature"; -// As a request header, provides a Signed Redemption Record obtained from a -// prior issuance-and-redemption flow. -constexpr char kTrustTokensRequestHeaderSecSignedRedemptionRecord[] = - "Sec-Signed-Redemption-Record"; +// As a request header, provides aRedemption Record obtained from a prior +// issuance-and-redemption flow. +constexpr char kTrustTokensRequestHeaderSecRedemptionRecord[] = + "Sec-Redemption-Record"; // As a request header during the request signing operation, provides the list // of headers included in the signing data's canonical request data. An absent @@ -56,8 +62,9 @@ constexpr char kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData[] = // // In particular, this does *not* contain Signed-Headers because this header's // value is provided by the Trust Token API's client. +COMPONENT_EXPORT(NETWORK_CPP) const std::vector<base::StringPiece>& TrustTokensRequestHeaders(); } // namespace network -#endif // SERVICES_NETWORK_TRUST_TOKENS_TRUST_TOKEN_HTTP_HEADERS_H_ +#endif // SERVICES_NETWORK_PUBLIC_CPP_TRUST_TOKEN_HTTP_HEADERS_H_ diff --git a/chromium/services/network/public/cpp/trust_token_operation_authorization.h b/chromium/services/network/public/cpp/trust_token_operation_authorization.h index 6996e1f7f9f..fdcd559efdd 100644 --- a/chromium/services/network/public/cpp/trust_token_operation_authorization.h +++ b/chromium/services/network/public/cpp/trust_token_operation_authorization.h @@ -23,7 +23,7 @@ namespace network { // records") are persistent first-party identifiers in the context of the top // frame at redemption time. Since embedded third-party frames are on the other // side of a privacy boundary, we’d like to prohibit these third-party frames -// from having access to the redeeming-context SRRs without the top-level +// from having access to the redeeming-context RRs without the top-level // frame's explicit consent. constexpr bool DoesTrustTokenOperationRequireFeaturePolicy( mojom::TrustTokenOperationType type) { diff --git a/chromium/services/network/public/cpp/url_request_mojom_traits.cc b/chromium/services/network/public/cpp/url_request_mojom_traits.cc index d45b19b8f61..8626ff6086f 100644 --- a/chromium/services/network/public/cpp/url_request_mojom_traits.cc +++ b/chromium/services/network/public/cpp/url_request_mojom_traits.cc @@ -202,6 +202,7 @@ bool StructTraits< !data.ReadThrottlingProfileId(&out->throttling_profile_id) || !data.ReadFetchWindowId(&out->fetch_window_id) || !data.ReadDevtoolsRequestId(&out->devtools_request_id) || + !data.ReadDevtoolsStackId(&out->devtools_stack_id) || !data.ReadRecursivePrefetchToken(&out->recursive_prefetch_token)) { // Note that data.ReadTrustTokenParams is temporarily handled below. return false; @@ -241,6 +242,7 @@ bool StructTraits< out->is_revalidating = data.is_revalidating(); out->is_signed_exchange_prefetch_cache_enabled = data.is_signed_exchange_prefetch_cache_enabled(); + out->is_fetch_like_api = data.is_fetch_like_api(); out->obey_origin_policy = data.obey_origin_policy(); return true; } @@ -266,18 +268,20 @@ bool StructTraits<network::mojom::DataElementDataView, network::DataElement>:: network::debug::SetDeserializationCrashKeyString("data_element_path"); return false; } - if (!data.ReadBlobUuid(&out->blob_uuid_)) { - network::debug::SetDeserializationCrashKeyString("data_element_blob_uuid"); - return false; - } if (!data.ReadExpectedModificationTime(&out->expected_modification_time_)) { return false; } if (data.type() == network::mojom::DataElementType::kBytes) { - if (!data.ReadBuf(&out->buf_)) + mojo_base::BigBufferView big_buffer; + if (!data.ReadBuf(&big_buffer)) return false; - if (data.length() != out->buf_.size()) + // TODO(yoichio): Fix DataElementDataView::ReadBuf issue + // (crbug.com/1152664). + if (data.length() != big_buffer.data().size()) return false; + out->buf_.clear(); + out->buf_.insert(out->buf_.end(), big_buffer.data().begin(), + big_buffer.data().end()); } out->type_ = data.type(); out->data_pipe_getter_ = data.TakeDataPipeGetter< diff --git a/chromium/services/network/public/cpp/url_request_mojom_traits.h b/chromium/services/network/public/cpp/url_request_mojom_traits.h index ea302870d45..2568ed5e70e 100644 --- a/chromium/services/network/public/cpp/url_request_mojom_traits.h +++ b/chromium/services/network/public/cpp/url_request_mojom_traits.h @@ -10,6 +10,7 @@ #include "base/component_export.h" #include "base/memory/scoped_refptr.h" +#include "mojo/public/cpp/base/big_buffer_mojom_traits.h" #include "mojo/public/cpp/base/file_mojom_traits.h" #include "mojo/public/cpp/base/file_path_mojom_traits.h" #include "mojo/public/cpp/base/time_mojom_traits.h" @@ -241,10 +242,17 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) const network::ResourceRequest& request) { return request.devtools_request_id; } + static const base::Optional<std::string>& devtools_stack_id( + const network::ResourceRequest& request) { + return request.devtools_stack_id; + } static bool is_signed_exchange_prefetch_cache_enabled( const network::ResourceRequest& request) { return request.is_signed_exchange_prefetch_cache_enabled; } + static bool is_fetch_like_api(const network::ResourceRequest& request) { + return request.is_fetch_like_api; + } static bool obey_origin_policy(const network::ResourceRequest& request) { return request.obey_origin_policy; } @@ -308,15 +316,12 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) const network::DataElement& element) { return element.type_; } - static const std::vector<uint8_t>& buf(const network::DataElement& element) { - return element.buf_; + static mojo_base::BigBufferView buf(const network::DataElement& element) { + return mojo_base::BigBufferView(element.buf_); } static const base::FilePath& path(const network::DataElement& element) { return element.path_; } - static const std::string& blob_uuid(const network::DataElement& element) { - return element.blob_uuid_; - } static mojo::PendingRemote<network::mojom::DataPipeGetter> data_pipe_getter( const network::DataElement& element) { if (element.type_ != network::mojom::DataElementType::kDataPipe) diff --git a/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc index 7daeae3834a..abbd67bdd87 100644 --- a/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc +++ b/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc @@ -87,7 +87,7 @@ TEST(URLRequestMojomTraitsTest, Roundtrips_ResourceRequest) { original.trusted_params = ResourceRequest::TrustedParams(); original.trusted_params->isolation_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateTopFrame, + net::IsolationInfo::RequestType::kMainFrame, url::Origin::Create(original.url), url::Origin::Create(original.url), original.site_for_cookies); original.trusted_params->disable_secure_dns = true; diff --git a/chromium/services/network/public/cpp/web_sandbox_flags.h b/chromium/services/network/public/cpp/web_sandbox_flags.h index bafed168f62..6d3a4ad4a88 100644 --- a/chromium/services/network/public/cpp/web_sandbox_flags.h +++ b/chromium/services/network/public/cpp/web_sandbox_flags.h @@ -43,9 +43,7 @@ inline constexpr WebSandboxFlags operator~(WebSandboxFlags flags) { // The output of |ParseSandboxPolicy(input)|. struct WebSandboxFlagsParsingResult { - // The complement of the parsed WebSandboxFlags policy. - // TODO(arthursonzogni): Update the caller of ParseWebSandboxPolicy(). They - // should directly use the policy instead of its complement. + // The parsed WebSandboxFlags policy. mojom::WebSandboxFlags flags; // The console error message to be displayed for invalid input. Empty when diff --git a/chromium/services/network/public/mojom/BUILD.gn b/chromium/services/network/public/mojom/BUILD.gn index 81aecbe52ca..ada2742a9a1 100644 --- a/chromium/services/network/public/mojom/BUILD.gn +++ b/chromium/services/network/public/mojom/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//mojo/public/tools/bindings/mojom.gni") import("//net/features.gni") import("//services/network/public/cpp/features.gni") @@ -218,6 +219,34 @@ mojom("url_loader_base") { blink_cpp_typemaps = shared_typemaps } +# Make this a separate target to avoid a circular dependency. +mojom("mojom_schemeful_site") { + generate_java = true + sources = [ "schemeful_site.mojom" ] + + public_deps = [ "//url/mojom:url_mojom_origin" ] + + if (!is_ios) { + export_class_attribute_blink = "BLINK_PLATFORM_EXPORT" + export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1" + export_header_blink = "third_party/blink/public/platform/web_common.h" + } + + cpp_typemaps = [ + { + types = [ + { + mojom = "network.mojom.SchemefulSite" + cpp = "::net::SchemefulSite" + }, + ] + traits_headers = + [ "//services/network/public/cpp/schemeful_site_mojom_traits.h" ] + traits_public_deps = [ "//net" ] + }, + ] +} + # This target is split from "mojom" target as the lazy serialization may # cause problems. See https://crbug.com/822732. mojom("websocket_mojom") { @@ -312,6 +341,7 @@ mojom("cookies_mojom") { ] public_deps = [ + ":mojom_schemeful_site", "//components/content_settings/core/common:mojo_bindings", "//mojo/public/mojom/base", "//url/mojom:url_mojom_gurl", @@ -423,10 +453,11 @@ mojom("cookies_mojom") { types = [ { mojom = "network.mojom.CanonicalCookie" - cpp = "::blink::CanonicalCookie" + cpp = "::net::CanonicalCookie" }, ] - traits_headers = [ "//third_party/blink/renderer/platform/cookie/canonical_cookie_mojom_traits.h" ] + traits_headers = + [ "//services/network/public/cpp/cookie_manager_mojom_traits.h" ] }, ] blink_cpp_typemaps += shared_cpp_typemaps @@ -471,6 +502,7 @@ mojom("mojom") { "referrer_policy.mojom", "source_location.mojom", "ssl_config.mojom", + "supports_loading_mode.mojom", "tcp_socket.mojom", "tls_socket.mojom", "udp_socket.mojom", @@ -485,6 +517,7 @@ mojom("mojom") { ":cookies_mojom", ":mojom_ip_address", ":mojom_network_isolation_key", + ":mojom_schemeful_site", ":url_loader_base", ":websocket_mojom", "//mojo/public/mojom/base", @@ -512,11 +545,11 @@ mojom("mojom") { # This is only needed on desktop linux, but the defines make this difficult # because IS_CHROMECAST is not available in build/build_config.h. - if (is_linux && !is_chromeos) { + if (is_linux || is_lacros) { enabled_features += [ "needs_crypt_config" ] } - if (is_android || is_chromeos) { + if (is_android || is_ash) { enabled_features += [ "network_change_notifier_in_browser" ] } diff --git a/chromium/services/network/public/mojom/content_security_policy.mojom b/chromium/services/network/public/mojom/content_security_policy.mojom index 43778b9d765..1651aaecc6e 100644 --- a/chromium/services/network/public/mojom/content_security_policy.mojom +++ b/chromium/services/network/public/mojom/content_security_policy.mojom @@ -142,8 +142,8 @@ struct ContentSecurityPolicy { bool treat_as_public_address = false; // https://www.w3.org/TR/CSP3/#directive-sandbox - // This uses the convention: kAll means "everything is allowed". - WebSandboxFlags sandbox = WebSandboxFlags.kAll; + // This uses the convention: kNone means "nothing is disallowed". + WebSandboxFlags sandbox = WebSandboxFlags.kNone; ContentSecurityPolicyHeader header; @@ -211,4 +211,4 @@ union AllowCSPFromHeaderValue { // If the header value is invalid, an error message will be stored here. string error_message; -};
\ No newline at end of file +}; diff --git a/chromium/services/network/public/mojom/cookie_manager.mojom b/chromium/services/network/public/mojom/cookie_manager.mojom index efb5fa353ef..c95b843fc7f 100644 --- a/chromium/services/network/public/mojom/cookie_manager.mojom +++ b/chromium/services/network/public/mojom/cookie_manager.mojom @@ -6,6 +6,7 @@ module network.mojom; import "components/content_settings/core/common/content_settings.mojom"; import "mojo/public/mojom/base/time.mojom"; +import "services/network/public/mojom/schemeful_site.mojom"; import "url/mojom/url.mojom"; // Parameters for constructing a cookie manager. @@ -114,6 +115,7 @@ struct CookieOptions { CookieSameSiteContext same_site_cookie_context; bool update_access_time = true; bool return_excluded_cookies = false; + array<SchemefulSite>? full_party_context; }; // See net/cookies/canonical_cookie.{h,cc} for documentation. @@ -131,6 +133,10 @@ struct CanonicalCookie { CookieSameSite site_restrictions = NO_RESTRICTION; CookiePriority priority = MEDIUM; CookieSourceScheme source_scheme = kUnset; + bool same_party = false; + // -1 because of url::PORT_UNSPECIFIED + // url/third_party/mozilla/url_parse.h + int32 source_port = -1; }; struct CookieInclusionStatus { diff --git a/chromium/services/network/public/mojom/cors.mojom b/chromium/services/network/public/mojom/cors.mojom index 7651620feda..1bffa98f929 100644 --- a/chromium/services/network/public/mojom/cors.mojom +++ b/chromium/services/network/public/mojom/cors.mojom @@ -95,4 +95,8 @@ enum CorsError { // Cross origin redirect location contains credentials such as 'user:pass'. kRedirectContainsCredentials, + + // Request client is not secure and less private than the request target. + // See: https://wicg.github.io/cors-rfc1918. + kInsecurePrivateNetwork, }; diff --git a/chromium/services/network/public/mojom/host_resolver.mojom b/chromium/services/network/public/mojom/host_resolver.mojom index 221ae640d1b..64840089c7f 100644 --- a/chromium/services/network/public/mojom/host_resolver.mojom +++ b/chromium/services/network/public/mojom/host_resolver.mojom @@ -66,7 +66,7 @@ struct DnsConfigOverrides { int8 ndots = -1; // -1 for no override. // Time between retransmissions, see res_state.retrans. - mojo_base.mojom.TimeDelta? timeout; + mojo_base.mojom.TimeDelta? fallback_period; // Maximum number of attempts, see res_state.retry. int32 attempts = -1; // -1 for no override. @@ -163,6 +163,7 @@ enum DnsQueryType { TXT, PTR, SRV, + HTTPS, }; // Parameter-grouping struct for additional optional parameters for diff --git a/chromium/services/network/public/mojom/isolation_info.mojom b/chromium/services/network/public/mojom/isolation_info.mojom index eb009448e82..cc2571066b6 100644 --- a/chromium/services/network/public/mojom/isolation_info.mojom +++ b/chromium/services/network/public/mojom/isolation_info.mojom @@ -7,19 +7,19 @@ module network.mojom; import "services/network/public/mojom/site_for_cookies.mojom"; import "url/mojom/origin.mojom"; -// Mapped to net::IsolationInfo::RedirectMode, which is what consumers should +// Mapped to net::IsolationInfo::RequestType, which is what consumers should // be using instead of using this directly. -enum IsolationInfoRedirectMode { - kUpdateTopFrame, - kUpdateFrameOnly, - kUpdateNothing, +enum IsolationInfoRequestType { + kMainFrame, + kSubFrame, + kOther, }; // Mapped to net::IsolationInfo. struct IsolationInfo { // These fields should not be used directly, but rather through the mapped // net::IsolationInfo. - IsolationInfoRedirectMode redirect_mode; + IsolationInfoRequestType request_type; url.mojom.Origin? top_frame_origin; url.mojom.Origin? frame_origin; bool opaque_and_non_transient; diff --git a/chromium/services/network/public/mojom/network_context.mojom b/chromium/services/network/public/mojom/network_context.mojom index dfeaf3c49e3..0a09398cf50 100644 --- a/chromium/services/network/public/mojom/network_context.mojom +++ b/chromium/services/network/public/mojom/network_context.mojom @@ -5,8 +5,8 @@ module network.mojom; import "mojo/public/mojom/base/big_buffer.mojom"; -import "mojo/public/mojom/base/file.mojom"; import "mojo/public/mojom/base/file_path.mojom"; +import "mojo/public/mojom/base/read_only_file.mojom"; import "mojo/public/mojom/base/time.mojom"; import "mojo/public/mojom/base/unguessable_token.mojom"; import "mojo/public/mojom/base/values.mojom"; @@ -697,10 +697,6 @@ struct URLLoaderFactoryParams { // trusted source, it would be good to set this depending on the headers' // values, too. TrustTokenRedemptionPolicy trust_token_redemption_policy = kPotentiallyPermit; - - // TODO(lukasza): https://crbug.com/1056949: Remove this diagnostic aid once - // the bug is understood. - string debug_tag = "<uninitialized>"; }; // The |credentials| output parameter is given to URLRequest::SetAuth() @@ -818,7 +814,7 @@ interface NetworkContextClient { OnFileUploadRequested(int32 process_id, bool async, array<mojo_base.mojom.FilePath> file_paths) => - (int32 net_error, array<mojo_base.mojom.File> files); + (int32 net_error, array<mojo_base.mojom.ReadOnlyFile> files); // Checks if network error reports could be sent for the given origins. // Replies with the origins that are allowed. @@ -849,6 +845,15 @@ interface NetworkContextClient { // Notification that a trust anchor was used for the given user. [EnableIf=is_chromeos] OnTrustAnchorUsed(); + + // If it's supported by the implementation, attempts to provide a response to + // the given Trust Tokens issuance request through some kind of local + // mediation---i.e., probably by a method other than sending a web request + // directly to the issuer's server. In situations where it's not possible to + // answer the request, returns a status of kNotFound (see the request and + // response structs' comments for more information). + OnTrustTokenIssuanceDivertedToSystem(FulfillTrustTokenIssuanceRequest request) + => (FulfillTrustTokenIssuanceAnswer response); }; // Represents a distinct context for making network requests, with its own @@ -958,13 +963,15 @@ interface NetworkContext { => (bool is_upper_bound, int64 size_or_error); // Notifies the HttpCache of a renderer-level cache hit with |url| - // and |http_method|, with the top-level frame of the containing page - // being on origin |top_frame_origin|. + // and |http_method|, with the network isolation key |key| and + // |is_subframe_document_resource| is true if this is a subframe navigation + // resource. // // This is being proxied by the browser because the renderer is unable to // directly interact with NetworkContext. NotifyExternalCacheHit(url.mojom.Url url, string http_method, - NetworkIsolationKey key); + NetworkIsolationKey key, + bool is_subframe_document_resource); // Clears the host cache. This will affect all NetworkContexts that share the // same HostResolved as the NetworkContext this is called on. @@ -1012,22 +1019,32 @@ interface NetworkContext { // Queues a report via the Reporting API. |type| describes the type of report // (as well as what data will contained in |body|). |group| specifies the // endpoint group that the report will be delivered to. |url| indicates the - // URL of the resource that the report describes; |user_agent| may be - // provided, or will be automatically generated if omitted; |body| holds the - // contents of the report. + // URL of the resource that the report describes; |network_isolation_key| + // indicates the NetworkIsolationKey associated with the request, and is + // used for both looking up the appropriately scoped reporting information + // and for sending the report. |user_agent| may be provided, or will be + // automatically generated if omitted; |body| holds the contents of the + // report. // // Note that this queued report will never be delivered if no reporting - // endpoint is registered for this |url|. + // endpoint is registered for this |url| with the provided + // |network_isolation_key|. // // Spec: https://w3c.github.io/reporting/#concept-reports QueueReport(string type, string group, url.mojom.Url url, + NetworkIsolationKey network_isolation_key, string? user_agent, mojo_base.mojom.DictionaryValue body); // Queues a signed exchange report. - QueueSignedExchangeReport(SignedExchangeReport report); + // + // Note that this queued report will never be delivered if no reporting + // endpoint matching is registered for with the provided + // |network_isolation_key|. + QueueSignedExchangeReport(SignedExchangeReport report, + NetworkIsolationKey network_isolation_key); // Closes all open connections within this context. CloseAllConnections() => (); @@ -1291,12 +1308,16 @@ interface NetworkContext { // Checks the given certificate against the CertVerifier and CTVerifier. This // implementation is currently specific for use by Signed Exchange. + // + // |network_isolation_key| must be the NetworkIsolationKey associated with the + // underlying resource load, and is used foy any reports generated as a result + // of verifying the cert. VerifyCertForSignedExchange(X509Certificate certificate, url.mojom.Url url, + NetworkIsolationKey network_isolation_key, string ocsp_response, string sct_list) => (int32 error_code, - CertVerifyResult cv_result, - CTVerifyResult ct_result); + CertVerifyResult cv_result); // Parses response headers and returns a structured version to the caller. // This call originates from the browser process. Used for navigations when diff --git a/chromium/services/network/public/mojom/network_isolation_key.mojom b/chromium/services/network/public/mojom/network_isolation_key.mojom index 3930d02cefc..9b85e28e681 100644 --- a/chromium/services/network/public/mojom/network_isolation_key.mojom +++ b/chromium/services/network/public/mojom/network_isolation_key.mojom @@ -8,9 +8,13 @@ import "url/mojom/origin.mojom"; // Mapped to net::NetworkIsolationKey. struct NetworkIsolationKey { + // These are not true origins, but rather schemeful sites | origins, depending + // on scheme. + // // Keeping optional to allow clients that do not populate top frame origin. // TODO(crbug.com/910721): This will eventually always be populated. - url.mojom.Origin? top_frame_origin; - url.mojom.Origin? frame_origin; + url.mojom.Origin? top_frame_site; + url.mojom.Origin? frame_site; + bool opaque_and_non_transient; }; diff --git a/chromium/services/network/public/mojom/network_param.mojom b/chromium/services/network/public/mojom/network_param.mojom index 41f31038dfe..8f9f5d0be6f 100644 --- a/chromium/services/network/public/mojom/network_param.mojom +++ b/chromium/services/network/public/mojom/network_param.mojom @@ -14,9 +14,6 @@ struct AuthCredentials; struct CertVerifyResult; [Native] -struct CTVerifyResult; - -[Native] struct HttpResponseHeaders; struct HttpVersion { diff --git a/chromium/services/network/public/mojom/network_service.mojom b/chromium/services/network/public/mojom/network_service.mojom index de31c22dcfa..0c7e1a852d1 100644 --- a/chromium/services/network/public/mojom/network_service.mojom +++ b/chromium/services/network/public/mojom/network_service.mojom @@ -152,6 +152,10 @@ struct HttpAuthDynamicParams { // Indicates whether the GSSAPI library should be loaded. Only supported on // Chrome OS. bool allow_gssapi_library_load = true; + + // True if Basic authentication challenges should be allowed for non-secure + // HTTP responses. + bool basic_over_http_enabled = true; }; // Values for configuring OSCrypt. diff --git a/chromium/services/network/public/mojom/network_service_test.mojom b/chromium/services/network/public/mojom/network_service_test.mojom index 895e88cd6d2..e7a99de8784 100644 --- a/chromium/services/network/public/mojom/network_service_test.mojom +++ b/chromium/services/network/public/mojom/network_service_test.mojom @@ -117,4 +117,9 @@ interface NetworkServiceTest { // policy oid. [Sync] SetEVPolicy(array<uint8, 32> fingerprint_sha256, string policy_oid) => (); + + // Gets the current count of entries in the preloaded First-Party sets + // mapping. Note that each entry is a registered domain mapped to its owner. + [Sync] + GetPreloadedFirstPartySetEntriesCount() => (int64 entries); }; diff --git a/chromium/services/network/public/mojom/parsed_headers.mojom b/chromium/services/network/public/mojom/parsed_headers.mojom index ab10d3cfd16..6bba67b26b7 100644 --- a/chromium/services/network/public/mojom/parsed_headers.mojom +++ b/chromium/services/network/public/mojom/parsed_headers.mojom @@ -41,4 +41,25 @@ struct ParsedHeaders { // Parsed Accept-CH-Lifetime value, if any. Zero if missing or on parse error. mojo_base.mojom.TimeDelta accept_ch_lifetime; + + // The parsed Critical-CH response header. + // + // Should be parsed in the same way (i.e. same tokens and grammar) as the + // Accept-CH header. + // + // Indicates that if these headers are missing from the Client Hint + // preference storage but not otherwise blocked from being sent, the + // appropriate preferences should be stored and the request should be + // restarted (with the new client hint preferences taken into account). + // + // All hints present in the Critical-CH header SHOULD also be present in the + // Accept-CH header. + // + // An empty list means the headers value was empty (i.e. 'Critical-CH:'). A + // null value means the header was not present in the response. These are + // both functionally a no-op. + // + // For more information, see: + // https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability#section-3 + array<WebClientHintsType>? critical_ch; }; diff --git a/chromium/services/network/public/mojom/schemeful_site.mojom b/chromium/services/network/public/mojom/schemeful_site.mojom new file mode 100644 index 00000000000..1861c7c493f --- /dev/null +++ b/chromium/services/network/public/mojom/schemeful_site.mojom @@ -0,0 +1,15 @@ +// 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. + +module network.mojom; + +import "url/mojom/origin.mojom"; + +// Class which represents a scheme and eTLD+1 for an origin. +// Mapped to net::SchemefulSite. +struct SchemefulSite { + // Underlying origin of the schemeful site. This is not an arbitrary origin. + // It must either be an opaque origin, or a scheme + eTLD+1 + default port. + url.mojom.Origin site_as_origin; +}; diff --git a/chromium/services/network/public/mojom/supports_loading_mode.mojom b/chromium/services/network/public/mojom/supports_loading_mode.mojom new file mode 100644 index 00000000000..60357c6ed7f --- /dev/null +++ b/chromium/services/network/public/mojom/supports_loading_mode.mojom @@ -0,0 +1,28 @@ +// 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. + +module network.mojom; + +// A loading mode which may be supported by the document resource. +enum LoadingMode { + // The ordinary loading mode. + kDefault, + + // A mode in which a response fetched without credentials and with other + // measures taken to obscure the user's identity may be used for navigation, + // even if credentials exist. The document should, if necessary, personalize + // itself when it loads, dynamically. + kUncredentialedPrefetch, + + // A mode similar to (and implying the requirements of) + // kUncredentialedPrefetch, but where the document may load and execute + // script before navigation. The document should, if necessary, personalize + // itself after loading when credentials become available, dynamically. + kUncredentialedPrerender, +}; + +// https://github.com/jeremyroman/alternate-loading-modes/blob/gh-pages/opt-in.md +struct SupportsLoadingMode { + array<LoadingMode> supported_modes; +}; diff --git a/chromium/services/network/public/mojom/trust_tokens.mojom b/chromium/services/network/public/mojom/trust_tokens.mojom index c138d2c8b21..c9df1b062f0 100644 --- a/chromium/services/network/public/mojom/trust_tokens.mojom +++ b/chromium/services/network/public/mojom/trust_tokens.mojom @@ -7,6 +7,20 @@ module network.mojom; import "url/mojom/origin.mojom"; import "mojo/public/mojom/base/time.mojom"; +// TrustTokenProtocolVersion enumerates the versions of Trust Token that the +// client knows about. Different versions represent different configuration +// flows, data structure meanings, etc and may require clearing the database +// due to incompatibilities. kTrustTokenV2Pmb and kTrustTokenV2Voprf can +// safely be supported at the same time, as they use the same underlying data +// model; they just use different cryptosystems to generate tokens' signatures. +// TODO(crbug/1133969): Schema versioning needs to be implemented for future +// versions that need to clear the database on schema changes. +enum TrustTokenProtocolVersion { + kTrustTokenV2Pmb, + kTrustTokenV2Voprf, +}; + + // TrustTokenOperationStatus enumerates (an incomplete collection of) outcomes // for a Trust Tokens protocol operation. // @@ -41,6 +55,10 @@ enum TrustTokenOperationStatus { // The operation failed for some other reason. kUnknownError, + + // The operation was executed by a means other than sending the resource + // request at hand, so there's no response to provide for the request. + kOperationSuccessfullyFulfilledLocally, }; // Trust Tokens operation parameterization @@ -55,37 +73,37 @@ enum TrustTokenOperationType { // tokens signed by an issuing server. kIssuance, // In "redemption", clients exchange single-use server-signed tokens for - // multi-use Signed Redemption Records. + // multi-use Redemption Records. kRedemption, - // The "signing" operation involves attaching Signed Redemption Records to - // outgoing requests, and potentially signing the requests with a key bound to - // the attached SRR, to represent trust from the issuer. + // The "signing" operation involves attaching Redemption Records to outgoing + // requests, and potentially signing the requests with a key bound to the + // attached RR, to represent trust from the issuer. kSigning, }; // TrustTokenRefreshPolicy specifies, during redemption, whether to respect or -// ignore cached Signed Redemption Records. +// ignore cached Redemption Records. enum TrustTokenRefreshPolicy { - // If there's a valid SRR already stored, return early and don't attempt to - // redeem a token for a new SRR. + // If there's a valid RR already stored, return early and don't attempt to + // redeem a token for a new RR. kUseCached, - // Even there's a valid SRR already stored, attempt to redeem a token for a - // new SRR, overwriting the stored SRR. + // Even there's a valid RR already stored, attempt to redeem a token for a + // new RR, overwriting the stored RR. kRefresh, }; // TrustTokenSignRequestData specifies how to construct a request signature (or -// none) during the "signed redemption record attachment and request signing" -// protocol step. +// none) during the "redemption record attachment and request signing" protocol +// step. enum TrustTokenSignRequestData { - // Just attach a Signed Redemption Record (SRR), not an additional signature - // over request data. + // Just attach a Redemption Record (RR), not an additional signature over + // request data. kOmit, - // In addition to an SRR, attach a signature over a canonical request data + // In addition to an RR, attach a signature over a canonical request data // structure comprising a collection of request headers and some additional // metadata (see the explainer). kHeadersOnly, - // In addition to an SRR, attach a signature over a canonical request data + // In addition to an RR, attach a signature over a canonical request data // structure comprising a collection of request headers, some additional // contents of the request, and some additional metadata (see the explainer). kInclude, @@ -98,8 +116,8 @@ struct TrustTokenParams { TrustTokenOperationType type; // Required exactly when "type" is "kRedemption"; specifies whether the - // caller wishes to use a cached Signed Redemption Record (SRR) if available - // or redeem a new token, evicting the SRR currently stored. + // caller wishes to use a cached Redemption Record (RR) if available or + // redeem a new token, evicting the RR currently stored. TrustTokenRefreshPolicy refresh_policy = kUseCached; // The remaining members are used only when "type" is "kSigning": these @@ -160,6 +178,13 @@ struct TrustTokenVerificationKey { }; struct TrustTokenKeyCommitmentResult { + // |protocol_version| is the Trust Token version that this key commitment is + // for. + TrustTokenProtocolVersion protocol_version; + + // |id| is the ID for this key commitment. + int32 id; + // |batch_size| is the issuer's number of tokens it wishes the client // to request per Trust Tokens issuance operation. int32 batch_size; @@ -168,9 +193,72 @@ struct TrustTokenKeyCommitmentResult { // keys. array<TrustTokenVerificationKey> keys; - // |signed_redemption_record_verification_key| is an Ed25519 public key that - // can be used to verify Signed Redemption Record (SRR) signatures - // subsequently provided by the issuer. - string signed_redemption_record_verification_key; + // |request_issuance_locally_on| specifies operating systems on which to + // divert issuance requests for this issuer to the system (i.e. to request + // "platform-provided" tokens) + enum Os { + kAndroid, + }; + array<Os> request_issuance_locally_on; + + // When specifying that the browser should attempt local issuance on at least + // one operating system, issuers could benefit from a couple different + // fallback behaviors depending on their particular requirements. + // + // |unavailable_local_issuance_fallback|'s value specifies what action to take + // when both of the following hold simultaneously: + // (1) local issuance is specified on at least one OS (i.e. + // |request_issuance_locally_on| is nonempty) and + // (2) we're not on any of the specified OSes. + enum UnavailableLocalIssuanceFallback { + // If we're not on a matching OS, instead attempt a standard web + // issuance request against the issuance request's destination URL. + kWebIssuance, + // If we're not on a matching OS, just fail the issuance request. + kReturnWithError, + }; + UnavailableLocalIssuanceFallback unavailable_local_issuance_fallback; +}; + +// Struct FulfillTrustTokenIssuanceRequest represents a Trust Tokens issuance +// request intended to be satisfied in a manner other than the standard direct +// resource request to the issuer's server. It contains "the same information" +// as a Trust-Tokens-over-HTTP request. +struct FulfillTrustTokenIssuanceRequest { + // |issuer| is the Trust Tokens issuer corresponding to this Trust Tokens + // issuance operation. Like all Trust Tokens issuer origins, this should be + // both + // - potentially trustworthy and + // - HTTP or HTTPS. + url.mojom.Origin issuer; + // |request| is a base64-encoded issuance request (in other words, a value + // that could serve as to the Sec-Trust-Token request header in a Trust + // Tokens-over-HTTP issuance request). + string request; }; +// Struct FulfillTrustTokenIssuanceAnswer represents a Trust Tokens issuance +// response obtained in a manner other than the standard direct resource +// request to the issuer's server. It contains "the same information" as a +// Trust-Tokens-over-HTTP response. +// +// Note: We can't call this "FulfillTrustTokenIssuanceResponse" if we want a +// "FulfillTrustTokenIssuance" method in C++-to-Java interfaces down the line, +// because the Java bindings append the suffix "Response" when generating +// callback names. +struct FulfillTrustTokenIssuanceAnswer { + enum Status { + kOk, + // It wasn't possible to route the issuance operation to the specified + // token issuer. + kNotFound, + // Some other error occurred. + kUnknownError + }; + Status status; + + // If |status| is kOk, |response| will contain a value intended to be + // interpreted identically to a Trust Tokens-over-HTTP Sec-Trust-Token + // response header. Otherwise, its value is indeterminate. + string response; +}; diff --git a/chromium/services/network/public/mojom/url_loader.mojom b/chromium/services/network/public/mojom/url_loader.mojom index ef862c8aefc..8f1834ec677 100644 --- a/chromium/services/network/public/mojom/url_loader.mojom +++ b/chromium/services/network/public/mojom/url_loader.mojom @@ -59,17 +59,13 @@ enum URLRequestReferrerPolicy { enum DataElementType { kUnknown = -1, - // Only used for Upload with Network Service as of now: kDataPipe, kChunkedDataPipe, kReadOnceStream, + kBytes, - // Used for Upload when Network Service is disabled: - kBlob, + // TODO(https://crbug.com/1132362): Remove this. kFile, - - // Commonly used in every case: - kBytes, }; // Options that may only be set on URLRequests passed to a URLLoaderFactory @@ -138,10 +134,6 @@ struct URLRequest { // |request_initiator| indicates the origin initiating the resource request. // - // |request_initiator| can be null for browser-initiated requests (e.g. - // navigations initiated via omnibox or bookmarks, internal subresource - // requests like fetching the SafeBrowsing data, etc.). - // // For all requests initiated via web (both subresource requests and // navigations), |request_initiator| should always be set to the origin of // the frame (or worker) that has initiated the request. This is true even @@ -151,6 +143,14 @@ struct URLRequest { // process on behalf of a web origin (e.g. as is the case for PaymentRequest // API). // + // |request_initiator| should be omitted (i.e. set to base::nullopt) for + // browser-initiated requests (e.g. navigations initiated via omnibox or + // bookmarks, internal subresource requests like fetching the SafeBrowsing + // data, etc.). Various security features may treat browser-initiated + // requests in a special way - for example in such requests 1) the special + // `Sec-Fetch-Site: none` request header is sent, 2) http responses are not + // blocked based on their Cross-Origin-Resource-Policy header, etc. + // // SECURITY NOTE: Factories with |process_id| set to |kBrowserProcessId| do // not enforce |request_initiator_origin_lock| and instead rely on the // factory user to ensure that a valid, non-nullopt |request_initiator| is @@ -375,12 +375,21 @@ struct URLRequest { // renderer. string? devtools_request_id; + // A V8 stack id string describing where the request was initiated. DevTools + // can use this to display the initiator call stack when debugging a process + // that later intercepts the request, e.g., in a service worker fetch event + // handler. + string? devtools_stack_id; + // True for prefetch requests when SignedExchangePrefetchCacheForNavigations // feature is enabled by flags or SignedExchangeSubresourcePrefetch feature is // enabled by flags, or OriginTrial. TODO(horo): Remove this when these // features are enabled by default. bool is_signed_exchange_prefetch_cache_enabled; + // True for XHR, Fetch, and EventSource. + bool is_fetch_like_api; + // If set, the network service will attempt to retrieve the appropriate origin // policy, if necessary, and attach it to the ResourceResponseHead. // Spec: https://wicg.github.io/origin-policy/ @@ -427,12 +436,9 @@ struct DataElement { DataElementType type; // For kBytes. - array<uint8> buf; + mojo_base.mojom.BigBuffer buf; // For kFile mojo_base.mojom.FilePath path; - // For kBlob - // TODO(richard.li): Deprecate this once NetworkService is fully shipped. - string blob_uuid; // For kDataPipe pending_remote<network.mojom.DataPipeGetter>? data_pipe_getter; // For kChunkedDataPipe diff --git a/chromium/services/network/public/mojom/websocket.mojom b/chromium/services/network/public/mojom/websocket.mojom index a9f92f3fb49..3b38ab47b1a 100644 --- a/chromium/services/network/public/mojom/websocket.mojom +++ b/chromium/services/network/public/mojom/websocket.mojom @@ -60,6 +60,15 @@ interface WebSocketHandshakeClient { // Notify the renderer that the browser has started an opening handshake. OnOpeningHandshakeStarted(WebSocketHandshakeRequest request); + // Called when the WebSocket connection has failed. + // |message| may contain a human-readable explanation of the error, but may be + // empty. + // |net_error| contains a network error code, which will be |ERR_FAILED| for + // WebSocket-level protocol errors that do not have their own error code. + // |response_code| contains the HTTP status code that caused the failure, if + // it was caused by an unexpected status code, or else is -1. + OnFailure(string message, int32 net_error, int32 response_code); + // Called when the connection is established. // |response| may contain cookie-related headers when the client has // an access to raw cookie information. diff --git a/chromium/services/network/quic_transport.cc b/chromium/services/network/quic_transport.cc index bf83fa193af..79b4ba48c63 100644 --- a/chromium/services/network/quic_transport.cc +++ b/chromium/services/network/quic_transport.cc @@ -149,11 +149,11 @@ class QuicTransport::Stream final { } ~Stream() { - if (!incoming_ && !outgoing_) { + auto* stream = incoming_ ? incoming_ : outgoing_; + if (!stream) { return; } - transport_->transport_->session()->ResetStream( - id_, quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED); + stream->Reset(quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED); } private: @@ -207,8 +207,8 @@ class QuicTransport::Stream final { } DCHECK_EQ(result, MOJO_RESULT_OK); - bool send_result = outgoing_->Write(quiche::QuicheStringPiece( - reinterpret_cast<const char*>(data), available)); + bool send_result = outgoing_->Write( + absl::string_view(reinterpret_cast<const char*>(data), available)); if (!send_result) { // TODO(yhirano): Handle this failure. readable_->EndReadData(0); @@ -516,15 +516,13 @@ void QuicTransport::OnIncomingBidirectionalStreamAvailable() { sizeof(options), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 256 * 1024}; if (mojo::CreateDataPipe(&options, &writable_for_outgoing, &readable_for_outgoing) != MOJO_RESULT_OK) { - transport_->session()->ResetStream( - stream->id(), quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED); + stream->Reset(quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED); // TODO(yhirano): Error the entire connection. return; } if (mojo::CreateDataPipe(&options, &writable_for_incoming, &readable_for_incoming) != MOJO_RESULT_OK) { - transport_->session()->ResetStream( - stream->id(), quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED); + stream->Reset(quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED); // TODO(yhirano): Error the entire connection. return; } @@ -559,8 +557,7 @@ void QuicTransport::OnIncomingUnidirectionalStreamAvailable() { sizeof(options), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 256 * 1024}; if (mojo::CreateDataPipe(&options, &writable_for_incoming, &readable_for_incoming) != MOJO_RESULT_OK) { - transport_->session()->ResetStream( - stream->id(), quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED); + stream->Reset(quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED); // TODO(yhirano): Error the entire connection. return; } diff --git a/chromium/services/network/quic_transport_unittest.cc b/chromium/services/network/quic_transport_unittest.cc index 07243209c99..23d588c063a 100644 --- a/chromium/services/network/quic_transport_unittest.cc +++ b/chromium/services/network/quic_transport_unittest.cc @@ -9,7 +9,7 @@ #include "base/rand_util.h" #include "base/stl_util.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "net/cert/mock_cert_verifier.h" #include "net/dns/mock_host_resolver.h" diff --git a/chromium/services/network/resource_scheduler/DIR_METADATA b/chromium/services/network/resource_scheduler/DIR_METADATA new file mode 100644 index 00000000000..2107bb97d49 --- /dev/null +++ b/chromium/services/network/resource_scheduler/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Network>NetworkQuality" +}
\ No newline at end of file diff --git a/chromium/services/network/resource_scheduler/OWNERS b/chromium/services/network/resource_scheduler/OWNERS index bd5f1d8a351..c3b8dc2f4f9 100644 --- a/chromium/services/network/resource_scheduler/OWNERS +++ b/chromium/services/network/resource_scheduler/OWNERS @@ -1,4 +1,2 @@ tbansal@chromium.org ryansturm@chromium.org - -# COMPONENT: Internals>Network>NetworkQuality
\ No newline at end of file diff --git a/chromium/services/network/resource_scheduler/resource_scheduler.cc b/chromium/services/network/resource_scheduler/resource_scheduler.cc index e738be0ff6b..e8984482ab2 100644 --- a/chromium/services/network/resource_scheduler/resource_scheduler.cc +++ b/chromium/services/network/resource_scheduler/resource_scheduler.cc @@ -1270,10 +1270,6 @@ class ResourceScheduler::Client ideal_duration_to_wait); } - // Tracks if the main HTML parser has reached the body which marks the end of - // layout-blocking resources. - // This is disabled and the is always true when kRendererSideResourceScheduler - // is enabled. RequestQueue pending_requests_; RequestSet in_flight_requests_; diff --git a/chromium/services/network/restricted_cookie_manager.cc b/chromium/services/network/restricted_cookie_manager.cc index 9c1e99cfef2..6a4ef88516e 100644 --- a/chromium/services/network/restricted_cookie_manager.cc +++ b/chromium/services/network/restricted_cookie_manager.cc @@ -385,10 +385,12 @@ void RestrictedCookieManager::SetCanonicalCookie( GURL::SchemeIsCryptographic(origin_.scheme()) ? net::CookieSourceScheme::kSecure : net::CookieSourceScheme::kNonSecure; - auto sanitized_cookie = std::make_unique<net::CanonicalCookie>( + auto sanitized_cookie = net::CanonicalCookie::FromStorage( cookie.Name(), cookie.Value(), cookie.Domain(), cookie.Path(), now, cookie.ExpiryDate(), now, cookie.IsSecure(), cookie.IsHttpOnly(), - cookie.SameSite(), cookie.Priority(), source_scheme); + cookie.SameSite(), cookie.Priority(), cookie.IsSameParty(), source_scheme, + origin_.port()); + DCHECK(sanitized_cookie); net::CanonicalCookie cookie_copy = *sanitized_cookie; net::CookieOptions options = diff --git a/chromium/services/network/restricted_cookie_manager_unittest.cc b/chromium/services/network/restricted_cookie_manager_unittest.cc index d91c0c563ef..a322cdf090e 100644 --- a/chromium/services/network/restricted_cookie_manager_unittest.cc +++ b/chromium/services/network/restricted_cookie_manager_unittest.cc @@ -8,7 +8,7 @@ #include "base/bind.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/time/time.h" @@ -241,11 +241,11 @@ class RestrictedCookieManagerTest const char* path, bool secure = true) { CHECK(SetCanonicalCookie( - net::CanonicalCookie(name, value, domain, path, base::Time(), - base::Time(), base::Time(), /* secure = */ secure, - /* httponly = */ false, - net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_DEFAULT), + net::CanonicalCookie( + name, value, domain, path, base::Time(), base::Time(), base::Time(), + /* secure = */ secure, + /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION, + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false), "https", /* can_modify_httponly = */ true)); } @@ -255,11 +255,11 @@ class RestrictedCookieManagerTest const char* domain, const char* path) { CHECK(SetCanonicalCookie( - net::CanonicalCookie(name, value, domain, path, base::Time(), - base::Time(), base::Time(), /* secure = */ true, - /* httponly = */ true, - net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_DEFAULT), + net::CanonicalCookie( + name, value, domain, path, base::Time(), base::Time(), base::Time(), + /* secure = */ true, + /* httponly = */ true, net::CookieSameSite::NO_RESTRICTION, + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false), "https", /* can_modify_httponly = */ true)); } @@ -569,7 +569,7 @@ TEST_P(RestrictedCookieManagerTest, SetCanonicalCookie) { "new-name", "new-value", "example.com", "/", base::Time(), base::Time(), base::Time(), /* secure = */ true, /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_DEFAULT), + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false), GURL("https://example.com/test/"), GURL("https://example.com"), url::Origin::Create(GURL("https://example.com")))); @@ -593,7 +593,7 @@ TEST_P(RestrictedCookieManagerTest, SetCanonicalCookieHttpOnly) { "new-name", "new-value", "example.com", "/", base::Time(), base::Time(), base::Time(), /* secure = */ true, /* httponly = */ true, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_DEFAULT), + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false), GURL("https://example.com/test/"), GURL("https://example.com"), url::Origin::Create(GURL("https://example.com")))); @@ -640,7 +640,7 @@ TEST_P(RestrictedCookieManagerTest, SetCanonicalCookieFromWrongOrigin) { "new-name", "new-value", "not-example.com", "/", base::Time(), base::Time(), base::Time(), /* secure = */ true, /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_DEFAULT), + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false), GURL("https://not-example.com/test/"), GURL("https://example.com"), url::Origin::Create(GURL("https://example.com")))); ASSERT_TRUE(received_bad_message()); @@ -657,7 +657,7 @@ TEST_P(RestrictedCookieManagerTest, SetCanonicalCookieFromOpaqueOrigin) { "new-name", "new-value", "not-example.com", "/", base::Time(), base::Time(), base::Time(), /* secure = */ true, /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_DEFAULT), + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false), GURL("https://example.com/test/"), GURL("https://example.com"), url::Origin::Create(GURL("https://example.com")))); ASSERT_TRUE(received_bad_message()); @@ -670,7 +670,7 @@ TEST_P(RestrictedCookieManagerTest, SetCanonicalCookieWithMismatchingDomain) { "new-name", "new-value", "not-example.com", "/", base::Time(), base::Time(), base::Time(), /* secure = */ true, /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_DEFAULT), + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false), GURL("https://example.com/test/"), GURL("https://example.com"), url::Origin::Create(GURL("https://example.com")))); ASSERT_TRUE(received_bad_message()); @@ -832,14 +832,14 @@ TEST_P(RestrictedCookieManagerTest, SameSiteCookiesSpecialScheme) { "strict-cookie", "1", "example.com", "/", base::Time(), base::Time(), base::Time(), /* secure = */ false, /* httponly = */ false, net::CookieSameSite::STRICT_MODE, - net::COOKIE_PRIORITY_DEFAULT), + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false), https_url, chrome_url, https_origin)); EXPECT_TRUE(sync_service_->SetCanonicalCookie( - net::CanonicalCookie("lax-cookie", "1", "example.com", "/", base::Time(), - base::Time(), base::Time(), /* secure = */ false, - /* httponly = */ false, - net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_DEFAULT), + net::CanonicalCookie( + "lax-cookie", "1", "example.com", "/", base::Time(), base::Time(), + base::Time(), /* secure = */ false, + /* httponly = */ false, net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false), https_url, chrome_url, https_origin)); auto options = mojom::CookieManagerGetOptions::New(); @@ -858,14 +858,14 @@ TEST_P(RestrictedCookieManagerTest, SameSiteCookiesSpecialScheme) { "strict-cookie", "2", "example.com", "/", base::Time(), base::Time(), base::Time(), /* secure = */ false, /* httponly = */ false, net::CookieSameSite::STRICT_MODE, - net::COOKIE_PRIORITY_DEFAULT), + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false), http_url, chrome_url, http_origin)); EXPECT_FALSE(sync_service_->SetCanonicalCookie( - net::CanonicalCookie("lax-cookie", "2", "example.com", "/", base::Time(), - base::Time(), base::Time(), /* secure = */ false, - /* httponly = */ false, - net::CookieSameSite::LAX_MODE, - net::COOKIE_PRIORITY_DEFAULT), + net::CanonicalCookie( + "lax-cookie", "2", "example.com", "/", base::Time(), base::Time(), + base::Time(), /* secure = */ false, + /* httponly = */ false, net::CookieSameSite::LAX_MODE, + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false), http_url, chrome_url, http_origin)); options = mojom::CookieManagerGetOptions::New(); @@ -885,12 +885,12 @@ TEST_P(RestrictedCookieManagerTest, SameSiteCompatPairWarning_AppliedOnGet) { "name", "value", "example.com", "/", base::Time(), base::Time(), base::Time(), /* secure = */ true, /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_DEFAULT))); + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false))); ASSERT_TRUE(EnsureSetCanonicalCookie(net::CanonicalCookie( "name_legacy", "value", "example.com", "/", base::Time(), base::Time(), base::Time(), /* secure = */ true, /* httponly = */ false, net::CookieSameSite::UNSPECIFIED, - net::COOKIE_PRIORITY_DEFAULT))); + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false))); // Get cookies from the RestrictedCookieManager in a same-site context (should // not trigger warnings). @@ -992,12 +992,12 @@ TEST_P(RestrictedCookieManagerTest, SameSiteCompatPairWarning_HttpOnly) { "name", "value", "example.com", "/", base::Time(), base::Time(), base::Time(), /* secure = */ true, /* httponly = */ true, net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_DEFAULT))); + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false))); ASSERT_TRUE(EnsureSetCanonicalCookie(net::CanonicalCookie( "name_legacy", "value", "example.com", "/", base::Time(), base::Time(), base::Time(), /* secure = */ true, /* httponly = */ false, net::CookieSameSite::UNSPECIFIED, - net::COOKIE_PRIORITY_DEFAULT))); + net::COOKIE_PRIORITY_DEFAULT, /* same_party = */ false))); // Get cookies from the RestrictedCookieManager in a cross-site context. { diff --git a/chromium/services/network/sct_auditing_cache_unittest.cc b/chromium/services/network/sct_auditing_cache_unittest.cc index fd6d8d14a0b..60d85275676 100644 --- a/chromium/services/network/sct_auditing_cache_unittest.cc +++ b/chromium/services/network/sct_auditing_cache_unittest.cc @@ -8,7 +8,6 @@ #include "base/memory/scoped_refptr.h" #include "base/metrics/field_trial_params.h" #include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "net/base/host_port_pair.h" #include "net/cert/sct_status_flags.h" @@ -22,6 +21,7 @@ #include "services/network/network_service.h" #include "services/network/public/cpp/features.h" #include "services/network/public/proto/sct_audit_report.pb.h" +#include "services/network/test/fake_test_cert_verifier_params_factory.h" #include "services/network/test/test_network_context_client.h" #include "services/network/test/test_url_loader_factory.h" @@ -50,10 +50,16 @@ class SCTAuditingCacheTest : public testing::Test { protected: void InitNetworkContext() { + mojom::NetworkContextParamsPtr params = mojom::NetworkContextParams::New(); + // Use a dummy CertVerifier that always passes cert verification, since + // these unittests don't need to test CertVerifier behavior. + params->cert_verifier_params = + FakeTestCertVerifierParamsFactory::GetCertVerifierParams(); + network_context_ = std::make_unique<NetworkContext>( network_service_.get(), network_context_remote_.BindNewPipeAndPassReceiver(), - mojom::NetworkContextParams::New()); + std::move(params)); // A NetworkContextClient is needed for embedder notifications to work. mojo::PendingRemote<network::mojom::NetworkContextClient> diff --git a/chromium/services/network/session_cleanup_cookie_store_unittest.cc b/chromium/services/network/session_cleanup_cookie_store_unittest.cc index 46ccd9bcb48..a48339456fd 100644 --- a/chromium/services/network/session_cleanup_cookie_store_unittest.cc +++ b/chromium/services/network/session_cleanup_cookie_store_unittest.cc @@ -68,10 +68,10 @@ class SessionCleanupCookieStoreTest : public testing::Test { const std::string& domain, const std::string& path, base::Time creation) { - store_->AddCookie(net::CanonicalCookie(name, value, domain, path, creation, - creation, base::Time(), false, false, - net::CookieSameSite::NO_RESTRICTION, - net::COOKIE_PRIORITY_DEFAULT)); + store_->AddCookie(net::CanonicalCookie( + name, value, domain, path, creation, creation, base::Time(), false, + false, net::CookieSameSite::NO_RESTRICTION, + net::COOKIE_PRIORITY_DEFAULT, false)); } void DestroyStore() { diff --git a/chromium/services/network/tcp_bound_socket_unittest.cc b/chromium/services/network/tcp_bound_socket_unittest.cc index c6800ff89a9..e18accf5620 100644 --- a/chromium/services/network/tcp_bound_socket_unittest.cc +++ b/chromium/services/network/tcp_bound_socket_unittest.cc @@ -11,7 +11,7 @@ #include "base/bind.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "build/build_config.h" #include "mojo/public/cpp/bindings/pending_remote.h" diff --git a/chromium/services/network/tcp_socket_unittest.cc b/chromium/services/network/tcp_socket_unittest.cc index 9e65857c518..f9fb17dc755 100644 --- a/chromium/services/network/tcp_socket_unittest.cc +++ b/chromium/services/network/tcp_socket_unittest.cc @@ -8,12 +8,12 @@ #include <vector> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/check_op.h" #include "base/location.h" #include "base/macros.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/thread.h" #include "build/build_config.h" diff --git a/chromium/services/network/test_mojo_proxy_resolver_factory.cc b/chromium/services/network/test_mojo_proxy_resolver_factory.cc index a583744e02a..b91ac2899fc 100644 --- a/chromium/services/network/test_mojo_proxy_resolver_factory.cc +++ b/chromium/services/network/test_mojo_proxy_resolver_factory.cc @@ -5,7 +5,7 @@ #include "services/network/test_mojo_proxy_resolver_factory.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/check.h" namespace network { diff --git a/chromium/services/network/tls_client_socket_unittest.cc b/chromium/services/network/tls_client_socket_unittest.cc index 4c13918e9d3..23a2930f733 100644 --- a/chromium/services/network/tls_client_socket_unittest.cc +++ b/chromium/services/network/tls_client_socket_unittest.cc @@ -12,7 +12,7 @@ #include "base/check_op.h" #include "base/macros.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/thread.h" #include "mojo/public/cpp/bindings/pending_receiver.h" diff --git a/chromium/services/network/transitional_url_loader_factory_owner_unittest.cc b/chromium/services/network/transitional_url_loader_factory_owner_unittest.cc index e3169d6f592..388672163ec 100644 --- a/chromium/services/network/transitional_url_loader_factory_owner_unittest.cc +++ b/chromium/services/network/transitional_url_loader_factory_owner_unittest.cc @@ -9,7 +9,7 @@ #include "base/message_loop/message_pump_type.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/thread.h" #include "net/test/embedded_test_server/default_handlers.h" diff --git a/chromium/services/network/trust_tokens/BUILD.gn b/chromium/services/network/trust_tokens/BUILD.gn index 2e105004a31..ce25b0ad8df 100644 --- a/chromium/services/network/trust_tokens/BUILD.gn +++ b/chromium/services/network/trust_tokens/BUILD.gn @@ -30,13 +30,16 @@ source_set("trust_tokens") { "has_trust_tokens_answerer.h", "in_memory_trust_token_persister.cc", "in_memory_trust_token_persister.h", + "local_trust_token_operation_delegate.h", + "local_trust_token_operation_delegate_impl.cc", + "local_trust_token_operation_delegate_impl.h", + "operating_system_matching.cc", + "operating_system_matching.h", "operation_timing_request_helper_wrapper.cc", "operation_timing_request_helper_wrapper.h", "pending_trust_token_store.cc", "pending_trust_token_store.h", "scoped_boringssl_bytes.h", - "signed_redemption_record_serialization.cc", - "signed_redemption_record_serialization.h", "sqlite_trust_token_persister.cc", "sqlite_trust_token_persister.h", "suitable_trust_token_origin.cc", @@ -45,8 +48,6 @@ source_set("trust_tokens") { "trust_token_client_data_canonicalization.h", "trust_token_database_owner.cc", "trust_token_database_owner.h", - "trust_token_http_headers.cc", - "trust_token_http_headers.h", "trust_token_key_commitment_controller.cc", "trust_token_key_commitment_controller.h", "trust_token_key_commitment_getter.h", @@ -58,6 +59,7 @@ source_set("trust_tokens") { "trust_token_key_filtering.h", "trust_token_operation_metrics_recorder.cc", "trust_token_operation_metrics_recorder.h", + "trust_token_parameterization.cc", "trust_token_parameterization.h", "trust_token_persister.h", "trust_token_request_canonicalizer.cc", @@ -116,6 +118,7 @@ source_set("test_support") { "//net", "//net:test_support", "//net/traffic_annotation:test_support", + "//services/network/public/cpp", "//services/network/public/mojom", "//testing/gtest", "//url", @@ -133,8 +136,8 @@ source_set("tests") { "ed25519_trust_token_request_signer_unittest.cc", "expiry_inspecting_record_expiry_delegate_unittest.cc", "has_trust_tokens_answerer_unittest.cc", + "local_trust_token_operation_delegate_impl_unittest.cc", "pending_trust_token_store_unittest.cc", - "signed_redemption_record_serialization_unittest.cc", "sqlite_trust_token_persister_unittest.cc", "suitable_trust_token_origin_unittest.cc", "trust_token_client_data_canonicalization_unittest.cc", diff --git a/chromium/services/network/trust_tokens/OWNERS b/chromium/services/network/trust_tokens/OWNERS index 53f0470b863..19528245d31 100644 --- a/chromium/services/network/trust_tokens/OWNERS +++ b/chromium/services/network/trust_tokens/OWNERS @@ -1,3 +1,4 @@ +davidvc@chromium.org csharrison@chromium.org svaldez@chromium.org asanka@chromium.org diff --git a/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer.cc b/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer.cc index 9492f86758e..a73b32383a5 100644 --- a/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer.cc +++ b/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer.cc @@ -29,13 +29,23 @@ BoringsslTrustTokenIssuanceCryptographer:: ~BoringsslTrustTokenIssuanceCryptographer() = default; bool BoringsslTrustTokenIssuanceCryptographer::Initialize( + mojom::TrustTokenProtocolVersion issuer_configured_version, int issuer_configured_batch_size) { if (!base::IsValueInRangeForNumericType<size_t>(issuer_configured_batch_size)) return false; + const TRUST_TOKEN_METHOD* method = nullptr; + switch (issuer_configured_version) { + case mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb: + method = TRUST_TOKEN_experiment_v2_pmb(); + break; + case mojom::TrustTokenProtocolVersion::kTrustTokenV2Voprf: + method = TRUST_TOKEN_experiment_v2_voprf(); + break; + } + ctx_ = bssl::UniquePtr<TRUST_TOKEN_CLIENT>(TRUST_TOKEN_CLIENT_new( - TRUST_TOKEN_experiment_v1(), - static_cast<size_t>(issuer_configured_batch_size))); + method, static_cast<size_t>(issuer_configured_batch_size))); return !!ctx_; } diff --git a/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer.h b/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer.h index 5a510b29c8b..cf6ab7dd666 100644 --- a/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer.h +++ b/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer.h @@ -22,7 +22,8 @@ class BoringsslTrustTokenIssuanceCryptographer ~BoringsslTrustTokenIssuanceCryptographer() override; // TrustTokenRequestIssuanceHelper::Cryptographer implementation: - bool Initialize(int issuer_configured_batch_size) override; + bool Initialize(mojom::TrustTokenProtocolVersion issuer_configured_version, + int issuer_configured_batch_size) override; bool AddKey(base::StringPiece key) override; base::Optional<std::string> BeginIssuance(size_t num_tokens) override; std::unique_ptr<UnblindedTokens> ConfirmIssuance( diff --git a/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer_unittest.cc b/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer_unittest.cc index c38b3aa27a0..6276aa98983 100644 --- a/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer_unittest.cc +++ b/chromium/services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer_unittest.cc @@ -13,14 +13,26 @@ namespace network { namespace { -std::string GenerateValidVerificationKey() { +enum KeyType { + kPmb, + kVoprf, +}; +std::string GenerateValidVerificationKey(KeyType key_type) { std::string verification(TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 'a'), signing(TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE, 'a'); size_t verification_len, signing_len; + const TRUST_TOKEN_METHOD* method; + switch (key_type) { + case kPmb: + method = TRUST_TOKEN_experiment_v2_pmb(); + break; + case kVoprf: + method = TRUST_TOKEN_experiment_v2_voprf(); + break; + } CHECK(TRUST_TOKEN_generate_key( - TRUST_TOKEN_experiment_v1(), - base::as_writable_bytes(base::make_span(signing)).data(), &signing_len, - signing.size(), + method, base::as_writable_bytes(base::make_span(signing)).data(), + &signing_len, signing.size(), base::as_writable_bytes(base::make_span(verification)).data(), &verification_len, verification.size(), /*id=*/0)); @@ -31,20 +43,40 @@ std::string GenerateValidVerificationKey() { } // namespace -TEST(BoringsslTrustTokenIssuanceCryptographer, RespectsKeyLimit) { - // Test that adding more than - // |kMaximumConcurrentlyValidTrustTokenVerificationKeys| many keys fails. This - // is essentially an integration test ensuring that - // kMaximumConcurrentlyValidTrustTokenVerificationKeys is no greater than - // BoringSSL's internally-configured maximum number of permitted keys. +TEST(BoringsslTrustTokenIssuanceCryptographer, RespectsKeyLimitPmb) { + // Test that adding more than the number of support keys fails. + BoringsslTrustTokenIssuanceCryptographer cryptographer; + ASSERT_TRUE(cryptographer.Initialize( + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb, + /*issuer_configured_batch_size=*/10)); + + size_t max_keys = TrustTokenMaxKeysForVersion( + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb); + for (size_t i = 0; i < max_keys; ++i) { + ASSERT_TRUE( + cryptographer.AddKey(GenerateValidVerificationKey(KeyType::kPmb))) + << i; + } + EXPECT_FALSE( + cryptographer.AddKey(GenerateValidVerificationKey(KeyType::kPmb))); +} + +TEST(BoringsslTrustTokenIssuanceCryptographer, RespectsKeyLimitVoprf) { + // Test that adding more than the number of support keys fails. BoringsslTrustTokenIssuanceCryptographer cryptographer; - ASSERT_TRUE(cryptographer.Initialize(/*issuer_configured_batch_size=*/10)); + ASSERT_TRUE(cryptographer.Initialize( + mojom::TrustTokenProtocolVersion::kTrustTokenV2Voprf, + /*issuer_configured_batch_size=*/10)); - for (size_t i = 0; i < kMaximumConcurrentlyValidTrustTokenVerificationKeys; - ++i) { - ASSERT_TRUE(cryptographer.AddKey(GenerateValidVerificationKey())) << i; + size_t max_keys = TrustTokenMaxKeysForVersion( + mojom::TrustTokenProtocolVersion::kTrustTokenV2Voprf); + for (size_t i = 0; i < max_keys; ++i) { + ASSERT_TRUE( + cryptographer.AddKey(GenerateValidVerificationKey(KeyType::kVoprf))) + << i; } - EXPECT_FALSE(cryptographer.AddKey(GenerateValidVerificationKey())); + EXPECT_FALSE( + cryptographer.AddKey(GenerateValidVerificationKey(KeyType::kVoprf))); } } // namespace network diff --git a/chromium/services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.cc b/chromium/services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.cc index f184c9f5a72..07403051e24 100644 --- a/chromium/services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.cc +++ b/chromium/services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.cc @@ -8,7 +8,6 @@ #include "base/callback_helpers.h" #include "net/http/structured_headers.h" #include "services/network/trust_tokens/scoped_boringssl_bytes.h" -#include "services/network/trust_tokens/signed_redemption_record_serialization.h" #include "services/network/trust_tokens/trust_token_client_data_canonicalization.h" #include "services/network/trust_tokens/trust_token_parameterization.h" #include "third_party/boringssl/src/include/openssl/base.h" @@ -25,31 +24,26 @@ BoringsslTrustTokenRedemptionCryptographer:: ~BoringsslTrustTokenRedemptionCryptographer() = default; bool BoringsslTrustTokenRedemptionCryptographer::Initialize( - int issuer_configured_batch_size, - base::StringPiece signed_redemption_record_verification_key) { + mojom::TrustTokenProtocolVersion issuer_configured_version, + int issuer_configured_batch_size) { if (!base::IsValueInRangeForNumericType<size_t>(issuer_configured_batch_size)) return false; + const TRUST_TOKEN_METHOD* method = nullptr; + switch (issuer_configured_version) { + case mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb: + method = TRUST_TOKEN_experiment_v2_pmb(); + break; + case mojom::TrustTokenProtocolVersion::kTrustTokenV2Voprf: + method = TRUST_TOKEN_experiment_v2_voprf(); + break; + } + ctx_ = bssl::UniquePtr<TRUST_TOKEN_CLIENT>(TRUST_TOKEN_CLIENT_new( - TRUST_TOKEN_experiment_v1(), - static_cast<size_t>(issuer_configured_batch_size))); + method, static_cast<size_t>(issuer_configured_batch_size))); if (!ctx_) return false; - bssl::UniquePtr<EVP_PKEY> srr_verification_pkey(EVP_PKEY_new_raw_public_key( - EVP_PKEY_ED25519, - /*unused=*/nullptr, // Yes, this parameter is called "unused". - base::as_bytes(base::make_span(signed_redemption_record_verification_key)) - .data(), - signed_redemption_record_verification_key.size())); - if (!srr_verification_pkey) - return false; - - if (!TRUST_TOKEN_CLIENT_set_srr_key(ctx_.get(), - srr_verification_pkey.get())) { - return false; - } - return true; } @@ -101,21 +95,20 @@ BoringsslTrustTokenRedemptionCryptographer::ConfirmRedemption( if (!base::Base64Decode(response_header, &decoded_response)) return base::nullopt; - // |srr_body| and |srr_signature| together provide the information in the - // signed redemption record (see ConstructSignedRedemptionRecord's function - // comment for more information). - ScopedBoringsslBytes srr_body; - ScopedBoringsslBytes srr_signature; + // In TrustTokenV2, the entire RR is stored in the body field, and the + // signature field is unused in finish_redemption. + ScopedBoringsslBytes rr; + ScopedBoringsslBytes unused; if (!TRUST_TOKEN_CLIENT_finish_redemption( - ctx_.get(), srr_body.mutable_ptr(), srr_body.mutable_len(), - srr_signature.mutable_ptr(), srr_signature.mutable_len(), + ctx_.get(), rr.mutable_ptr(), rr.mutable_len(), unused.mutable_ptr(), + unused.mutable_len(), base::as_bytes(base::make_span(decoded_response)).data(), decoded_response.size())) { return base::nullopt; } - return ConstructSignedRedemptionRecord(srr_body.as_span(), - srr_signature.as_span()); + return std::string(reinterpret_cast<const char*>(rr.as_span().data()), + rr.as_span().size()); } } // namespace network diff --git a/chromium/services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.h b/chromium/services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.h index e252efc00eb..950c87bfd93 100644 --- a/chromium/services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.h +++ b/chromium/services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.h @@ -19,9 +19,8 @@ class BoringsslTrustTokenRedemptionCryptographer ~BoringsslTrustTokenRedemptionCryptographer() override; // TrustTokenRequestRedemptionHelper::Cryptographer implementation: - bool Initialize( - int issuer_configured_batch_size, - base::StringPiece signed_redemption_record_verification_key) override; + bool Initialize(mojom::TrustTokenProtocolVersion issuer_configured_version, + int issuer_configured_batch_size) override; base::Optional<std::string> BeginRedemption( TrustToken token, base::StringPiece verification_key, diff --git a/chromium/services/network/trust_tokens/ed25519_trust_token_request_signer.cc b/chromium/services/network/trust_tokens/ed25519_trust_token_request_signer.cc index cce9801f44d..2b244bd2c5d 100644 --- a/chromium/services/network/trust_tokens/ed25519_trust_token_request_signer.cc +++ b/chromium/services/network/trust_tokens/ed25519_trust_token_request_signer.cc @@ -38,4 +38,8 @@ bool Ed25519TrustTokenRequestSigner::Verify( verification_key.data()); } +std::string Ed25519TrustTokenRequestSigner::GetAlgorithmIdentifier() { + return "ed25519"; +} + } // namespace network diff --git a/chromium/services/network/trust_tokens/ed25519_trust_token_request_signer.h b/chromium/services/network/trust_tokens/ed25519_trust_token_request_signer.h index c8e75215640..ee78f23e407 100644 --- a/chromium/services/network/trust_tokens/ed25519_trust_token_request_signer.h +++ b/chromium/services/network/trust_tokens/ed25519_trust_token_request_signer.h @@ -26,6 +26,8 @@ class Ed25519TrustTokenRequestSigner bool Verify(base::span<const uint8_t> data, base::span<const uint8_t> signature, base::span<const uint8_t> verification_key) override; + + std::string GetAlgorithmIdentifier() override; }; } // namespace network diff --git a/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.cc b/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.cc index 49935756854..4533e1ee3f6 100644 --- a/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.cc +++ b/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.cc @@ -7,7 +7,6 @@ #include "components/cbor/reader.h" #include "components/cbor/values.h" #include "services/network/public/mojom/trust_tokens.mojom.h" -#include "services/network/trust_tokens/signed_redemption_record_serialization.h" #include "services/network/trust_tokens/suitable_trust_token_origin.h" #include "services/network/trust_tokens/trust_token_key_commitment_getter.h" #include "services/network/trust_tokens/trust_token_parameterization.h" @@ -15,77 +14,13 @@ namespace network { -namespace { - -const char kExpiryTimestampKey[] = "expiry-timestamp"; - -// Extracts the expiry timestamp from the given SRR body, a top-level CBOR map -// member of type integer with key "expiry-timestamp" and value an expiry in -// seconds since the UNIX epoch. (The Trust Tokens design doc is the current -// normative source for this field's format.) -// -// Returns |kTrustTokenDefaultRedemptionRecordExpiry| if the optional timestamp -// is not present in the SRR body; returns nullopt if the SRR body is not a map, -// or if it contains an "expiry-timestamp" member that is not an integer. -// -// Implementation note: We do this on the fly since it is pretty fast (a few -// microseconds) and expected to be done at most once per request. -// Pre-extracting the timestamp and storing it alongside the SRR would be a -// potential improvement if the control flow changes so that multiple SRRs are -// queried for expiry per protocol operation, but would introduce extra -// complexity: the SRRs could get out of sync with the timestamp bodies. -base::Optional<base::Time> ExtractExpiryTimestampOrDefault( - base::span<const uint8_t> srr_body) { - // Extract the expiry timestamp now so that downstream consumers don't have to - // deserialize CBOR repeatedly to inspect the timestamp. - // - // From the design doc: - // “expiry-timestamp”: <optional expiry timestamp, seconds past the Unix - // epoch> - base::Optional<cbor::Value> maybe_cbor = cbor::Reader::Read(srr_body); - if (!maybe_cbor || !maybe_cbor->is_map()) - return base::nullopt; - - cbor::Value expiry_timestamp_cbor_key(kExpiryTimestampKey, - cbor::Value::Type::STRING); - - auto it = maybe_cbor->GetMap().find(expiry_timestamp_cbor_key); - if (it == maybe_cbor->GetMap().end()) - return kTrustTokenDefaultRedemptionRecordExpiry; - if (!it->second.is_integer()) - return base::nullopt; - - return base::Time::UnixEpoch() + - base::TimeDelta::FromSeconds(it->second.GetInteger()); -} - -} // namespace - ExpiryInspectingRecordExpiryDelegate::ExpiryInspectingRecordExpiryDelegate( const SynchronousTrustTokenKeyCommitmentGetter* key_commitment_getter) : key_commitment_getter_(key_commitment_getter) {} bool ExpiryInspectingRecordExpiryDelegate::IsRecordExpired( - const SignedTrustTokenRedemptionRecord& record, + const TrustTokenRedemptionRecord& record, const SuitableTrustTokenOrigin& issuer) { - std::string record_body; - if (!ParseTrustTokenSignedRedemptionRecord(record.body(), &record_body, - /*signature_out=*/nullptr)) { - // Malformed record; say that it's expired so it gets deleted. - return true; - } - - base::Optional<base::Time> expiry_timestamp_or_error = - ExtractExpiryTimestampOrDefault( - base::as_bytes(base::make_span(record_body))); - if (!expiry_timestamp_or_error) { - // Malformed record; say that it's expired so it gets deleted. - return true; - } - - if (*expiry_timestamp_or_error <= base::Time::Now()) - return true; - mojom::TrustTokenKeyCommitmentResultPtr key_commitments = key_commitment_getter_->GetSync(issuer.origin()); @@ -93,14 +28,14 @@ bool ExpiryInspectingRecordExpiryDelegate::IsRecordExpired( // changed (due to data corruption) or the commitments changed (due to an // overwrite by the key commitments' producer, or due to data corruption). // - // In both cases, the SRR's associated token-issuance verification key isn't + // In both cases, the RR's associated token-issuance verification key isn't // present in the current key commitments we possess for the issuer, because // we don't have any key commitments whatsoever for the issuer: mark the // record as expired. if (!key_commitments) return true; - // Treat the SRR as expired if its associated token-issuance verification key + // Treat the RR as expired if its associated token-issuance verification key // (|token_verification_key|) is no longer present in its issuer's key // commitment. if (!std::any_of(key_commitments->keys.begin(), key_commitments->keys.end(), diff --git a/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.h b/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.h index 405287e75ce..27ebd8f5720 100644 --- a/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.h +++ b/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.h @@ -12,9 +12,8 @@ namespace network { class SynchronousTrustTokenKeyCommitmentGetter; -// ExpiryInspectingRecordExpiryDelegate considers a signed redemption record -// (SRR) to have expired if: -// - its expiry timestamp is not in the future, or +// ExpiryInspectingRecordExpiryDelegate considers a redemption record (RR) to +// have expired if: // - its associated trust token verification key is not present in the token's // issuer's most recent key commitment, or // - its issuer is not a valid Trust Tokens issuer (this means the record has @@ -24,7 +23,7 @@ class ExpiryInspectingRecordExpiryDelegate : public TrustTokenStore::RecordExpiryDelegate { public: // Constructs a new expiry delegate using |key_commitment_getter|, which must - // outlive this object, to inspect the most recent key commitment of each SRR. + // outlive this object, to inspect the most recent key commitment of each RR. explicit ExpiryInspectingRecordExpiryDelegate( const SynchronousTrustTokenKeyCommitmentGetter* key_commitment_getter); @@ -34,7 +33,7 @@ class ExpiryInspectingRecordExpiryDelegate const ExpiryInspectingRecordExpiryDelegate&) = delete; // TrustTokenStore::RecordExpiryDelegate implementation: - bool IsRecordExpired(const SignedTrustTokenRedemptionRecord& record, + bool IsRecordExpired(const TrustTokenRedemptionRecord& record, const SuitableTrustTokenOrigin& issuer) override; private: diff --git a/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate_unittest.cc b/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate_unittest.cc index 843def7ed5e..b1222c71def 100644 --- a/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate_unittest.cc +++ b/chromium/services/network/trust_tokens/expiry_inspecting_record_expiry_delegate_unittest.cc @@ -11,7 +11,6 @@ #include "components/cbor/writer.h" #include "services/network/public/mojom/trust_tokens.mojom.h" #include "services/network/trust_tokens/proto/public.pb.h" -#include "services/network/trust_tokens/signed_redemption_record_serialization.h" #include "services/network/trust_tokens/suitable_trust_token_origin.h" #include "services/network/trust_tokens/trust_token_key_commitment_getter.h" #include "services/network/trust_tokens/trust_token_parameterization.h" @@ -21,24 +20,6 @@ namespace network { namespace { -// Overwrites |record| with a serialized signed redemption record with -// just enough structure to have a well-formed expiry time of |expiry|. -// -// Reference: Trust Tokens design doc (currently the normative source for SRR -// structure), -// https://docs.google.com/document/d/1TNnya6B8pyomDK2F1R9CL3dY10OAmqWlnCxsWyOBDVQ/edit#heading=h.7mkzvhpqb8l5 -const char kExpiryTimestampKey[] = "expiry-timestamp"; -void SetRecordExpiry(SignedTrustTokenRedemptionRecord* record, - base::Time expiry) { - cbor::Value::MapValue map; - map[cbor::Value(kExpiryTimestampKey, cbor::Value::Type::STRING)] = - cbor::Value((expiry - base::Time::UnixEpoch()).InSeconds()); - - std::vector<uint8_t> empty_signature; - record->set_body(*ConstructSignedRedemptionRecord( - *cbor::Writer::Write(cbor::Value(std::move(map))), empty_signature)); -} - class FixedKeyCommitmentGetter : public SynchronousTrustTokenKeyCommitmentGetter { public: @@ -67,49 +48,7 @@ TEST(ExpiryInspectingRecordExpiryDelegate, ExpiresRecordWhenNoKeys) { FixedKeyCommitmentGetter getter(nullptr); // return no keys ExpiryInspectingRecordExpiryDelegate delegate(&getter); - SignedTrustTokenRedemptionRecord record; - - SetRecordExpiry(&record, base::Time::Now() + base::TimeDelta::FromMinutes(1)); - EXPECT_TRUE(delegate.IsRecordExpired( - record, - *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example")))); -} - -// A record with its expiry time in the past... should be marked as expired. -TEST(ExpiryInspectingRecordExpiryDelegate, ExpiresRecordWithPastExpiry) { - base::test::TaskEnvironment env( - base::test::TaskEnvironment::TimeSource::MOCK_TIME); - - auto commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - commitment_result->keys.push_back(mojom::TrustTokenVerificationKey::New( - "key", /*expiry=*/base::Time::Max())); - FixedKeyCommitmentGetter getter(std::move(commitment_result)); - ExpiryInspectingRecordExpiryDelegate delegate(&getter); - - SignedTrustTokenRedemptionRecord record; - record.set_token_verification_key("key"); - SetRecordExpiry(&record, base::Time::Now() - base::TimeDelta::FromMinutes(1)); - - EXPECT_TRUE(delegate.IsRecordExpired( - record, - *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example")))); -} - -// The delegate's interface defines a record as expired if its expiration time -// is not in the future. -TEST(ExpiryInspectingRecordExpiryDelegate, ExpiresRecordExpiringRightNow) { - base::test::TaskEnvironment env( - base::test::TaskEnvironment::TimeSource::MOCK_TIME); - - auto commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - commitment_result->keys.push_back(mojom::TrustTokenVerificationKey::New( - "key", /*expiry=*/base::Time::Max())); - FixedKeyCommitmentGetter getter(std::move(commitment_result)); - ExpiryInspectingRecordExpiryDelegate delegate(&getter); - - SignedTrustTokenRedemptionRecord record; - record.set_token_verification_key("key"); - SetRecordExpiry(&record, base::Time::Now()); + TrustTokenRedemptionRecord record; EXPECT_TRUE(delegate.IsRecordExpired( record, @@ -128,19 +67,17 @@ TEST(ExpiryInspectingRecordExpiryDelegate, ExpiresRecordWithNoMatchingKey) { FixedKeyCommitmentGetter getter(std::move(commitment_result)); ExpiryInspectingRecordExpiryDelegate delegate(&getter); - SignedTrustTokenRedemptionRecord record; + TrustTokenRedemptionRecord record; // "key" is not present in the commitment record.set_token_verification_key("key"); - SetRecordExpiry(&record, base::Time::Now() + base::TimeDelta::FromMinutes(1)); EXPECT_TRUE(delegate.IsRecordExpired( record, *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example")))); } -// When a record's issuer has the record's key in its current commitment, and -// the record's expiry timestamp hasn't passed, the record should not be marked -// as expired. +// When a record's issuer has the record's key in its current commitment, the +// record should not be marked as expired. TEST(ExpiryInspectingRecordExpiryDelegate, DoesntExpireUnexpiredRecord) { base::test::TaskEnvironment env( base::test::TaskEnvironment::TimeSource::MOCK_TIME); @@ -151,93 +88,12 @@ TEST(ExpiryInspectingRecordExpiryDelegate, DoesntExpireUnexpiredRecord) { FixedKeyCommitmentGetter getter(std::move(commitment_result)); ExpiryInspectingRecordExpiryDelegate delegate(&getter); - SignedTrustTokenRedemptionRecord record; + TrustTokenRedemptionRecord record; record.set_token_verification_key("key"); - SetRecordExpiry(&record, base::Time::Now() + base::TimeDelta::FromMinutes(1)); EXPECT_FALSE(delegate.IsRecordExpired( record, *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example")))); } -TEST(ExpiryInspectingRecordExpiryDelegate, ExpiresRecordWithMalformedBody) { - base::test::TaskEnvironment env( - base::test::TaskEnvironment::TimeSource::MOCK_TIME); - - auto commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - commitment_result->keys.push_back(mojom::TrustTokenVerificationKey::New( - "key", /*expiry=*/base::Time::Max())); - FixedKeyCommitmentGetter getter(std::move(commitment_result)); - ExpiryInspectingRecordExpiryDelegate delegate(&getter); - - // This SRR has an empty (and, consequently, invalid) body; it should be - // marked as expired. - SignedTrustTokenRedemptionRecord record; - record.set_token_verification_key("key"); - - EXPECT_TRUE(delegate.IsRecordExpired( - record, - *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example")))); -} - -TEST(ExpiryInspectingRecordExpiryDelegate, RespectsDefaultTimestamp) { - base::test::TaskEnvironment env( - base::test::TaskEnvironment::TimeSource::MOCK_TIME); - - auto commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - commitment_result->keys.push_back(mojom::TrustTokenVerificationKey::New( - "key", /*expiry=*/base::Time::Max())); - FixedKeyCommitmentGetter getter(std::move(commitment_result)); - ExpiryInspectingRecordExpiryDelegate delegate(&getter); - - SignedTrustTokenRedemptionRecord record; - record.set_token_verification_key("key"); - - // Construct an SRR body missing the (optional) expiry timestamp field. - std::vector<uint8_t> empty_signature; - cbor::Value::MapValue map; - record.set_body(*ConstructSignedRedemptionRecord( - *cbor::Writer::Write(cbor::Value(std::move(map))), empty_signature)); - - // The record's expiry should depend on whether the default expiry is in the - // future or the past. - EXPECT_EQ( - delegate.IsRecordExpired(record, *SuitableTrustTokenOrigin::Create( - GURL("https://issuer.example"))), - kTrustTokenDefaultRedemptionRecordExpiry <= base::Time::Now()); - - static_assert(kTrustTokenDefaultRedemptionRecordExpiry == base::Time::Max(), - "If kTrustTokenDefaultRedemptionRecordExpiry becomes less " - "than base::Time::Max(), add another test case moving the " - "clock past Time::Max() and confirming that a record with the" - " default timestamp is marked as expired."); -} - -TEST(ExpiryInspectingRecordExpiryDelegate, ExpiresRecordWithTypeUnsafeExpiry) { - base::test::TaskEnvironment env( - base::test::TaskEnvironment::TimeSource::MOCK_TIME); - - auto commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - commitment_result->keys.push_back(mojom::TrustTokenVerificationKey::New( - "key", /*expiry=*/base::Time::Max())); - FixedKeyCommitmentGetter getter(std::move(commitment_result)); - ExpiryInspectingRecordExpiryDelegate delegate(&getter); - - SignedTrustTokenRedemptionRecord record; - record.set_token_verification_key("key"); - - std::vector<uint8_t> empty_signature; - cbor::Value::MapValue map; - map[cbor::Value(kExpiryTimestampKey, cbor::Value::Type::STRING)] = - cbor::Value("oops! not an int", cbor::Value::Type::STRING); - record.set_body(*ConstructSignedRedemptionRecord( - *cbor::Writer::Write(cbor::Value(std::move(map))), empty_signature)); - - // Since the expiry is of the wrong type, the record should be marked as - // expired. - EXPECT_TRUE(delegate.IsRecordExpired( - record, - *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example")))); -} - } // namespace network diff --git a/chromium/services/network/trust_tokens/has_trust_tokens_answerer_unittest.cc b/chromium/services/network/trust_tokens/has_trust_tokens_answerer_unittest.cc index f94124aa50f..555fefb8be6 100644 --- a/chromium/services/network/trust_tokens/has_trust_tokens_answerer_unittest.cc +++ b/chromium/services/network/trust_tokens/has_trust_tokens_answerer_unittest.cc @@ -5,7 +5,7 @@ #include "services/network/trust_tokens/has_trust_tokens_answerer.h" #include "base/strings/stringprintf.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "services/network/public/cpp/trust_token_parameterization.h" #include "services/network/public/mojom/trust_tokens.mojom.h" #include "services/network/trust_tokens/pending_trust_token_store.h" diff --git a/chromium/services/network/trust_tokens/local_trust_token_operation_delegate.h b/chromium/services/network/trust_tokens/local_trust_token_operation_delegate.h new file mode 100644 index 00000000000..2703779d6cb --- /dev/null +++ b/chromium/services/network/trust_tokens/local_trust_token_operation_delegate.h @@ -0,0 +1,33 @@ +// 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 SERVICES_NETWORK_TRUST_TOKENS_LOCAL_TRUST_TOKEN_OPERATION_DELEGATE_H_ +#define SERVICES_NETWORK_TRUST_TOKENS_LOCAL_TRUST_TOKEN_OPERATION_DELEGATE_H_ + +#include "base/callback.h" +#include "services/network/public/mojom/trust_tokens.mojom-forward.h" + +namespace network { + +// LocalTrustTokenOperationDelegate provides an interface for executing +// Trust Tokens "against the platform," i.e. via some kind of operating system +// mediation rather than through the typical method of a direct HTTP request to +// a counterparty. +class LocalTrustTokenOperationDelegate { + public: + virtual ~LocalTrustTokenOperationDelegate() = default; + + // FulfillIssuance attempts to execute the given Trust Tokens operation + // locally, on conclusion populating |done| with either a response or a + // suitable status as described in FulfillTrustTokenIssuanceAnswer's struct + // comments. + virtual void FulfillIssuance( + mojom::FulfillTrustTokenIssuanceRequestPtr request, + base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)> + done) = 0; +}; + +} // namespace network + +#endif // SERVICES_NETWORK_TRUST_TOKENS_LOCAL_TRUST_TOKEN_OPERATION_DELEGATE_H_ diff --git a/chromium/services/network/trust_tokens/local_trust_token_operation_delegate_impl.cc b/chromium/services/network/trust_tokens/local_trust_token_operation_delegate_impl.cc new file mode 100644 index 00000000000..7afbd1ac497 --- /dev/null +++ b/chromium/services/network/trust_tokens/local_trust_token_operation_delegate_impl.cc @@ -0,0 +1,31 @@ +// 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 "services/network/trust_tokens/local_trust_token_operation_delegate_impl.h" + +namespace network { + +LocalTrustTokenOperationDelegateImpl::LocalTrustTokenOperationDelegateImpl( + base::RepeatingCallback<mojom::NetworkContextClient*(void)> client_provider) + : client_provider_(std::move(client_provider)) {} + +LocalTrustTokenOperationDelegateImpl::~LocalTrustTokenOperationDelegateImpl() = + default; + +void LocalTrustTokenOperationDelegateImpl::FulfillIssuance( + mojom::FulfillTrustTokenIssuanceRequestPtr request, + base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)> done) { + mojom::NetworkContextClient* client = client_provider_.Run(); + if (!client) { + auto answer = mojom::FulfillTrustTokenIssuanceAnswer::New(); + answer->status = mojom::FulfillTrustTokenIssuanceAnswer::Status::kNotFound; + std::move(done).Run(std::move(answer)); + return; + } + + client->OnTrustTokenIssuanceDivertedToSystem(std::move(request), + std::move(done)); +} + +} // namespace network diff --git a/chromium/services/network/trust_tokens/local_trust_token_operation_delegate_impl.h b/chromium/services/network/trust_tokens/local_trust_token_operation_delegate_impl.h new file mode 100644 index 00000000000..93c35210d7b --- /dev/null +++ b/chromium/services/network/trust_tokens/local_trust_token_operation_delegate_impl.h @@ -0,0 +1,49 @@ +// 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 SERVICES_NETWORK_TRUST_TOKENS_LOCAL_TRUST_TOKEN_OPERATION_DELEGATE_IMPL_H_ +#define SERVICES_NETWORK_TRUST_TOKENS_LOCAL_TRUST_TOKEN_OPERATION_DELEGATE_IMPL_H_ + +#include "base/callback.h" +#include "services/network/public/mojom/network_context.mojom.h" +#include "services/network/public/mojom/trust_tokens.mojom.h" +#include "services/network/trust_tokens/local_trust_token_operation_delegate.h" + +namespace network { + +// LocalTrustTokenOperationDelegateImpl provides an interface for executing +// Trust Tokens "against the platform," i.e. via some kind of operating system +// mediation rather than through the typical method of a direct HTTP request to +// a counterparty. +class LocalTrustTokenOperationDelegateImpl + : public LocalTrustTokenOperationDelegate { + public: + // |client_provider| provides a handle to a NetworkContextClient that will be + // used for requesting Trust Tokens operations' local execution. + // + // client_provider.Run() will be called before each attempt to delegate a + // Trust Tokens operation. It is permitted to return nullptr; in this case, + // the operation will be cancelled. + explicit LocalTrustTokenOperationDelegateImpl( + base::RepeatingCallback<mojom::NetworkContextClient*(void)> + client_provider); + + ~LocalTrustTokenOperationDelegateImpl() override; + + // FulfillIssuance attempts to execute the given Trust Tokens operation + // locally, on conclusion populating |done| with either a response or a + // suitable status as described in FulfillTrustTokenIssuanceAnswer's struct + // comments. + void FulfillIssuance( + mojom::FulfillTrustTokenIssuanceRequestPtr request, + base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)> done) + override; + + private: + base::RepeatingCallback<mojom::NetworkContextClient*(void)> client_provider_; +}; + +} // namespace network + +#endif // SERVICES_NETWORK_TRUST_TOKENS_LOCAL_TRUST_TOKEN_OPERATION_DELEGATE_IMPL_H_ diff --git a/chromium/services/network/trust_tokens/local_trust_token_operation_delegate_impl_unittest.cc b/chromium/services/network/trust_tokens/local_trust_token_operation_delegate_impl_unittest.cc new file mode 100644 index 00000000000..e5e39a2d873 --- /dev/null +++ b/chromium/services/network/trust_tokens/local_trust_token_operation_delegate_impl_unittest.cc @@ -0,0 +1,91 @@ +// 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 "services/network/trust_tokens/local_trust_token_operation_delegate_impl.h" + +#include "base/callback.h" +#include "base/run_loop.h" +#include "base/test/bind.h" +#include "base/test/mock_callback.h" +#include "base/test/task_environment.h" +#include "services/network/public/mojom/trust_tokens.mojom.h" +#include "services/network/test/test_network_context_client.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace network { + +namespace { + +using ::testing::Field; +using ::testing::Pointee; + +TEST(LocalTrustTokenOperationDelegateImpl, HandlesNullClient) { + LocalTrustTokenOperationDelegateImpl delegate(base::BindRepeating( + []() -> mojom::NetworkContextClient* { return nullptr; })); + + auto request = mojom::FulfillTrustTokenIssuanceRequest::New(); + + base::MockOnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)> + callback; + + EXPECT_CALL(callback, + Run(Pointee(Field( + &mojom::FulfillTrustTokenIssuanceAnswer::status, + mojom::FulfillTrustTokenIssuanceAnswer::Status::kNotFound)))); + + delegate.FulfillIssuance(std::move(request), callback.Get()); +} + +class RequestCapturingNetworkContextClient : public TestNetworkContextClient { + public: + explicit RequestCapturingNetworkContextClient( + mojom::FulfillTrustTokenIssuanceRequestPtr& request_out) + : request_out_(request_out) {} + + void OnTrustTokenIssuanceDivertedToSystem( + mojom::FulfillTrustTokenIssuanceRequestPtr request, + OnTrustTokenIssuanceDivertedToSystemCallback callback) override { + request_out_ = std::move(request); + std::move(callback).Run(mojom::FulfillTrustTokenIssuanceAnswer::New( + mojom::FulfillTrustTokenIssuanceAnswer::Status::kOk, + "Here's your answer")); + } + + private: + mojom::FulfillTrustTokenIssuanceRequestPtr& request_out_; +}; + +TEST(LocalTrustTokenOperationDelegateImpl, RelaysRequestAndAnswer) { + base::test::TaskEnvironment task_environment; + mojom::FulfillTrustTokenIssuanceRequestPtr relayed_request; + auto client = + std::make_unique<RequestCapturingNetworkContextClient>(relayed_request); + base::RunLoop run_loop; + + LocalTrustTokenOperationDelegateImpl delegate(base::BindLambdaForTesting( + [&client]() -> mojom::NetworkContextClient* { return client.get(); })); + + auto request = mojom::FulfillTrustTokenIssuanceRequest::New(); + request->request = "Please give me an answer"; + + delegate.FulfillIssuance( + std::move(request), + base::BindLambdaForTesting( + [&run_loop](mojom::FulfillTrustTokenIssuanceAnswerPtr answer) { + run_loop.Quit(); + ASSERT_TRUE(answer); + EXPECT_EQ(answer->status, + mojom::FulfillTrustTokenIssuanceAnswer::Status::kOk); + EXPECT_EQ(answer->response, "Here's your answer"); + })); + run_loop.Run(); + + ASSERT_TRUE(relayed_request); + EXPECT_EQ(relayed_request->request, "Please give me an answer"); +} + +} // namespace + +} // namespace network diff --git a/chromium/services/network/trust_tokens/operating_system_matching.cc b/chromium/services/network/trust_tokens/operating_system_matching.cc new file mode 100644 index 00000000000..e850394ec49 --- /dev/null +++ b/chromium/services/network/trust_tokens/operating_system_matching.cc @@ -0,0 +1,23 @@ +// 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 "services/network/trust_tokens/operating_system_matching.h" + +#include "build/build_config.h" + +namespace network { + +bool IsCurrentOperatingSystem(mojom::TrustTokenKeyCommitmentResult::Os os) { + switch (os) { + case mojom::TrustTokenKeyCommitmentResult::Os::kAndroid: +#if defined(OS_ANDROID) + return true; +#endif // defined(OS_ANDROID) + break; + } + + return false; +} + +} // namespace network diff --git a/chromium/services/network/trust_tokens/operating_system_matching.h b/chromium/services/network/trust_tokens/operating_system_matching.h new file mode 100644 index 00000000000..bc4c7d7c9df --- /dev/null +++ b/chromium/services/network/trust_tokens/operating_system_matching.h @@ -0,0 +1,24 @@ +// 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 SERVICES_NETWORK_TRUST_TOKENS_OPERATING_SYSTEM_MATCHING_H_ +#define SERVICES_NETWORK_TRUST_TOKENS_OPERATING_SYSTEM_MATCHING_H_ + +#include "base/callback.h" +#include "services/network/public/mojom/trust_tokens.mojom.h" + +namespace network { + +// Returns whether the given Os value corresponds to the operating system on +// which this code is built. +// +// This information allows Trust Tokens logic to decide whether it should try to +// execute certain operations locally, by comparing the current operating system +// to an issuer-provided collection of operating systems on which to attempt +// executing operations locally. +bool IsCurrentOperatingSystem(mojom::TrustTokenKeyCommitmentResult::Os os); + +} // namespace network + +#endif // SERVICES_NETWORK_TRUST_TOKENS_OPERATING_SYSTEM_MATCHING_H_ diff --git a/chromium/services/network/trust_tokens/pending_trust_token_store_unittest.cc b/chromium/services/network/trust_tokens/pending_trust_token_store_unittest.cc index b180816ace8..77d1a83d56e 100644 --- a/chromium/services/network/trust_tokens/pending_trust_token_store_unittest.cc +++ b/chromium/services/network/trust_tokens/pending_trust_token_store_unittest.cc @@ -4,7 +4,7 @@ #include "services/network/trust_tokens/pending_trust_token_store.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "services/network/trust_tokens/trust_token_store.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/services/network/trust_tokens/proto/public.proto b/chromium/services/network/trust_tokens/proto/public.proto index 427eca037f5..777a0492b65 100644 --- a/chromium/services/network/trust_tokens/proto/public.proto +++ b/chromium/services/network/trust_tokens/proto/public.proto @@ -22,14 +22,13 @@ message TrustToken { optional bytes signing_key = 2; // required } -// A SignedTrustTokenRedemptionRecord message stores state associated with a -// single Trust Tokens signed redemption record ("SRR"). The "body" field is the -// contents of the SRR itself; when the protocol is configured to use -// SRR-bound key pairs, "public_key" and "signing_key" are the keys associated -// with the SRR. -message SignedTrustTokenRedemptionRecord { - // The body of an SRR encodes information such as its top-level - // origin and its expiration time. +// A TrustTokenRedemptionRecord message stores state associated with a single +// Trust Token's redemption record ("RR"). The "body" field is the contents of +// the RR itself; when the protocol is configured to use RR-bound key pairs, +// "public_key" and "signing_key" are the keys associated with the RR. +message TrustTokenRedemptionRecord { + // The body of an RR contains an arbitrary bundle of issuer-provided bytes + // set as part of the redemption. optional bytes body = 1; // required // If one of public_key or signing_key is present, the other must also be @@ -37,6 +36,6 @@ message SignedTrustTokenRedemptionRecord { optional bytes public_key = 2; optional bytes signing_key = 3; - // The token verification key for the token redeemed to obtain this SRR. + // The token verification key for the token redeemed to obtain this RR. optional bytes token_verification_key = 4; // required } diff --git a/chromium/services/network/trust_tokens/proto/storage.proto b/chromium/services/network/trust_tokens/proto/storage.proto index 936aeebed99..8c65fa1e994 100644 --- a/chromium/services/network/trust_tokens/proto/storage.proto +++ b/chromium/services/network/trust_tokens/proto/storage.proto @@ -32,6 +32,6 @@ message TrustTokenIssuerToplevelPairConfig { // The time of the most recent redemption for this pair. Used for // rate-limiting. optional string last_redemption = 1; - // The signed redemption record cached for this pair, if any. - optional SignedTrustTokenRedemptionRecord signed_redemption_record = 2; + // The redemption record cached for this pair, if any. + optional TrustTokenRedemptionRecord redemption_record = 2; } diff --git a/chromium/services/network/trust_tokens/signed_redemption_record_serialization.cc b/chromium/services/network/trust_tokens/signed_redemption_record_serialization.cc deleted file mode 100644 index 1271e7921f4..00000000000 --- a/chromium/services/network/trust_tokens/signed_redemption_record_serialization.cc +++ /dev/null @@ -1,75 +0,0 @@ -// 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 "services/network/trust_tokens/signed_redemption_record_serialization.h" -#include "components/cbor/reader.h" -#include "components/cbor/values.h" -#include "net/http/structured_headers.h" - -namespace network { - -namespace { - -const char kSignedRedemptionRecordBodyKey[] = "body"; -const char kSignedRedemptionRecordSignatureKey[] = "signature"; - -} // namespace - -base::Optional<std::string> ConstructSignedRedemptionRecord( - base::span<const uint8_t> body, - base::span<const uint8_t> signature) { - net::structured_headers::Dictionary dictionary; - - // Stunningly, this is the easiest way to add a byte array-typed value to a - // net::structured_headers::Dictionary. - auto make_value_for_dict = [](base::span<const uint8_t> value) { - return net::structured_headers::ParameterizedMember( - net::structured_headers::Item( - std::string(reinterpret_cast<const char*>(value.data()), - value.size()), - net::structured_headers::Item::kByteSequenceType), - net::structured_headers::Parameters{}); - }; - - dictionary[kSignedRedemptionRecordBodyKey] = make_value_for_dict(body); - dictionary[kSignedRedemptionRecordSignatureKey] = - make_value_for_dict(signature); - - return net::structured_headers::SerializeDictionary(dictionary); -} - -bool ParseTrustTokenSignedRedemptionRecord(base::StringPiece record, - std::string* body_out, - std::string* signature_out) { - base::Optional<net::structured_headers::Dictionary> maybe_dictionary = - net::structured_headers::ParseDictionary(record); - if (!maybe_dictionary) - return false; - - if (maybe_dictionary->size() != 2u) - return false; - - if (!maybe_dictionary->contains("body") || - !maybe_dictionary->contains("signature")) { - return false; - } - - net::structured_headers::Item& body_item = - maybe_dictionary->at("body").member.front().item; - if (!body_item.is_byte_sequence()) - return false; - if (body_out) - *body_out = body_item.GetString(); // GetString gets a byte sequence, too. - - net::structured_headers::Item& signature_item = - maybe_dictionary->at("signature").member.front().item; - if (!signature_item.is_byte_sequence()) - return false; - if (signature_out) - *signature_out = signature_item.GetString(); - - return true; -} - -} // namespace network diff --git a/chromium/services/network/trust_tokens/signed_redemption_record_serialization.h b/chromium/services/network/trust_tokens/signed_redemption_record_serialization.h deleted file mode 100644 index 26103396b58..00000000000 --- a/chromium/services/network/trust_tokens/signed_redemption_record_serialization.h +++ /dev/null @@ -1,46 +0,0 @@ -// 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 SERVICES_NETWORK_TRUST_TOKENS_SIGNED_REDEMPTION_RECORD_SERIALIZATION_H_ -#define SERVICES_NETWORK_TRUST_TOKENS_SIGNED_REDEMPTION_RECORD_SERIALIZATION_H_ - -#include <string> - -#include "base/containers/span.h" -#include "base/optional.h" -#include "base/strings/string_piece_forward.h" -#include "base/time/time.h" - -namespace network { - -// The Trust Tokens design doc [1] defines a signed redemption record (SRR) as a -// Structured Headers Draft 15 dictionary with two "byte sequence"-typed fields, -// a body and a signature. This method constructs such a dictionary, given the -// body and signature's contents as bytestrings. -// -// Returns nullopt on internal serialization error in the Structured Headers -// library. -// -// [1] -// https://docs.google.com/document/d/1TNnya6B8pyomDK2F1R9CL3dY10OAmqWlnCxsWyOBDVQ/edit#heading=h.7mkzvhpqb8l5 -base::Optional<std::string> ConstructSignedRedemptionRecord( - base::span<const uint8_t> body, - base::span<const uint8_t> signature); - -// Parses a Trust Tokens Signed Redemption Record (SRR), a Structured Headers -// Draft 15 dictionary, into its constituent "body" and "signature" elements, -// placing them in the output parameters. -// -// Each output argument may be nullptr, denoting a lack of interest in the -// corresponding field. (The entire record might still be parsed.) -// -// Returns true on parse success and false on parse error. -bool ParseTrustTokenSignedRedemptionRecord( - base::StringPiece record, - std::string* body_out = nullptr, - std::string* signature_out = nullptr); - -} // namespace network - -#endif // SERVICES_NETWORK_TRUST_TOKENS_SIGNED_REDEMPTION_RECORD_SERIALIZATION_H_ diff --git a/chromium/services/network/trust_tokens/signed_redemption_record_serialization_unittest.cc b/chromium/services/network/trust_tokens/signed_redemption_record_serialization_unittest.cc deleted file mode 100644 index f2e12fb0294..00000000000 --- a/chromium/services/network/trust_tokens/signed_redemption_record_serialization_unittest.cc +++ /dev/null @@ -1,156 +0,0 @@ -// 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 "services/network/trust_tokens/signed_redemption_record_serialization.h" - -#include <string> - -#include "base/containers/span.h" -#include "base/strings/string_piece.h" -#include "base/traits_bag.h" -#include "net/http/structured_headers.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace network { - -namespace { - -enum class WithBody { kValid, kInvalid, kAbsent }; -enum class WithSignature { kValid, kInvalid, kAbsent }; -enum class WithAdditionalMember { kYes, kNo }; - -// Returns a minimal signed redemption record-like Structured Headers dictionary -// to help with error handling in the SRR deserialization code. -// -// |with_body| specifies whether to include a valid "body" field, a type-unsafe -// one, or none at all; |with_signature| does the same for the "signature" -// field. -// -// If |with_additional_member| is kYes, the dictionary will contain an -// additional member beyond whichever of the body and signature are included. -std::string CreateSerializedDictionary( - WithBody with_body, - WithSignature with_signature, - WithAdditionalMember with_additional_member) { - net::structured_headers::Dictionary dict; - - switch (with_signature) { - case WithSignature::kValid: - dict["signature"] = net::structured_headers::ParameterizedMember( - net::structured_headers::Item( - "example signature", - net::structured_headers::Item::kByteSequenceType), - {}); - break; - case WithSignature::kInvalid: - // This isn't a byte sequence, so it's not a valid value corresponding to - // the "signature" key. - dict["signature"] = net::structured_headers::ParameterizedMember( - net::structured_headers::Item(int64_t{5}), {}); - break; - case WithSignature::kAbsent: - break; - } - - switch (with_body) { - case WithBody::kValid: - dict["body"] = net::structured_headers::ParameterizedMember( - net::structured_headers::Item( - "example body", net::structured_headers::Item::kByteSequenceType), - {}); - break; - case WithBody::kInvalid: - // This isn't a byte sequence, so it's not a valid value corresponding to - // the "body" key. - dict["body"] = net::structured_headers::ParameterizedMember( - net::structured_headers::Item(int64_t{5}), {}); - break; - case WithBody::kAbsent: - break; - } - - if (with_additional_member == WithAdditionalMember::kYes) { - dict["additional"] = net::structured_headers::ParameterizedMember( - net::structured_headers::Item(int64_t{5}), {}); - } - - return *net::structured_headers::SerializeDictionary(dict); -} - -} // namespace - -TEST(SignedRedemptionRecordSerialization, SerializeAndParse) { - std::string body = "body"; - std::string signature = "example signature"; - base::Optional<std::string> maybe_serialized = - ConstructSignedRedemptionRecord( - base::as_bytes(base::make_span(body)), - base::as_bytes(base::make_span(signature))); - ASSERT_TRUE(maybe_serialized); - - std::string obtained_body; - std::string obtained_signature; - EXPECT_TRUE(ParseTrustTokenSignedRedemptionRecord( - *maybe_serialized, &obtained_body, &obtained_signature)); - EXPECT_EQ(obtained_body, body); - EXPECT_EQ(obtained_signature, signature); -} - -TEST(SignedRedemptionRecordSerialization, SerializeAndParseNullptrParams) { - // Make sure ParseTrustTokenSignedRedemptionRecord doesn't blow up (i.e., - // dereference a null pointer) when its optional params aren't provided. - std::string body = "example body"; - std::string signature = "example signature"; - base::Optional<std::string> maybe_serialized = - ConstructSignedRedemptionRecord( - base::as_bytes(base::make_span(body)), - base::as_bytes(base::make_span(signature))); - ASSERT_TRUE(maybe_serialized); - - EXPECT_TRUE(ParseTrustTokenSignedRedemptionRecord(*maybe_serialized, nullptr, - nullptr)); -} - -TEST(SignedRedemptionRecordSerialization, ParseNotDictionary) { - // Parse should reject objects that aren't Structured Headers dictionaries. - EXPECT_FALSE(ParseTrustTokenSignedRedemptionRecord( - "Not a Structured Headers dictionary", nullptr, nullptr)); -} - -TEST(SignedRedemptionRecordSerialization, ParseTooSmallDictionary) { - // Parse should reject Structured Headers dictionaries that aren't size 2. - EXPECT_FALSE(ParseTrustTokenSignedRedemptionRecord( - CreateSerializedDictionary(WithBody::kAbsent, WithSignature::kAbsent, - WithAdditionalMember::kNo), - nullptr, nullptr)); -} - -TEST(SignedRedemptionRecordSerialization, - ParseDictionaryWithTypeUnsafeSignature) { - // Parse should reject size 2 structured headers dictionaries with members of - // the wrong type. - EXPECT_FALSE(ParseTrustTokenSignedRedemptionRecord( - CreateSerializedDictionary(WithBody::kValid, WithSignature::kInvalid, - WithAdditionalMember::kNo), - nullptr, nullptr)); -} - -TEST(SignedRedemptionRecordSerialization, ParseDictionaryWithTypeUnsafeBody) { - // Parse should reject size 2 structured headers dictionaries with members of - // the wrong type. - EXPECT_FALSE(ParseTrustTokenSignedRedemptionRecord( - CreateSerializedDictionary(WithBody::kInvalid, WithSignature::kValid, - WithAdditionalMember::kNo), - nullptr, nullptr)); -} - -TEST(SignedRedemptionRecordSerialization, ParseDictionaryWithExtraMembers) { - // Parse should reject size >2 structured headers dictionaries. - EXPECT_FALSE(ParseTrustTokenSignedRedemptionRecord( - CreateSerializedDictionary(WithBody::kValid, WithSignature::kValid, - WithAdditionalMember::kYes), - nullptr, nullptr)); -} - -} // namespace network diff --git a/chromium/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc b/chromium/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc index d89947bb068..7a8e18dcbe8 100644 --- a/chromium/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc +++ b/chromium/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc @@ -12,7 +12,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" #include "base/task/post_task.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "components/sqlite_proto/key_value_data.h" diff --git a/chromium/services/network/trust_tokens/trust_token_cryptographers_test.cc b/chromium/services/network/trust_tokens/trust_token_cryptographers_test.cc index f570b3696a0..9277366492c 100644 --- a/chromium/services/network/trust_tokens/trust_token_cryptographers_test.cc +++ b/chromium/services/network/trust_tokens/trust_token_cryptographers_test.cc @@ -42,12 +42,11 @@ struct TokenKeyPair { }; struct ProtocolKeys { std::vector<TokenKeyPair> token_keys; - - // Signed redemption record (SRR) signing and verification keys: - std::vector<uint8_t> srr_signing; - std::vector<uint8_t> srr_verification; }; +const mojom::TrustTokenProtocolVersion kProtocolVersion = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + // Choose this number to be > 1 but fairly small: setting it to 10 // led to the test running for 2.5 sec on a debug build. constexpr size_t kNumTokensToRequest = 3; @@ -62,7 +61,7 @@ TokenKeyPair GenerateTokenKeys(uint32_t key_id) { keys.verification.resize(TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE); size_t signing_key_len, verification_key_len; CHECK(TRUST_TOKEN_generate_key( - TRUST_TOKEN_experiment_v1(), keys.signing.data(), &signing_key_len, + TRUST_TOKEN_experiment_v2_pmb(), keys.signing.data(), &signing_key_len, keys.signing.size(), keys.verification.data(), &verification_key_len, keys.verification.size(), key_id)); keys.signing.resize(signing_key_len); @@ -71,8 +70,7 @@ TokenKeyPair GenerateTokenKeys(uint32_t key_id) { return keys; } -// Generates a set of issuance keys associated with |key_id| and a set of signed -// redemption record keys. +// Generates a set of issuance keys associated with |key_id|. ProtocolKeys GenerateProtocolKeys(size_t num_keys) { ProtocolKeys keys; for (size_t i = 0; i < num_keys; ++i) { @@ -81,11 +79,6 @@ ProtocolKeys GenerateProtocolKeys(size_t num_keys) { keys.token_keys.push_back(GenerateTokenKeys(/*key_id=*/3 * i)); } - keys.srr_signing.resize(ED25519_PRIVATE_KEY_LEN); - keys.srr_verification.resize(ED25519_PUBLIC_KEY_LEN); - // (ED25519_keypair can't fail). - ED25519_keypair(keys.srr_verification.data(), keys.srr_signing.data()); - return keys; } @@ -112,7 +105,8 @@ void RequestManyTokensAndRetainOneArbitrarily( TRUST_TOKEN_ISSUER* issuer_ctx, TrustToken* out_token) { BoringsslTrustTokenIssuanceCryptographer issuance_cryptographer; - ASSERT_TRUE(issuance_cryptographer.Initialize(kNumTokensToRequest)); + ASSERT_TRUE( + issuance_cryptographer.Initialize(kProtocolVersion, kNumTokensToRequest)); for (const TokenKeyPair& token_keys : keys.token_keys) { ASSERT_TRUE(issuance_cryptographer.AddKey(std::string( @@ -158,14 +152,14 @@ void RequestManyTokensAndRetainOneArbitrarily( void RedeemSingleToken(const ProtocolKeys& keys, TRUST_TOKEN_ISSUER* issuer_ctx, const TrustToken& token_to_redeem, - std::string* signed_redemption_record_out) { + std::string* redemption_record_out) { BoringsslTrustTokenRedemptionCryptographer redemption_cryptographer; const url::Origin kRedeemingOrigin = url::Origin::Create(GURL("https://topframe.example")); - ASSERT_TRUE(redemption_cryptographer.Initialize( - kNumTokensToRequest, as_string(keys.srr_verification))); + ASSERT_TRUE(redemption_cryptographer.Initialize(kProtocolVersion, + kNumTokensToRequest)); base::Optional<std::string> maybe_base64_encoded_redemption_request = redemption_cryptographer.BeginRedemption( @@ -184,7 +178,7 @@ void RedeemSingleToken(const ProtocolKeys& keys, // TRUST_TOKEN **out_token, uint8_t **out_client_data, // size_t *out_client_data_len, uint64_t *out_redemption_time, // const uint8_t *request, size_t request_len, uint64_t lifetime); - constexpr base::TimeDelta kSrrLifetime = base::TimeDelta::FromSeconds(100); + constexpr base::TimeDelta kRrLifetime = base::TimeDelta::FromSeconds(100); ScopedBoringsslBytes raw_redemption_response; TRUST_TOKEN* redeemed_token; ScopedBoringsslBytes redeemed_client_data; @@ -195,7 +189,7 @@ void RedeemSingleToken(const ProtocolKeys& keys, redeemed_client_data.mutable_ptr(), redeemed_client_data.mutable_len(), &received_redemption_timestamp, base::as_bytes(base::make_span(raw_redemption_request)).data(), - raw_redemption_request.size(), kSrrLifetime.InSeconds())); + raw_redemption_request.size(), kRrLifetime.InSeconds())); // Put the issuer-receied token in a smart pointer so it will get deleted on // leaving scope. bssl::UniquePtr<TRUST_TOKEN> redeemed_token_scoper(redeemed_token); @@ -204,8 +198,6 @@ void RedeemSingleToken(const ProtocolKeys& keys, // |token_to_redeem|, but the TRUST_TOKEN type represents different things in // client and server settings, so these structs don't necessarily have equal // contents. - EXPECT_EQ(base::checked_cast<int64_t>(received_redemption_timestamp), - (base::Time::Now() - base::Time::UnixEpoch()).InSeconds()); auto expected_client_data = *CanonicalizeTrustTokenClientDataForRedemption( base::Time::Now(), kRedeemingOrigin, "client-generated public key bound to the redemption"); @@ -216,12 +208,12 @@ void RedeemSingleToken(const ProtocolKeys& keys, std::string base64_encoded_redemption_response = base::Base64Encode(raw_redemption_response.as_span()); - base::Optional<std::string> maybe_signed_redemption_record = + base::Optional<std::string> maybe_redemption_record = redemption_cryptographer.ConfirmRedemption( base64_encoded_redemption_response); - ASSERT_TRUE(maybe_signed_redemption_record); - signed_redemption_record_out->swap(*maybe_signed_redemption_record); + ASSERT_TRUE(maybe_redemption_record); + redemption_record_out->swap(*maybe_redemption_record); } } // namespace @@ -232,38 +224,36 @@ TEST(TrustTokenCryptographersTest, IssuanceAndRedemption) { ProtocolKeys keys = GenerateProtocolKeys(/*num_keys=*/1); - // Initialization: provide the issuer context the token-signing and - // SRR-signing keys. + // Initialization: provide the issuer context the token-signing keys. bssl::UniquePtr<TRUST_TOKEN_ISSUER> issuer_ctx(TRUST_TOKEN_ISSUER_new( - TRUST_TOKEN_experiment_v1(), /*max_batchsize=*/kNumTokensToRequest)); + TRUST_TOKEN_experiment_v2_pmb(), /*max_batchsize=*/kNumTokensToRequest)); ASSERT_TRUE(issuer_ctx); for (const TokenKeyPair& token_key_pair : keys.token_keys) { ASSERT_TRUE(TRUST_TOKEN_ISSUER_add_key(issuer_ctx.get(), token_key_pair.signing.data(), token_key_pair.signing.size())); } + // Copying the comment from evp.h: // The [Ed25519] RFC 8032 private key format is the 32-byte prefix of // |ED25519_sign|'s 64-byte private key. - bssl::UniquePtr<EVP_PKEY> issuer_srr_key(EVP_PKEY_new_raw_private_key( - EVP_PKEY_ED25519, /*unused=*/nullptr, keys.srr_signing.data(), + uint8_t public_key[32], private_key[64]; + ED25519_keypair(public_key, private_key); + bssl::UniquePtr<EVP_PKEY> issuer_rr_key(EVP_PKEY_new_raw_private_key( + EVP_PKEY_ED25519, /*unused=*/nullptr, private_key, /*len=*/32)); - ASSERT_TRUE(issuer_srr_key); + ASSERT_TRUE(issuer_rr_key); ASSERT_TRUE( - TRUST_TOKEN_ISSUER_set_srr_key(issuer_ctx.get(), issuer_srr_key.get())); + TRUST_TOKEN_ISSUER_set_srr_key(issuer_ctx.get(), issuer_rr_key.get())); // Execute an issuance and a redemption; they should succeed. TrustToken token; ASSERT_NO_FATAL_FAILURE(RequestManyTokensAndRetainOneArbitrarily( keys, keys.token_keys[0], issuer_ctx.get(), &token)); - std::string signed_redemption_record; - ASSERT_NO_FATAL_FAILURE(RedeemSingleToken(keys, issuer_ctx.get(), token, - &signed_redemption_record)); - - ASSERT_EQ(test::VerifyTrustTokenSignedRedemptionRecord( - signed_redemption_record, as_string(keys.srr_verification)), - test::SrrVerificationStatus::kSuccess); + std::string redemption_record; + ASSERT_NO_FATAL_FAILURE( + RedeemSingleToken(keys, issuer_ctx.get(), token, &redemption_record)); } TEST(TrustTokenCryptographersTest, IssuanceAndRedemptionWithMultipleKeys) { @@ -272,25 +262,27 @@ TEST(TrustTokenCryptographersTest, IssuanceAndRedemptionWithMultipleKeys) { ProtocolKeys keys = GenerateProtocolKeys(/*num_keys=*/3); - // Initialization: provide the issuer context the token-signing and - // SRR-signing keys. + // Initialization: provide the issuer context the token-signing keys. bssl::UniquePtr<TRUST_TOKEN_ISSUER> issuer_ctx(TRUST_TOKEN_ISSUER_new( - TRUST_TOKEN_experiment_v1(), /*max_batchsize=*/kNumTokensToRequest)); + TRUST_TOKEN_experiment_v2_pmb(), /*max_batchsize=*/kNumTokensToRequest)); ASSERT_TRUE(issuer_ctx); for (const TokenKeyPair& token_key_pair : keys.token_keys) { ASSERT_TRUE(TRUST_TOKEN_ISSUER_add_key(issuer_ctx.get(), token_key_pair.signing.data(), token_key_pair.signing.size())); } + // Copying the comment from evp.h: // The [Ed25519] RFC 8032 private key format is the 32-byte prefix of // |ED25519_sign|'s 64-byte private key. - bssl::UniquePtr<EVP_PKEY> issuer_srr_key(EVP_PKEY_new_raw_private_key( - EVP_PKEY_ED25519, /*unused=*/nullptr, keys.srr_signing.data(), + uint8_t public_key[32], private_key[64]; + ED25519_keypair(public_key, private_key); + bssl::UniquePtr<EVP_PKEY> issuer_rr_key(EVP_PKEY_new_raw_private_key( + EVP_PKEY_ED25519, /*unused=*/nullptr, private_key, /*len=*/32)); - ASSERT_TRUE(issuer_srr_key); + ASSERT_TRUE(issuer_rr_key); ASSERT_TRUE( - TRUST_TOKEN_ISSUER_set_srr_key(issuer_ctx.get(), issuer_srr_key.get())); + TRUST_TOKEN_ISSUER_set_srr_key(issuer_ctx.get(), issuer_rr_key.get())); // Issuance should succeed when the issuer uses the first issuance key // generated, and when the issuer uses the second issuance key generated. @@ -302,21 +294,13 @@ TEST(TrustTokenCryptographersTest, IssuanceAndRedemptionWithMultipleKeys) { keys, keys.token_keys[1], issuer_ctx.get(), &another_token)); // In both cases, redeeming a token from the issuance should succeed and yield - // a well-formed signed redemption record. - std::string signed_redemption_record; - ASSERT_NO_FATAL_FAILURE(RedeemSingleToken(keys, issuer_ctx.get(), token, - &signed_redemption_record)); - - ASSERT_EQ(test::VerifyTrustTokenSignedRedemptionRecord( - signed_redemption_record, as_string(keys.srr_verification)), - test::SrrVerificationStatus::kSuccess); - - ASSERT_NO_FATAL_FAILURE(RedeemSingleToken( - keys, issuer_ctx.get(), another_token, &signed_redemption_record)); + // a well-formed redemption record. + std::string redemption_record; + ASSERT_NO_FATAL_FAILURE( + RedeemSingleToken(keys, issuer_ctx.get(), token, &redemption_record)); - ASSERT_EQ(test::VerifyTrustTokenSignedRedemptionRecord( - signed_redemption_record, as_string(keys.srr_verification)), - test::SrrVerificationStatus::kSuccess); + ASSERT_NO_FATAL_FAILURE(RedeemSingleToken(keys, issuer_ctx.get(), + another_token, &redemption_record)); } } // namespace network diff --git a/chromium/services/network/trust_tokens/trust_token_database_owner_unittest.cc b/chromium/services/network/trust_tokens/trust_token_database_owner_unittest.cc index c935b819dfe..9dbf033652b 100644 --- a/chromium/services/network/trust_tokens/trust_token_database_owner_unittest.cc +++ b/chromium/services/network/trust_tokens/trust_token_database_owner_unittest.cc @@ -4,7 +4,7 @@ #include "services/network/trust_tokens/trust_token_database_owner.h" #include "base/task/post_task.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/services/network/trust_tokens/trust_token_key_commitment_controller_unittest.cc b/chromium/services/network/trust_tokens/trust_token_key_commitment_controller_unittest.cc index dee87c1cd70..8e12f32e85f 100644 --- a/chromium/services/network/trust_tokens/trust_token_key_commitment_controller_unittest.cc +++ b/chromium/services/network/trust_tokens/trust_token_key_commitment_controller_unittest.cc @@ -9,7 +9,7 @@ #include "base/bind.h" #include "base/no_destructor.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" @@ -47,7 +47,7 @@ class FixedKeyCommitmentParser static mojom::TrustTokenKeyCommitmentResultPtr DeterministicallyReturnedValue() { auto result = mojom::TrustTokenKeyCommitmentResult::New(); - result->signed_redemption_record_verification_key = "key"; + result->batch_size = 10; return result; } }; diff --git a/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.cc b/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.cc index 6bcfe8abe58..652cbc34c69 100644 --- a/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.cc +++ b/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.cc @@ -7,15 +7,29 @@ #include "base/base64.h" #include "base/json/json_reader.h" #include "base/numerics/safe_conversions.h" +#include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/values.h" -#include "services/network/public/mojom/trust_tokens.mojom-forward.h" #include "services/network/public/mojom/trust_tokens.mojom.h" #include "services/network/trust_tokens/suitable_trust_token_origin.h" namespace network { +const char kTrustTokenKeyCommitmentProtocolVersionField[] = "protocol_version"; +const char kTrustTokenKeyCommitmentIDField[] = "id"; +const char kTrustTokenKeyCommitmentBatchsizeField[] = "batchsize"; +const char kTrustTokenKeyCommitmentExpiryField[] = "expiry"; +const char kTrustTokenKeyCommitmentKeyField[] = "Y"; +const char kTrustTokenKeyCommitmentRequestIssuanceLocallyOnField[] = + "request_issuance_locally_on"; +const char kTrustTokenLocalIssuanceOsAndroid[] = "android"; +const char kTrustTokenKeyCommitmentUnavailableLocalIssuanceFallbackField[] = + "unavailable_local_issuance_fallback"; +const char kTrustTokenLocalIssuanceFallbackWebIssuance[] = "web_issuance"; +const char kTrustTokenLocalIssuanceFallbackReturnWithError[] = + "return_with_error"; + namespace { // Parses a single key label. If |in| is the string representation of an integer @@ -71,6 +85,82 @@ ParseKeyResult ParseSingleKeyExceptLabel( return ParseKeyResult::kSucceed; } +base::Optional<mojom::TrustTokenKeyCommitmentResult::Os> ParseOs( + base::StringPiece os_string) { + if (os_string == kTrustTokenLocalIssuanceOsAndroid) + return mojom::TrustTokenKeyCommitmentResult::Os::kAndroid; + return base::nullopt; +} + +// Attempts to parse a string representation of a member of the +// UnavailableLocalIssuanceFallback enum, returning true on success and false on +// failure. +bool ParseUnavailableLocalIssuanceFallback( + base::StringPiece fallback_string, + mojom::TrustTokenKeyCommitmentResult::UnavailableLocalIssuanceFallback* + fallback_out) { + if (fallback_string == kTrustTokenLocalIssuanceFallbackWebIssuance) { + *fallback_out = mojom::TrustTokenKeyCommitmentResult:: + UnavailableLocalIssuanceFallback::kWebIssuance; + return true; + } + if (fallback_string == kTrustTokenLocalIssuanceFallbackReturnWithError) { + *fallback_out = mojom::TrustTokenKeyCommitmentResult:: + UnavailableLocalIssuanceFallback::kReturnWithError; + return true; + } + return false; +} + +// Given a per-issuer key commitment dictionary, looks for the local Trust +// Tokens issuance-related fields request_issuance_locally_on and +// unavailable_local_issuance_fallback. +// +// Returns true if both are absent, or if both are present and well-formed; in +// the latter case, updates |result| to with their parsed values. Otherwise, +// returns false. +bool ParseLocalIssuanceFieldsIfPresent( + const base::Value& value, + mojom::TrustTokenKeyCommitmentResult* result) { + const base::Value* maybe_request_issuance_locally_on = + value.FindKey(kTrustTokenKeyCommitmentRequestIssuanceLocallyOnField); + + // The local issuance field is optional... + if (!maybe_request_issuance_locally_on) + return true; + + // ...but needs to be the right type if it's provided. + if (!maybe_request_issuance_locally_on->is_list()) + return false; + + for (const base::Value& maybe_os_value : + maybe_request_issuance_locally_on->GetList()) { + if (!maybe_os_value.is_string()) + return false; + base::Optional<mojom::TrustTokenKeyCommitmentResult::Os> maybe_os = + ParseOs(maybe_os_value.GetString()); + if (!maybe_os) + return false; + result->request_issuance_locally_on.push_back(*maybe_os); + } + + // Deduplicate the OS values: + auto& oses = result->request_issuance_locally_on; + base::ranges::sort(oses); + auto to_remove = base::ranges::unique(oses); + oses.erase(to_remove, oses.end()); + + const std::string* maybe_fallback = value.FindStringKey( + kTrustTokenKeyCommitmentUnavailableLocalIssuanceFallbackField); + if (!maybe_fallback || + !ParseUnavailableLocalIssuanceFallback( + *maybe_fallback, &result->unavailable_local_issuance_fallback)) { + return false; + } + + return true; +} + mojom::TrustTokenKeyCommitmentResultPtr ParseSingleIssuer( const base::Value& value) { if (!value.is_dict()) @@ -78,6 +168,28 @@ mojom::TrustTokenKeyCommitmentResultPtr ParseSingleIssuer( auto result = mojom::TrustTokenKeyCommitmentResult::New(); + // Confirm that the protocol_version field is present. + const std::string* maybe_version = + value.FindStringKey(kTrustTokenKeyCommitmentProtocolVersionField); + if (!maybe_version) + return nullptr; + if (*maybe_version == "TrustTokenV2PMB") { + result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + } else if (*maybe_version == "TrustTokenV2VOPRF") { + result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Voprf; + } else { + return nullptr; + } + + // Confirm that the id field is present and type-safe. + base::Optional<int> maybe_id = + value.FindIntKey(kTrustTokenKeyCommitmentIDField); + if (!maybe_id || *maybe_id <= 0) + return nullptr; + result->id = *maybe_id; + // Confirm that the batchsize field is present and type-safe. base::Optional<int> maybe_batch_size = value.FindIntKey(kTrustTokenKeyCommitmentBatchsizeField); @@ -85,15 +197,8 @@ mojom::TrustTokenKeyCommitmentResultPtr ParseSingleIssuer( return nullptr; result->batch_size = *maybe_batch_size; - // Confirm that the srrkey field is present and base64-encoded. - const std::string* maybe_srrkey = - value.FindStringKey(kTrustTokenKeyCommitmentSrrkeyField); - if (!maybe_srrkey) - return nullptr; - if (!base::Base64Decode(*maybe_srrkey, - &result->signed_redemption_record_verification_key)) { + if (!ParseLocalIssuanceFieldsIfPresent(value, result.get())) return nullptr; - } // Parse the key commitments in the result (these are exactly the // key-value pairs in the dictionary with dictionary-typed values). @@ -137,25 +242,27 @@ mojom::TrustTokenKeyCommitmentResultPtr& commitment(Entry& e) { } // namespace -const char kTrustTokenKeyCommitmentBatchsizeField[] = "batchsize"; -const char kTrustTokenKeyCommitmentSrrkeyField[] = "srrkey"; -const char kTrustTokenKeyCommitmentExpiryField[] = "expiry"; -const char kTrustTokenKeyCommitmentKeyField[] = "Y"; - // https://docs.google.com/document/d/1TNnya6B8pyomDK2F1R9CL3dY10OAmqWlnCxsWyOBDVQ/edit#bookmark=id.6wh9crbxdizi // { -// "batchsize" : ..., // Batch size; value of type int. -// "srrkey" : ..., // Required Signed Redemption Record (SRR) -// // verification key, in base64. +// "protocol_version" : ..., // Protocol Version; value of type string. +// "id" : ..., // ID; value of type int. +// "batchsize" : ..., // Batch size; value of type int. +// +// // Optional operating systems on which to request issuance via system +// // mediation (valid values are: "android"), and (required if at least one +// // OS is specified) fallback behavior on other operating systems: +// "request_issuance_locally_on": [<os 1>, ..., <os N>], +// "unavailable_local_issuance_fallback": "web_issuance" | "return_with_error" // -// "1" : { // Key label, a number in uint32_t range; ignored except -// // for checking that it is present and type-safe. -// "Y" : ..., // Required token issuance verification key, in -// // base64. -// "expiry" : ..., // Required token issuance key expiry time, in -// // microseconds since the Unix epoch. +// "1" : { // Key label, a number in uint32_t range; ignored +// // except for checking that it is present and +// // type-safe. +// "Y" : ..., // Required token issuance verification key, in +// // base64. +// "expiry" : ..., // Required token issuance key expiry time, in +// // microseconds since the Unix epoch. // }, -// "17" : { // No guarantee that key labels (1, 17) are dense. +// "17" : { // No guarantee that key labels (1, 7) are dense. // "Y" : ..., // "expiry" : ..., // } diff --git a/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.h b/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.h index 2131ce8c76b..2562daca7bb 100644 --- a/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.h +++ b/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.h @@ -14,37 +14,45 @@ namespace network { -// Field names from the key commitment JSON format specified in the Trust Tokens -// design doc -// (https://docs.google.com/document/d/1TNnya6B8pyomDK2F1R9CL3dY10OAmqWlnCxsWyOBDVQ/edit#bookmark=id.6wh9crbxdizi): -// - "batch size" (number of blinded tokens to provide per issuance request) +// These field names are from the key commitment JSON format specified in the +// Trust Tokens design doc +// (https://docs.google.com/document/d/1TNnya6B8pyomDK2F1R9CL3dY10OAmqWlnCxsWyOBDVQ/edit#bookmark=id.6wh9crbxdizi). +// "protocol version" (version of Trust Token used for this commitment): +extern const char kTrustTokenKeyCommitmentProtocolVersionField[]; +// This commitment's ID, used for mediating between concurrencyID for this key +// commitment): +extern const char kTrustTokenKeyCommitmentIDField[]; +// "Batch size" (number of blinded tokens to provide per issuance request): extern const char kTrustTokenKeyCommitmentBatchsizeField[]; -// - verification key for the signatures the issuer provides over its Signed -// Redemption Records (SRRs) -extern const char kTrustTokenKeyCommitmentSrrkeyField[]; -// - each issuance key's expiry timestamp +// Each issuance key's expiry timestamp: extern const char kTrustTokenKeyCommitmentExpiryField[]; -// - each issuance key's key material +// Each issuance key's key material: extern const char kTrustTokenKeyCommitmentKeyField[]; +// The operating systems on which to request issuance via system mediation +// rather than through a request to the issuer's website: +extern const char kTrustTokenKeyCommitmentRequestIssuanceLocallyOnField[]; +extern const char kTrustTokenKeyCommitmentOsAndroid[]; + +// The desired fallback behavior when local issuance isn't available on the +// requested operating system: +extern const char + kTrustTokenKeyCommitmentUnavailableLocalIssuanceFallbackField[]; +extern const char kTrustTokenLocalIssuanceFallbackWebIssuance[]; +extern const char kTrustTokenLocalIssuanceFallbackReturnWithError[]; + class TrustTokenKeyCommitmentParser : public TrustTokenKeyCommitmentController::Parser { public: TrustTokenKeyCommitmentParser() = default; ~TrustTokenKeyCommitmentParser() override = default; - // Parses a JSON key commitment response. + // Parses a JSON key commitment response, returning nullptr if the input is + // not a valid representation of a JSON dictionary containing all required + // fields listed in the Trust Tokens design doc, the current normative source + // for key commitment responses' format: // - // This method returns nullptr unless: - // - the input is valid JSON; and - // - the JSON represents a nonempty dictionary; and - // - within this inner dictionary (which stores metadata like batch size, as - // well as more dictionaries denoting keys' information): - // - every dictionary-type value has an expiry field - // (|kTrustTokenKeyCommitmentExpiryField| above) and a key body field - // (|kTrustTokenKeyCommitmentKeyField|), and - // - the expiry field is a positive integer (microseconds since the Unix - // epoch) storing a time in the future. + // https://docs.google.com/document/d/1TNnya6B8pyomDK2F1R9CL3dY10OAmqWlnCxsWyOBDVQ/edit#heading=h.wkezf6pcskvh mojom::TrustTokenKeyCommitmentResultPtr Parse( base::StringPiece response_body) override; diff --git a/chromium/services/network/trust_tokens/trust_token_key_commitment_parser_unittest.cc b/chromium/services/network/trust_tokens/trust_token_key_commitment_parser_unittest.cc index 42479c52f6f..82f694357a2 100644 --- a/chromium/services/network/trust_tokens/trust_token_key_commitment_parser_unittest.cc +++ b/chromium/services/network/trust_tokens/trust_token_key_commitment_parser_unittest.cc @@ -9,7 +9,7 @@ #include "base/no_destructor.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/time/time.h" #include "mojo/public/cpp/bindings/struct_ptr.h" @@ -68,54 +68,23 @@ TEST(TrustTokenKeyCommitmentParser, RejectsNonDictionaryInput) { } TEST(TrustTokenKeyCommitmentParser, AcceptsMinimal) { - std::string input = R"( { "batchsize": 5, "srrkey": "aaaa" } )"; + std::string input = + R"( { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5 + } )"; // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); auto expectation = mojom::TrustTokenKeyCommitmentResult::New(); + expectation->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + expectation->id = 1; expectation->batch_size = 5; - base::Base64Decode("aaaa", - &expectation->signed_redemption_record_verification_key); EXPECT_THAT(TrustTokenKeyCommitmentParser().Parse(input), EqualsMojo(expectation)); } -TEST(TrustTokenKeyCommitmentParser, RejectsMissingSrrkey) { - std::string input = R"( {"batchsize": 5} )"; - - // Sanity check that the input is actually valid JSON. - ASSERT_TRUE(base::JSONReader::Read(input)); - - mojom::TrustTokenKeyCommitmentResultPtr result = - TrustTokenKeyCommitmentParser().Parse(input); - EXPECT_FALSE(result); -} - -TEST(TrustTokenKeyCommitmentParser, RejectsTypeUnsafeSrrkey) { - std::string input = R"( { "batchsize": 5, "srrkey": 5 } )"; - - // Sanity check that the input is actually valid JSON. - ASSERT_TRUE(base::JSONReader::Read(input)); - - mojom::TrustTokenKeyCommitmentResultPtr result = - TrustTokenKeyCommitmentParser().Parse(input); - EXPECT_FALSE(result); -} - -TEST(TrustTokenKeyCommitmentParser, RejectsNonBase64Srrkey) { - std::string input = R"( { "batchsize": 5, - "srrkey": "spaces aren't valid base64" } )"; - - // Sanity check that the input is actually valid JSON. - ASSERT_TRUE(base::JSONReader::Read(input)); - - mojom::TrustTokenKeyCommitmentResultPtr result = - TrustTokenKeyCommitmentParser().Parse(input); - EXPECT_FALSE(result); -} - TEST(TrustTokenKeyCommitmentParser, RejectsKeyWithTypeUnsafeKeyLabel) { base::test::TaskEnvironment env( base::test::TaskEnvironment::TimeSource::MOCK_TIME); @@ -129,7 +98,7 @@ TEST(TrustTokenKeyCommitmentParser, RejectsKeyWithTypeUnsafeKeyLabel) { // it's encoded as a string.) const std::string input = base::StringPrintf( R"({ - "batchsize": 5, "srrkey": "aaaa", + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, "this label is not an integer": { "Y": "akey", "expiry": "%s" @@ -156,7 +125,7 @@ TEST(TrustTokenKeyCommitmentParser, RejectsKeyWithKeyLabelTooSmall) { const std::string input = base::StringPrintf( R"({ - "batchsize": 5, "srrkey": "aaaa", + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, "-1": { "Y": "akey", "expiry": "%s" @@ -183,7 +152,7 @@ TEST(TrustTokenKeyCommitmentParser, RejectsKeyWithKeyLabelTooLarge) { const std::string input = base::StringPrintf( R"({ - "batchsize": 5, "srrkey": "aaaa", + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, "1000000000000": { "Y": "akey", "expiry": "%s" @@ -210,7 +179,7 @@ TEST(TrustTokenKeyCommitmentParser, RejectsOtherwiseValidButNonBase64Key) { const std::string input = base::StringPrintf( R"({ - "batchsize": 5, "srrkey": "aaaa", + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, "1": { "Y": "this key isn't valid base64, so it should be rejected", "expiry": "%s" @@ -236,7 +205,7 @@ TEST(TrustTokenKeyCommitmentParser, AcceptsKeyWithExpiryAndBody) { const std::string input = base::StringPrintf( R"({ - "batchsize": 5, "srrkey": "aaaa", + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, "1": { "Y": "akey", "expiry": "%s" } })", base::NumberToString(one_minute_from_now_in_micros).c_str()); @@ -270,7 +239,7 @@ TEST(TrustTokenKeyCommitmentParser, AcceptsMultipleKeys) { const std::string input = base::StringPrintf( R"({ - "batchsize": 5, "srrkey": "aaaa", + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, "1": { "Y": "akey", "expiry": "%s" }, "2": { "Y": "aaaa", "expiry": "%s" } })", @@ -298,8 +267,9 @@ TEST(TrustTokenKeyCommitmentParser, AcceptsMultipleKeys) { TEST(TrustTokenKeyCommitmentParser, RejectsKeyWithNoExpiry) { // If a key has a missing "expiry" field, we should reject the entire // record. - const std::string input = R"( { "batchsize": 5, "srrkey": "aaaa", - "1": { "Y": "akey" } })"; + const std::string input = + R"( { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, + "1": { "Y": "akey" } })"; // Sanity check that the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); @@ -314,7 +284,7 @@ TEST(TrustTokenKeyCommitmentParser, RejectsKeyWithMalformedExpiry) { const std::string input = R"( { - "batchsize": 5, "srrkey": "aaaa", + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, "1": { "Y": "akey", "expiry": "absolutely not a valid timestamp" @@ -347,7 +317,7 @@ TEST(TrustTokenKeyCommitmentParser, IgnoreKeyWithExpiryInThePast) { // If the time has passed a key's "expiry" field, we should reject the entire // record. const std::string input = base::StringPrintf( - R"( { "batchsize": 5, "srrkey": "aaaa", + R"( { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, "1": { "Y": "akey", "expiry": "%s" } })", base::NumberToString(one_minute_before_now_in_micros).c_str()); @@ -355,8 +325,9 @@ TEST(TrustTokenKeyCommitmentParser, IgnoreKeyWithExpiryInThePast) { ASSERT_TRUE(base::JSONReader::Read(input)); auto expectation = mojom::TrustTokenKeyCommitmentResult::New(); - base::Base64Decode("aaaa", - &expectation->signed_redemption_record_verification_key); + expectation->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + expectation->id = 1; expectation->batch_size = 5; EXPECT_TRUE( @@ -375,8 +346,8 @@ TEST(TrustTokenKeyCommitmentParser, RejectsKeyWithNoBody) { // If a key has an expiry but is missing its body, // we should reject the entire result. const std::string input = base::StringPrintf( - R"( { "batchsize": 5, "srrkey": "aaaa", - "1": { "expiry": "%s" } } )", + R"( { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, + "1": { "expiry": "%s" } } )", base::NumberToString(one_minute_from_now_in_micros).c_str()); // Sanity check that the input is actually valid JSON, @@ -391,8 +362,9 @@ TEST(TrustTokenKeyCommitmentParser, RejectsEmptyKey) { // If a key has neither an expiry or a body, // we should reject the entire result. - const std::string input = R"( { "batchsize": 5, - "srrkey": "aaaa", "1": { } })"; + const std::string input = + R"( { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, + "1": { } })"; // Sanity check that the input is actually valid JSON, // and that the date is valid. @@ -405,9 +377,10 @@ TEST(TrustTokenKeyCommitmentParser, RejectsEmptyKey) { TEST(TrustTokenKeyCommitmentParser, ParsesBatchSize) { std::string input = R"({ - "batchsize": 5, - "srrkey": "aaaa" + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5 })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); mojom::TrustTokenKeyCommitmentResultPtr result = TrustTokenKeyCommitmentParser().Parse(input); @@ -419,8 +392,10 @@ TEST(TrustTokenKeyCommitmentParser, ParsesBatchSize) { TEST(TrustTokenKeyCommitmentParser, RejectsMissingBatchSize) { std::string input = R"({ - "srrkey": "aaaa", + "protocol_version": "TrustTokenV2PMB", "id": 1 })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); mojom::TrustTokenKeyCommitmentResultPtr result = TrustTokenKeyCommitmentParser().Parse(input); @@ -430,9 +405,11 @@ TEST(TrustTokenKeyCommitmentParser, RejectsMissingBatchSize) { TEST(TrustTokenKeyCommitmentParser, RejectsNonpositiveBatchSize) { std::string input = R"({ - "srrkey": "aaaa", - "batchsize": "0", + "protocol_version": "TrustTokenV2PMB", "id": 1, + "batchsize": 0 })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); mojom::TrustTokenKeyCommitmentResultPtr result = TrustTokenKeyCommitmentParser().Parse(input); @@ -442,9 +419,323 @@ TEST(TrustTokenKeyCommitmentParser, RejectsNonpositiveBatchSize) { TEST(TrustTokenKeyCommitmentParser, RejectsTypeUnsafeBatchSize) { std::string input = R"({ - "srrkey": "aaaa", + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": "not a number" })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + EXPECT_FALSE(result); +} + +TEST(TrustTokenKeyCommitmentParser, RequestIssuanceLocallyOn) { + std::string input = + R"({ + "srrkey": "aaaa", + "batchsize": 1, + "protocol_version": "TrustTokenV2PMB", + "id": 1, + "request_issuance_locally_on": ["android"], + "unavailable_local_issuance_fallback": "web_issuance" + })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + ASSERT_TRUE(result); + EXPECT_THAT(result->request_issuance_locally_on, + ElementsAre(mojom::TrustTokenKeyCommitmentResult::Os::kAndroid)); +} + +TEST(TrustTokenKeyCommitmentParser, DeduplicatesRequestIssuanceLocallyOn) { + std::string input = + R"({ + "srrkey": "aaaa", + "batchsize": 1, + "protocol_version": "TrustTokenV2PMB", + "id": 1, + "request_issuance_locally_on": ["android", "android", "android"], + "unavailable_local_issuance_fallback": "web_issuance" + })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + ASSERT_TRUE(result); + EXPECT_THAT(result->request_issuance_locally_on, + ElementsAre(mojom::TrustTokenKeyCommitmentResult::Os::kAndroid)); +} + +TEST(TrustTokenKeyCommitmentParser, NoRequestIssuanceLocallyOn) { + std::string input = + R"({ + "srrkey": "aaaa", + "batchsize": 1, + "protocol_version": "TrustTokenV2PMB", + "id": 1 + })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + ASSERT_TRUE(result); + EXPECT_TRUE(result->request_issuance_locally_on.empty()); +} + +TEST(TrustTokenKeyCommitmentParser, RejectsTypeUnsafeRequestIssuanceLocallyOn) { + std::string input = + R"({ + "srrkey": "aaaa", + "batchsize": 1, + "protocol_version": "TrustTokenV2PMB", + "id": 1, + "request_issuance_locally_on": "not an array", + "unavailable_local_issuance_fallback": "web_issuance" + })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + EXPECT_FALSE(result); +} + +TEST(TrustTokenKeyCommitmentParser, + RejectsTypeUnsafeRequestIssuanceLocallyOnMember) { + std::string input = + R"({ + "srrkey": "aaaa", + "batchsize": 1, + "protocol_version": "TrustTokenV2PMB", + "id": 1, + "request_issuance_locally_on": ["android", 47], + "unavailable_local_issuance_fallback": "web_issuance" + })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + EXPECT_FALSE(result); +} + +TEST(TrustTokenKeyCommitmentParser, + RejectsUnrecognizedOsInRequestIssuanceLocallyOn) { + std::string input = + R"({ + "srrkey": "aaaa", + "batchsize": 1, + "protocol_version": "TrustTokenV2PMB", + "id": 1, + "request_issuance_locally_on": ["android", "imaginaryOS"], + "unavailable_local_issuance_fallback": "web_issuance" + })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + EXPECT_FALSE(result); +} + +TEST(TrustTokenKeyCommitmentParser, + ProvidingLocalIssuanceOsRequiresSpecifyingIssuanceFallback) { + std::string input = + R"({ + "srrkey": "aaaa", + "batchsize": 1, + "protocol_version": "TrustTokenV2PMB", + "id": 1, + "request_issuance_locally_on": ["android"] + })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + EXPECT_FALSE(result); +} + +TEST(TrustTokenKeyCommitmentParser, + RejectsTypeUnsafeUnavailableLocalIssuanceFallback) { + std::string input = + R"({ + "srrkey": "aaaa", + "batchsize": 1, + "protocol_version": "TrustTokenV2PMB", + "id": 1, + "request_issuance_locally_on": ["android"], + "unavailable_local_issuance_fallback": 57 + })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + EXPECT_FALSE(result); +} + +TEST(TrustTokenKeyCommitmentParser, + RejectsUnrecognizedUnavailableLocalIssuanceFallback) { + std::string input = + R"({ + "srrkey": "aaaa", + "batchsize": 1, + "protocol_version": "TrustTokenV2PMB", + "id": 1, + "request_issuance_locally_on": ["android"], + "unavailable_local_issuance_fallback": "not a valid enum value" + })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + EXPECT_FALSE(result); +} + +TEST(TrustTokenKeyCommitmentParser, ParsesLocalIssuanceFallbackWebIssuance) { + std::string input = + R"({ + "srrkey": "aaaa", + "batchsize": 1, + "protocol_version": "TrustTokenV2PMB", + "id": 1, + "request_issuance_locally_on": ["android"], + "unavailable_local_issuance_fallback": "web_issuance" + })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + ASSERT_TRUE(result); + EXPECT_EQ(result->unavailable_local_issuance_fallback, + mojom::TrustTokenKeyCommitmentResult:: + UnavailableLocalIssuanceFallback::kWebIssuance); +} + +TEST(TrustTokenKeyCommitmentParser, + ParsesLocalIssuanceFallbackReturnWithError) { + std::string input = + R"({ + "srrkey": "aaaa", + "batchsize": 1, + "protocol_version": "TrustTokenV2PMB", + "id": 1, + "request_issuance_locally_on": ["android"], + "unavailable_local_issuance_fallback": "return_with_error" + })"; + // Double-check that the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + ASSERT_TRUE(result); + EXPECT_EQ(result->unavailable_local_issuance_fallback, + mojom::TrustTokenKeyCommitmentResult:: + UnavailableLocalIssuanceFallback::kReturnWithError); +} + +TEST(TrustTokenKeyCommitmentParser, ParsesProtocolVersion) { + std::string input = + R"({ + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, + "srrkey": "aaaa" + })"; + // Make sure the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + ASSERT_TRUE(result); + EXPECT_EQ(result->protocol_version, + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb); +} + +TEST(TrustTokenKeyCommitmentParser, RejectsMissingProtocolVersion) { + std::string input = + R"({ + "id": 1, "batchsize": 5, "srrkey": "aaaa" + })"; + // Make sure the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + EXPECT_FALSE(result); +} + +TEST(TrustTokenKeyCommitmentParser, RejectsUnknownProtocolVersion) { + std::string input = + R"({ + "protocol_version": "TrustTokenJunk", "id": 1, "srrkey": "aaaa", + "batchsize": 5 + })"; + // Make sure the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + EXPECT_FALSE(result); +} + +TEST(TrustTokenKeyCommitmentParser, RejectsTypeUnsafeProtocolVersion) { + std::string input = + R"({ + "protocol_version": 5, "id": 1, "srrkey": "aaaa", + "batchsize": 5 + })"; + // Make sure the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + EXPECT_FALSE(result); +} + +TEST(TrustTokenKeyCommitmentParser, ParsesID) { + std::string input = + R"({ + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5, + "srrkey": "aaaa" + })"; + // Make sure the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + ASSERT_TRUE(result); + ASSERT_TRUE(result->id); + EXPECT_EQ(result->id, 1); +} + +TEST(TrustTokenKeyCommitmentParser, RejectsMissingID) { + std::string input = + R"({ + "protocol_version": "TrustTokenV2PMB", "batchsize": 5, "srrkey": "aaaa" + })"; + // Make sure the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); + + mojom::TrustTokenKeyCommitmentResultPtr result = + TrustTokenKeyCommitmentParser().Parse(input); + EXPECT_FALSE(result); +} + +TEST(TrustTokenKeyCommitmentParser, RejectsTypeUnsafeID) { + std::string input = + R"({ + "protocol_version": "TrustTokenV2PMB", "id": "foo", "srrkey": "aaaa", + "batchsize": 5 + })"; + // Make sure the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); mojom::TrustTokenKeyCommitmentResultPtr result = TrustTokenKeyCommitmentParser().Parse(input); @@ -462,6 +753,8 @@ TEST(TrustTokenKeyCommitmentParserMultipleIssuers, InvalidJson) { TEST(TrustTokenKeyCommitmentParserMultipleIssuers, NotADictionary) { std::string input = "3"; + // Make sure the input is actually valid JSON. + ASSERT_TRUE(base::JSONReader::Read(input)); auto result = TrustTokenKeyCommitmentParser().ParseMultipleIssuers(input); EXPECT_FALSE(result); @@ -482,7 +775,8 @@ TEST(TrustTokenKeyCommitmentParserMultipleIssuers, UnsuitableKey) { // Test that a key with an unsuitable Trust Tokens origin gets skipped. std::string input = R"( { "http://insecure.example/": - { "batchsize": 5, "srrkey": "aaaa" } } )"; + { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5 + } } )"; // Make sure the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); @@ -509,7 +803,8 @@ TEST(TrustTokenKeyCommitmentParserMultipleIssuers, SuitableKeyInvalidValue) { TEST(TrustTokenKeyCommitmentParserMultipleIssuers, SingleIssuer) { std::string input = R"( { "https://issuer.example/": { - "batchsize": 5, "srrkey": "aaaa" } } )"; + "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5 + } } )"; // Make sure the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); @@ -521,16 +816,21 @@ TEST(TrustTokenKeyCommitmentParserMultipleIssuers, SingleIssuer) { auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example")); ASSERT_TRUE(result->count(issuer)); - EXPECT_TRUE(mojo::Equals(result->at(issuer), parser.Parse(R"({ "batchsize": 5, - "srrkey": "aaaa" })"))); + EXPECT_TRUE(mojo::Equals( + result->at(issuer), + parser.Parse( + R"({ "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5 + })"))); } TEST(TrustTokenKeyCommitmentParserMultipleIssuers, DuplicateIssuer) { std::string input = - R"( { "https://issuer.example/": { "batchsize": 5, "srrkey": "aaaa" }, - "https://other.example/": { "batchsize": 5, "srrkey": "aaab" }, + R"( { "https://issuer.example/": { "protocol_version": "TrustTokenV2PMB", + "id": 1, "batchsize": 5 }, + "https://other.example/": { "protocol_version": "TrustTokenV2PMB", + "id": 1, "batchsize": 5 }, "https://issuer.example/this-is-really-the-same-issuer-as-the-first-entry": - { "batchsize": 5, "srrkey": "aaac" } + { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 3 } } )"; // Make sure the input is actually valid JSON. @@ -548,9 +848,11 @@ TEST(TrustTokenKeyCommitmentParserMultipleIssuers, DuplicateIssuer) { auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example")); ASSERT_TRUE(result->count(issuer)); - EXPECT_TRUE( - mojo::Equals(result->at(issuer), - parser.Parse(R"({ "batchsize": 5, "srrkey": "aaac" })"))); + EXPECT_TRUE(mojo::Equals( + result->at(issuer), + parser.Parse( + R"({ "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 3 + })"))); } TEST(TrustTokenKeyCommitmentParserMultipleIssuers, DuplicateIssuerFirstWins) { @@ -560,10 +862,12 @@ TEST(TrustTokenKeyCommitmentParserMultipleIssuers, DuplicateIssuerFirstWins) { std::string input = R"( { - "https://issuer.example/longer": { "batchsize": 5, "srrkey": "aaaa" }, - "https://other.example/": { "batchsize": 5, "srrkey": "aaab" }, + "https://issuer.example/longer": { "protocol_version": "TrustTokenV2PMB", + "id": 1, "batchsize": 5 }, + "https://other.example/": { "protocol_version": "TrustTokenV2PMB", "id": 1, + "batchsize": 5 }, "https://issuer.example/": - { "batchsize": 5, "srrkey": "aaac" } + { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 3 } } )"; // Make sure the input is actually valid JSON. @@ -581,16 +885,20 @@ TEST(TrustTokenKeyCommitmentParserMultipleIssuers, DuplicateIssuerFirstWins) { auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example")); ASSERT_TRUE(result->count(issuer)); - EXPECT_TRUE( - mojo::Equals(result->at(issuer), - parser.Parse(R"({ "batchsize": 5, "srrkey": "aaaa" })"))); + EXPECT_TRUE(mojo::Equals( + result->at(issuer), + parser.Parse( + R"({ "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5 + })"))); } TEST(TrustTokenKeyCommitmentParserMultipleIssuers, MixOfSuitableAndUnsuitableIssuers) { std::string input = R"( { - "https://issuer.example/": { "batchsize": 5, "srrkey": "aaaa" }, - "http://insecure.example": { "batchsize": 5, "srrkey": "bbbb" } } )"; + "https://issuer.example/": { "protocol_version": "TrustTokenV2PMB", "id": 1, + "batchsize": 5 }, + "http://insecure.example": { "protocol_version": "TrustTokenV2PMB", "id": 1, + "batchsize": 5 } } )"; // Make sure the input is actually valid JSON. ASSERT_TRUE(base::JSONReader::Read(input)); @@ -604,9 +912,11 @@ TEST(TrustTokenKeyCommitmentParserMultipleIssuers, auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example")); ASSERT_TRUE(result->count(issuer)); - EXPECT_TRUE( - mojo::Equals(result->at(issuer), - parser.Parse(R"({ "batchsize": 5, "srrkey": "aaaa" })"))); + EXPECT_TRUE(mojo::Equals( + result->at(issuer), + parser.Parse( + R"({ "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5 + })"))); } } // namespace network diff --git a/chromium/services/network/trust_tokens/trust_token_key_commitments.cc b/chromium/services/network/trust_tokens/trust_token_key_commitments.cc index 4b50e745c68..4e7a7eaa91a 100644 --- a/chromium/services/network/trust_tokens/trust_token_key_commitments.cc +++ b/chromium/services/network/trust_tokens/trust_token_key_commitments.cc @@ -51,8 +51,8 @@ ParseCommitmentsFromCommandLine() { mojom::TrustTokenKeyCommitmentResultPtr FilterCommitments( mojom::TrustTokenKeyCommitmentResultPtr result) { if (result) { - RetainSoonestToExpireTrustTokenKeys( - &result->keys, kMaximumConcurrentlyValidTrustTokenVerificationKeys); + size_t max_keys = TrustTokenMaxKeysForVersion(result->protocol_version); + RetainSoonestToExpireTrustTokenKeys(&result->keys, max_keys); } return result; @@ -117,7 +117,7 @@ mojom::TrustTokenKeyCommitmentResultPtr TrustTokenKeyCommitments::GetSync( if (!additional_commitments_from_command_line_.empty()) { auto it = additional_commitments_from_command_line_.find(*suitable_origin); - if (it != commitments_.end()) { + if (it != additional_commitments_from_command_line_.end()) { return FilterCommitments(it->second->Clone()); } } diff --git a/chromium/services/network/trust_tokens/trust_token_key_commitments.h b/chromium/services/network/trust_tokens/trust_token_key_commitments.h index e32446a52c1..e86b37d58dd 100644 --- a/chromium/services/network/trust_tokens/trust_token_key_commitments.h +++ b/chromium/services/network/trust_tokens/trust_token_key_commitments.h @@ -50,9 +50,8 @@ class TrustTokenKeyCommitments // // If |origin| is not suitable, or if no commitment result is found, returns // nullptr. Otherwise, returns the key commitment result stored for |origin|, - // with its verification keys filtered to contain at most - // |kMaximumConcurrentlyValidTrustTokenVerificationKeys| keys, none of - // which has yet expired. + // with its verification keys filtered to contain at most the maximum number + // of keys allowed for the protocol version, none of which has yet expired. // // If commitments for |origin| were passed both through a prior call to |Set| // and through the --additional-trust-token-key-commitments command-line diff --git a/chromium/services/network/trust_tokens/trust_token_key_commitments_unittest.cc b/chromium/services/network/trust_tokens/trust_token_key_commitments_unittest.cc index 87166584ac1..c01a6c94b21 100644 --- a/chromium/services/network/trust_tokens/trust_token_key_commitments_unittest.cc +++ b/chromium/services/network/trust_tokens/trust_token_key_commitments_unittest.cc @@ -5,7 +5,7 @@ #include "services/network/trust_tokens/trust_token_key_commitments.h" #include "base/base64.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/scoped_command_line.h" #include "base/test/task_environment.h" #include "services/network/public/cpp/network_switches.h" @@ -64,6 +64,9 @@ TEST(TrustTokenKeyCommitments, CanRetrieveRecordForSuitableOrigin) { TrustTokenKeyCommitments commitments; auto expectation = mojom::TrustTokenKeyCommitmentResult::New(); + expectation->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + expectation->id = 1; expectation->batch_size = 5; auto suitable_origin = *SuitableTrustTokenOrigin::Create( @@ -88,6 +91,9 @@ TEST(TrustTokenKeyCommitments, CantRetrieveRecordForOriginNotPresent) { auto an_origin = *SuitableTrustTokenOrigin::Create(GURL("https://an-origin.example")); auto an_expectation = mojom::TrustTokenKeyCommitmentResult::New(); + an_expectation->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + an_expectation->id = 1; an_expectation->batch_size = 5; base::flat_map<url::Origin, mojom::TrustTokenKeyCommitmentResultPtr> to_set; @@ -114,7 +120,13 @@ TEST(TrustTokenKeyCommitments, MultipleOrigins) { mojom::TrustTokenKeyCommitmentResult::New(), }; + expectations[0]->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + expectations[0]->id = 1; expectations[0]->batch_size = 0; + expectations[1]->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + expectations[1]->id = 1; expectations[1]->batch_size = 1; base::flat_map<url::Origin, mojom::TrustTokenKeyCommitmentResultPtr> to_set; @@ -132,7 +144,7 @@ TEST(TrustTokenKeyCommitments, MultipleOrigins) { TEST(TrustTokenKeyCommitments, ParseAndSet) { TrustTokenKeyCommitments commitments; commitments.ParseAndSet( - R"( { "https://issuer.example": { "batchsize": 5, "srrkey": "aaaa" } } )"); + R"( { "https://issuer.example": { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5 } } )"); EXPECT_TRUE(GetCommitmentForOrigin( commitments, @@ -143,7 +155,7 @@ TEST(TrustTokenKeyCommitments, KeysFromCommandLine) { base::test::ScopedCommandLine command_line; command_line.GetProcessCommandLine()->AppendSwitchASCII( switches::kAdditionalTrustTokenKeyCommitments, - R"( { "https://issuer.example": { "batchsize": 5, "srrkey": "aaaa" } } )"); + R"( { "https://issuer.example": { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 5 } } )"); TrustTokenKeyCommitments commitments; @@ -152,18 +164,15 @@ TEST(TrustTokenKeyCommitments, KeysFromCommandLine) { *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example")))); commitments.ParseAndSet( - R"( { "https://issuer.example": { "batchsize": 10, "srrkey": "bbbb" } } )"); - - // A commitment provided through |Set| should defer to the one passed - // through the command line. - std::string expected_srrkey; - ASSERT_TRUE(base::Base64Decode("aaaa", &expected_srrkey)); + R"( { "https://issuer.example": { "protocol_version": "TrustTokenV2PMB", "id": 1, "batchsize": 10 } } )"); auto result = GetCommitmentForOrigin( commitments, *SuitableTrustTokenOrigin::Create(GURL("https://issuer.example"))); ASSERT_TRUE(result); - EXPECT_EQ(result->signed_redemption_record_verification_key, expected_srrkey); + EXPECT_EQ(result->protocol_version, + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb); + EXPECT_EQ(result->id, 1); EXPECT_EQ(result->batch_size, 5); } @@ -180,10 +189,9 @@ TEST(TrustTokenKeyCommitments, FiltersKeys) { expired_key->expiry = base::Time::Now() - base::TimeDelta::FromMinutes(1); commitment_result->keys.push_back(std::move(expired_key)); - static_assert(kMaximumConcurrentlyValidTrustTokenVerificationKeys < 100, - "If the constant grows large, consider rewriting this test."); - for (size_t i = 0; i < kMaximumConcurrentlyValidTrustTokenVerificationKeys; - ++i) { + size_t max_keys = TrustTokenMaxKeysForVersion( + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb); + for (size_t i = 0; i < max_keys; ++i) { auto not_expired_key = mojom::TrustTokenVerificationKey::New(); not_expired_key->expiry = base::Time::Now() + base::TimeDelta::FromMinutes(1); @@ -195,15 +203,13 @@ TEST(TrustTokenKeyCommitments, FiltersKeys) { base::Time::Now() + base::TimeDelta::FromMinutes(2); // We expect to get rid of the expired key and the farthest-in-the-future key - // (since there are more than kMaximum... many keys yet to expire). + // (since there are more than |max_keys| many keys yet to expire). base::flat_map<url::Origin, mojom::TrustTokenKeyCommitmentResultPtr> to_set; to_set.insert_or_assign(origin.origin(), commitment_result.Clone()); commitments.Set(std::move(to_set)); auto result = GetCommitmentForOrigin(commitments, origin); - EXPECT_EQ( - result->keys.size(), - static_cast<size_t>(kMaximumConcurrentlyValidTrustTokenVerificationKeys)); + EXPECT_EQ(result->keys.size(), max_keys); EXPECT_TRUE(std::all_of(result->keys.begin(), result->keys.end(), [](const mojom::TrustTokenVerificationKeyPtr& key) { return key->expiry == @@ -216,6 +222,9 @@ TEST(TrustTokenKeyCommitments, GetSync) { TrustTokenKeyCommitments commitments; auto expectation = mojom::TrustTokenKeyCommitmentResult::New(); + expectation->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + expectation->id = 1; expectation->batch_size = 5; auto suitable_origin = *SuitableTrustTokenOrigin::Create( diff --git a/chromium/services/network/trust_tokens/trust_token_parameterization.cc b/chromium/services/network/trust_tokens/trust_token_parameterization.cc new file mode 100644 index 00000000000..164fc0d3f91 --- /dev/null +++ b/chromium/services/network/trust_tokens/trust_token_parameterization.cc @@ -0,0 +1,20 @@ +// 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 "services/network/trust_tokens/trust_token_parameterization.h" + +#include "services/network/public/mojom/trust_tokens.mojom-forward.h" + +namespace network { + +size_t TrustTokenMaxKeysForVersion(mojom::TrustTokenProtocolVersion version) { + switch (version) { + case mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb: + return 3; + case mojom::TrustTokenProtocolVersion::kTrustTokenV2Voprf: + return 6; + } +} + +} // namespace network diff --git a/chromium/services/network/trust_tokens/trust_token_parameterization.h b/chromium/services/network/trust_tokens/trust_token_parameterization.h index 93209d72c3f..5302b205fa0 100644 --- a/chromium/services/network/trust_tokens/trust_token_parameterization.h +++ b/chromium/services/network/trust_tokens/trust_token_parameterization.h @@ -8,6 +8,7 @@ #include "base/component_export.h" #include "base/task/task_traits.h" #include "base/time/time.h" +#include "services/network/public/mojom/trust_tokens.mojom-shared.h" namespace network { @@ -57,17 +58,15 @@ constexpr int kTrustTokenPerIssuerTokenCapacity = 500; // an issuer). constexpr int kMaximumTrustTokenIssuanceBatchSize = 100; -// When executing Trust Tokens issuance and redemption, -// use at most |kMaximumConcurrentlyValidTrustTokenVerificationKeys| many -// soonest-to-expire-but-unexpired keys from the available key commitments. -constexpr int kMaximumConcurrentlyValidTrustTokenVerificationKeys = 3; - // When to expire a signed redemption record, assuming that the issuer declined // to specify the optional expiry timestamp. This value was chosen in absence of // a specific reason to pick anything shorter; it could be revisited. constexpr base::Time kTrustTokenDefaultRedemptionRecordExpiry = base::Time::Max(); +// Returns the maximum number of keys supported by a protocol version. +size_t TrustTokenMaxKeysForVersion(mojom::TrustTokenProtocolVersion version); + } // namespace network #endif // SERVICES_NETWORK_TRUST_TOKENS_TRUST_TOKEN_PARAMETERIZATION_H_ diff --git a/chromium/services/network/trust_tokens/trust_token_persister_unittest.cc b/chromium/services/network/trust_tokens/trust_token_persister_unittest.cc index a082bd6e162..a13ae550806 100644 --- a/chromium/services/network/trust_tokens/trust_token_persister_unittest.cc +++ b/chromium/services/network/trust_tokens/trust_token_persister_unittest.cc @@ -8,7 +8,7 @@ #include <string> #include <utility> -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "services/network/trust_tokens/in_memory_trust_token_persister.h" diff --git a/chromium/services/network/trust_tokens/trust_token_request_canonicalizer.cc b/chromium/services/network/trust_tokens/trust_token_request_canonicalizer.cc index e7b91f15447..7a4273c7a32 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_canonicalizer.cc +++ b/chromium/services/network/trust_tokens/trust_token_request_canonicalizer.cc @@ -10,8 +10,8 @@ #include "components/cbor/values.h" #include "components/cbor/writer.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include "services/network/public/cpp/trust_token_http_headers.h" #include "services/network/public/mojom/trust_tokens.mojom-shared.h" -#include "services/network/trust_tokens/trust_token_http_headers.h" #include "services/network/trust_tokens/trust_token_request_signing_helper.h" namespace network { diff --git a/chromium/services/network/trust_tokens/trust_token_request_canonicalizer_unittest.cc b/chromium/services/network/trust_tokens/trust_token_request_canonicalizer_unittest.cc index dbe34848f20..e00870eea36 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_canonicalizer_unittest.cc +++ b/chromium/services/network/trust_tokens/trust_token_request_canonicalizer_unittest.cc @@ -9,9 +9,9 @@ #include "components/cbor/values.h" #include "components/cbor/writer.h" #include "net/url_request/url_request.h" +#include "services/network/public/cpp/trust_token_http_headers.h" #include "services/network/public/mojom/trust_tokens.mojom-shared.h" #include "services/network/trust_tokens/test/trust_token_test_util.h" -#include "services/network/trust_tokens/trust_token_http_headers.h" #include "services/network/trust_tokens/trust_token_request_canonicalizer.h" #include "services/network/trust_tokens/trust_token_request_signing_helper.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/services/network/trust_tokens/trust_token_request_helper_factory.cc b/chromium/services/network/trust_tokens/trust_token_request_helper_factory.cc index a1834dee258..c5b9d704be5 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_helper_factory.cc +++ b/chromium/services/network/trust_tokens/trust_token_request_helper_factory.cc @@ -15,18 +15,20 @@ #include "net/log/net_log_with_source.h" #include "net/url_request/url_request.h" #include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/trust_token_http_headers.h" #include "services/network/public/cpp/trust_token_parameterization.h" #include "services/network/public/mojom/trust_tokens.mojom-shared.h" #include "services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer.h" #include "services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.h" #include "services/network/trust_tokens/ed25519_key_pair_generator.h" #include "services/network/trust_tokens/ed25519_trust_token_request_signer.h" +#include "services/network/trust_tokens/local_trust_token_operation_delegate.h" +#include "services/network/trust_tokens/local_trust_token_operation_delegate_impl.h" +#include "services/network/trust_tokens/operating_system_matching.h" #include "services/network/trust_tokens/suitable_trust_token_origin.h" -#include "services/network/trust_tokens/trust_token_http_headers.h" #include "services/network/trust_tokens/trust_token_key_commitment_controller.h" #include "services/network/trust_tokens/trust_token_parameterization.h" #include "services/network/trust_tokens/trust_token_request_canonicalizer.h" -#include "services/network/trust_tokens/trust_token_request_issuance_helper.h" #include "services/network/trust_tokens/trust_token_request_redemption_helper.h" #include "services/network/trust_tokens/trust_token_request_signing_helper.h" #include "services/network/trust_tokens/types.h" @@ -78,9 +80,12 @@ void LogOutcome(const net::NetLogWithSource& log, TrustTokenRequestHelperFactory::TrustTokenRequestHelperFactory( PendingTrustTokenStore* store, const TrustTokenKeyCommitmentGetter* key_commitment_getter, + base::RepeatingCallback<mojom::NetworkContextClient*(void)> + context_client_provider, base::RepeatingCallback<bool(void)> authorizer) : store_(store), key_commitment_getter_(key_commitment_getter), + context_client_provider_(std::move(context_client_provider)), authorizer_(std::move(authorizer)) {} TrustTokenRequestHelperFactory::~TrustTokenRequestHelperFactory() = default; @@ -143,6 +148,9 @@ void TrustTokenRequestHelperFactory::ConstructHelperUsingStore( new TrustTokenRequestIssuanceHelper( std::move(top_frame_origin), store, key_commitment_getter_, std::make_unique<BoringsslTrustTokenIssuanceCryptographer>(), + std::make_unique<LocalTrustTokenOperationDelegateImpl>( + context_client_provider_), + base::BindRepeating(&IsCurrentOperatingSystem), std::move(net_log)))); return; } diff --git a/chromium/services/network/trust_tokens/trust_token_request_helper_factory.h b/chromium/services/network/trust_tokens/trust_token_request_helper_factory.h index 3bbbd47d6fb..27d00eaac10 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_helper_factory.h +++ b/chromium/services/network/trust_tokens/trust_token_request_helper_factory.h @@ -13,10 +13,12 @@ #include "net/log/net_log_with_source.h" #include "services/network/public/cpp/features.h" #include "services/network/public/mojom/trust_tokens.mojom.h" +#include "services/network/trust_tokens/local_trust_token_operation_delegate.h" #include "services/network/trust_tokens/pending_trust_token_store.h" #include "services/network/trust_tokens/suitable_trust_token_origin.h" #include "services/network/trust_tokens/trust_token_key_commitment_getter.h" #include "services/network/trust_tokens/trust_token_request_helper.h" +#include "services/network/trust_tokens/trust_token_request_issuance_helper.h" namespace network { @@ -55,12 +57,20 @@ class TrustTokenRequestHelperFactory { // Tokens state and |key_commitment_getter| to obtain keys; consequently, both // arguments must outlive all of the created helpers. // + // |context_client_provider| provides a handle to a NetworkContextClient that + // will be used for requesting Trust Tokens operations' local execution. + // context_client_provider.Run() will be called before each attempt to + // delegate a Trust Tokens operation. It is permitted to return nullptr; in + // this case, the operation will be cancelled. + // // Each decision whether to vend a helper will first query |authorizer| to // determine whether it's currently allowed to execute Trust Tokens // operations. TrustTokenRequestHelperFactory( PendingTrustTokenStore* store, const TrustTokenKeyCommitmentGetter* key_commitment_getter, + base::RepeatingCallback<mojom::NetworkContextClient*(void)> + context_client_provider, base::RepeatingCallback<bool(void)> authorizer); TrustTokenRequestHelperFactory(const TrustTokenRequestHelperFactory&) = @@ -102,6 +112,8 @@ class TrustTokenRequestHelperFactory { PendingTrustTokenStore* store_; const TrustTokenKeyCommitmentGetter* key_commitment_getter_; + base::RepeatingCallback<mojom::NetworkContextClient*(void)> + context_client_provider_; base::RepeatingCallback<bool(void)> authorizer_; base::WeakPtrFactory<TrustTokenRequestHelperFactory> weak_factory_{this}; diff --git a/chromium/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc b/chromium/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc index e5fce7615b2..28efbc084d9 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc +++ b/chromium/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc @@ -6,18 +6,18 @@ #include "base/optional.h" #include "base/strings/strcat.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" #include "net/base/isolation_info.h" #include "net/url_request/url_request.h" #include "services/network/public/cpp/optional_trust_token_params.h" #include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/trust_token_http_headers.h" #include "services/network/public/cpp/trust_token_parameterization.h" #include "services/network/public/mojom/trust_tokens.mojom.h" #include "services/network/trust_tokens/pending_trust_token_store.h" #include "services/network/trust_tokens/test/trust_token_test_util.h" -#include "services/network/trust_tokens/trust_token_http_headers.h" #include "services/network/trust_tokens/trust_token_parameterization.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/origin.h" @@ -95,8 +95,11 @@ class TrustTokenRequestHelperFactoryTest : public ::testing::Test { store.OnStoreReady(TrustTokenStore::CreateForTesting()); NoopTrustTokenKeyCommitmentGetter getter; - TrustTokenRequestHelperFactory(&store, &getter, - base::BindRepeating([]() { return true; })) + TrustTokenRequestHelperFactory( + &store, &getter, + base::BindRepeating( + []() -> mojom::NetworkContextClient* { return nullptr; }), + base::BindRepeating([]() { return true; })) .CreateTrustTokenHelperForRequest( request, params, base::BindLambdaForTesting( @@ -269,8 +272,11 @@ TEST_F(TrustTokenRequestHelperFactoryTest, RespectsAuthorizer) { store.OnStoreReady(TrustTokenStore::CreateForTesting()); NoopTrustTokenKeyCommitmentGetter getter; - TrustTokenRequestHelperFactory(&store, &getter, - base::BindRepeating([]() { return false; })) + TrustTokenRequestHelperFactory( + &store, &getter, + base::BindRepeating( + []() -> mojom::NetworkContextClient* { return nullptr; }), + base::BindRepeating([]() { return false; })) .CreateTrustTokenHelperForRequest( suitable_request(), suitable_signing_params(), base::BindLambdaForTesting( diff --git a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.cc b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.cc index d4dcbaaa7b3..1f12d25c94b 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.cc +++ b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.cc @@ -7,18 +7,21 @@ #include <utility> #include "base/callback.h" +#include "base/command_line.h" +#include "base/metrics/field_trial_params.h" +#include "base/stl_util.h" #include "base/task/thread_pool.h" #include "net/base/load_flags.h" #include "net/http/http_response_headers.h" #include "net/log/net_log_event_type.h" #include "net/url_request/url_request.h" +#include "services/network/public/cpp/features.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" -#include "services/network/public/mojom/trust_tokens.mojom-forward.h" +#include "services/network/public/cpp/trust_token_http_headers.h" #include "services/network/public/mojom/trust_tokens.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "services/network/trust_tokens/proto/public.pb.h" #include "services/network/trust_tokens/suitable_trust_token_origin.h" -#include "services/network/trust_tokens/trust_token_http_headers.h" #include "services/network/trust_tokens/trust_token_key_filtering.h" #include "services/network/trust_tokens/trust_token_parameterization.h" #include "services/network/trust_tokens/trust_token_store.h" @@ -82,11 +85,16 @@ TrustTokenRequestIssuanceHelper::TrustTokenRequestIssuanceHelper( TrustTokenStore* token_store, const TrustTokenKeyCommitmentGetter* key_commitment_getter, std::unique_ptr<Cryptographer> cryptographer, + std::unique_ptr<LocalTrustTokenOperationDelegate> local_operation_delegate, + base::RepeatingCallback<bool(mojom::TrustTokenKeyCommitmentResult::Os)> + is_current_os_callback, net::NetLogWithSource net_log) : top_level_origin_(std::move(top_level_origin)), token_store_(token_store), key_commitment_getter_(std::move(key_commitment_getter)), cryptographer_(std::move(cryptographer)), + local_operation_delegate_(std::move(local_operation_delegate)), + is_current_os_callback_(std::move(is_current_os_callback)), net_log_(std::move(net_log)) { DCHECK(token_store_); DCHECK(key_commitment_getter_); @@ -144,8 +152,29 @@ void TrustTokenRequestIssuanceHelper::OnGotKeyCommitment( return; } + if (features::kPlatformProvidedTrustTokenIssuance.Get() && + !commitment_result->request_issuance_locally_on.empty()) { + should_divert_issuance_request_to_os_ = base::ranges::any_of( + commitment_result->request_issuance_locally_on, + [this](mojom::TrustTokenKeyCommitmentResult::Os os) { + return is_current_os_callback_.Run(os); + }); + if (!should_divert_issuance_request_to_os_ && + commitment_result->unavailable_local_issuance_fallback == + mojom::TrustTokenKeyCommitmentResult:: + UnavailableLocalIssuanceFallback::kReturnWithError) { + // If the issuer requests that issuance be mediated by the OS on at least + // one platform, and we aren't on that platform, and the issuer has + // configured that we should return with an error in this case, do so. + std::move(done).Run(mojom::TrustTokenOperationStatus::kUnavailable); + return; + } + } + + protocol_version_ = commitment_result->protocol_version; if (!commitment_result->batch_size || - !cryptographer_->Initialize(commitment_result->batch_size)) { + !cryptographer_->Initialize(protocol_version_, + commitment_result->batch_size)) { LogOutcome(net_log_, kBegin, "Internal error initializing cryptography delegate"); std::move(done).Run(mojom::TrustTokenOperationStatus::kInternalError); @@ -194,10 +223,33 @@ void TrustTokenRequestIssuanceHelper::OnDelegateBeginIssuanceCallComplete( std::move(done).Run(mojom::TrustTokenOperationStatus::kInternalError); return; } + + if (should_divert_issuance_request_to_os_) { + LogOutcome(net_log_, kBegin, + "Passing operation to local issuance provider"); + auto fulfill_request = mojom::FulfillTrustTokenIssuanceRequest::New(); + fulfill_request->issuer = url::Origin::Create(request->url()); + fulfill_request->request = std::move(*maybe_blinded_tokens); + local_operation_delegate_->FulfillIssuance( + std::move(fulfill_request), + base::BindOnce(&TrustTokenRequestIssuanceHelper:: + DoneRequestingLocallyFulfilledIssuance, + weak_ptr_factory_.GetWeakPtr(), std::move(done))); + // |this| may have been deleted and/or Finalize may have been called + // already. + return; + } + request->SetExtraRequestHeaderByName(kTrustTokensSecTrustTokenHeader, std::move(*maybe_blinded_tokens), /*overwrite=*/true); + std::string protocol_string_version = + internal::ProtocolVersionToString(protocol_version_); + request->SetExtraRequestHeaderByName(kTrustTokensSecTrustTokenVersionHeader, + protocol_string_version, + /*overwrite=*/true); + // We don't want cache reads, because the highest priority is to execute the // protocol operation by sending the server the Trust Tokens request header // and getting the corresponding response header, but we want cache writes @@ -234,10 +286,16 @@ void TrustTokenRequestIssuanceHelper::Finalize( response->headers->RemoveHeader(kTrustTokensSecTrustTokenHeader); + ConfirmIssuanceResponse(std::move(header_value), std::move(done)); +} + +void TrustTokenRequestIssuanceHelper::ConfirmIssuanceResponse( + std::string issuance_response, + base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done) { base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&ConfirmIssuanceOnPostedSequence, - std::move(cryptographer_), std::move(header_value)), + std::move(cryptographer_), std::move(issuance_response)), base::BindOnce(&TrustTokenRequestIssuanceHelper:: OnDelegateConfirmIssuanceCallComplete, weak_ptr_factory_.GetWeakPtr(), std::move(done))); @@ -274,4 +332,43 @@ void TrustTokenRequestIssuanceHelper::OnDelegateConfirmIssuanceCallComplete( return; } +void TrustTokenRequestIssuanceHelper::DoneRequestingLocallyFulfilledIssuance( + base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done, + mojom::FulfillTrustTokenIssuanceAnswerPtr answer) { + switch (answer->status) { + case mojom::FulfillTrustTokenIssuanceAnswer::Status::kNotFound: { + std::move(done).Run(mojom::TrustTokenOperationStatus::kUnavailable); + return; + } + case mojom::FulfillTrustTokenIssuanceAnswer::Status::kUnknownError: { + std::move(done).Run(mojom::TrustTokenOperationStatus::kUnknownError); + return; + } + case mojom::FulfillTrustTokenIssuanceAnswer::Status::kOk: + break; + } + + // Log the beginning of the Finalize event here, since this is where we enter + // the main response processing logic when executing issuance locally: + net_log_.BeginEvent( + net::NetLogEventType::TRUST_TOKEN_OPERATION_FINALIZE_ISSUANCE); + ConfirmIssuanceResponse( + std::move(answer->response), + base::BindOnce(&TrustTokenRequestIssuanceHelper:: + DoneFinalizingLocallyFulfilledIssuance, + weak_ptr_factory_.GetWeakPtr(), std::move(done))); +} + +void TrustTokenRequestIssuanceHelper::DoneFinalizingLocallyFulfilledIssuance( + base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done, + mojom::TrustTokenOperationStatus status) { + if (status == mojom::TrustTokenOperationStatus::kOk) { + std::move(done).Run(mojom::TrustTokenOperationStatus:: + kOperationSuccessfullyFulfilledLocally); + return; + } + + std::move(done).Run(status); +} + } // namespace network diff --git a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.h b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.h index 3b7af0aa91d..44f06f6783e 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.h +++ b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.h @@ -6,6 +6,7 @@ #define SERVICES_NETWORK_TRUST_TOKENS_TRUST_TOKEN_REQUEST_ISSUANCE_HELPER_H_ #include <memory> +#include <set> #include <string> #include <vector> @@ -14,6 +15,7 @@ #include "base/strings/string_piece_forward.h" #include "net/log/net_log_with_source.h" #include "services/network/public/mojom/trust_tokens.mojom-shared.h" +#include "services/network/trust_tokens/local_trust_token_operation_delegate.h" #include "services/network/trust_tokens/proto/public.pb.h" #include "services/network/trust_tokens/suitable_trust_token_origin.h" #include "services/network/trust_tokens/trust_token_key_commitment_getter.h" @@ -55,12 +57,15 @@ class TrustTokenRequestIssuanceHelper : public TrustTokenRequestHelper { public: virtual ~Cryptographer() = default; - // Initializes the delegate. |issuer_configured_batch_size| must be the - // "batchsize" value from an issuer-provided key commitment result. + // Initializes the delegate. |issuer_configured_version| and + // |issuer_configured_batch_size| must be the "protocol_version" and + // "batchsize" values from an issuer-provided key commitment result. // // Returns true on success and false if the batch size is unacceptable or an // internal error occurred in the underlying cryptographic library. - virtual bool Initialize(int issuer_configured_batch_size) = 0; + virtual bool Initialize( + mojom::TrustTokenProtocolVersion issuer_configured_version, + int issuer_configured_batch_size) = 0; // Stores a Trust Tokens issuance verification key for subsequent use // verifying signed tokens in |ConfirmIssuance|. May be called multiple @@ -112,16 +117,25 @@ class TrustTokenRequestIssuanceHelper : public TrustTokenRequestHelper { // 2. potentially trustworthy origin to satisfy Web security requirements. // - |token_store| will be responsible for storing underlying Trust Tokens // state. It must outlive this object. - // - |key_commitment_getter| and |cryptographer| are delegates that - // help execute the protocol; see their class comments. + // - |key_commitment_getter|, |cryptographer|, and |local_operation_delegate| + // are delegates that help execute the protocol; see their class comments. + // They must live outlive this object. + // - |is_current_os_callback| should return whether, when the given Os is + // present in the issuer's "request_issuance_locally_on" field in its key + // commitment, the issuance helper should attempt to forward requests to the + // local operation delegate. // - // REQUIRES: |token_store|, |key_commitment_getter|, and |cryptographer| must - // be non-null. + // REQUIRES: |token_store|, |key_commitment_getter|, |cryptographer|, + // |local_operation_delegate|, and |is_current_os_callback| must be non-null. TrustTokenRequestIssuanceHelper( SuitableTrustTokenOrigin top_level_origin, TrustTokenStore* token_store, const TrustTokenKeyCommitmentGetter* key_commitment_getter, std::unique_ptr<Cryptographer> cryptographer, + std::unique_ptr<LocalTrustTokenOperationDelegate> + local_operation_delegate, + base::RepeatingCallback<bool(mojom::TrustTokenKeyCommitmentResult::Os)> + is_current_os_callback, net::NetLogWithSource net_log = net::NetLogWithSource()); ~TrustTokenRequestIssuanceHelper() override; @@ -195,6 +209,13 @@ class TrustTokenRequestIssuanceHelper : public TrustTokenRequestHelper { base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done, CryptographerAndBlindedTokens cryptographer_and_blinded_tokens); + // Continuation of |Finalize| after extracting the base64-encoded issuance + // response from a response header (or receiving it from a locally executed + // operation). + void ConfirmIssuanceResponse( + std::string issuance_response, + base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done); + // Continuation of |Finalize| after a call to the cryptography delegate to // execute the bulk of the inbound half of the issuance operation. // Receives ownership of the cryptographer back from the asynchronous @@ -203,6 +224,25 @@ class TrustTokenRequestIssuanceHelper : public TrustTokenRequestHelper { base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done, CryptographerAndUnblindedTokens cryptographer_and_unblinded_tokens); + // DoneRequestingLocallyFulfilledIssuance proceeds with a locally fulfilled + // issuance operation by handling the operation's response |answer|, + // either terminating the operation with an error passed to |done| (if + // |answer| contains an error) or continuing to finalize the operation (if + // |answer| contains an issuance response). + void DoneRequestingLocallyFulfilledIssuance( + base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done, + mojom::FulfillTrustTokenIssuanceAnswerPtr answer); + + // DoneFinalizingLocallyFulfilledIssuance determines a final response status + // to pass to the caller via |done|, then calls the callback. + // + // If the operation succeeded, calls |done| with + // kOperationSuccessfullyFulfilledLocally. Otherwise, calls |done| with + // |status|. + void DoneFinalizingLocallyFulfilledIssuance( + base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done, + mojom::TrustTokenOperationStatus status); + // |issuer_| needs to be a nullable type because it is initialized in |Begin|, // but, once initialized, it will never be empty over the course of the // operation's execution. @@ -211,15 +251,33 @@ class TrustTokenRequestIssuanceHelper : public TrustTokenRequestHelper { TrustTokenStore* const token_store_; const TrustTokenKeyCommitmentGetter* const key_commitment_getter_; + mojom::TrustTokenProtocolVersion protocol_version_; + + // Set once we read the issuer's key commitment, + // |should_divert_issuance_request_to_os_| specifies whether, at the time we + // would return from an otherwise successful Begin half of this issuance + // operation, we should pass the issuance request to + // |local_operation_delegate_| rather than returning to the caller. + bool should_divert_issuance_request_to_os_ = false; + // Relinquishes ownership during posted tasks for the potentially // computationally intensive cryptographic operations // (Cryptographer::BeginIssuance, Cryptographer::ConfirmIssuance); repopulated // when regaining ownership upon receiving each operation's results. std::unique_ptr<Cryptographer> cryptographer_; + // |local_operation_delegate_| is responsible for attempting to satisfying + // "platform-provided" issuance operations (e.g. by talking to a system + // service capable of replying to an issuance request). + std::unique_ptr<LocalTrustTokenOperationDelegate> local_operation_delegate_; + + base::RepeatingCallback<bool(mojom::TrustTokenKeyCommitmentResult::Os)> + is_current_os_callback_; + net::NetLogWithSource net_log_; base::WeakPtrFactory<TrustTokenRequestIssuanceHelper> weak_ptr_factory_{this}; }; + } // namespace network #endif // SERVICES_NETWORK_TRUST_TOKENS_TRUST_TOKEN_REQUEST_ISSUANCE_HELPER_H_ diff --git a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc index df04c1c6924..ec7bc8e72be 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc +++ b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc @@ -8,19 +8,24 @@ #include "base/callback.h" #include "base/no_destructor.h" +#include "base/test/bind.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" +#include "build/build_config.h" #include "net/base/load_flags.h" #include "net/base/request_priority.h" #include "net/http/http_response_headers.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_test_util.h" +#include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/trust_token_http_headers.h" #include "services/network/public/cpp/trust_token_parameterization.h" #include "services/network/public/mojom/trust_tokens.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h" +#include "services/network/trust_tokens/operating_system_matching.h" #include "services/network/trust_tokens/proto/public.pb.h" #include "services/network/trust_tokens/test/trust_token_test_util.h" -#include "services/network/trust_tokens/trust_token_http_headers.h" #include "services/network/trust_tokens/trust_token_key_commitment_getter.h" #include "services/network/trust_tokens/trust_token_parameterization.h" #include "services/network/trust_tokens/trust_token_store.h" @@ -35,9 +40,13 @@ namespace { using ::testing::_; using ::testing::ByMove; using ::testing::ElementsAre; +using ::testing::Invoke; using ::testing::Property; using ::testing::Return; using ::testing::ReturnNull; +using ::testing::StrEq; +using ::testing::StrictMock; +using ::testing::WithArgs; using TrustTokenRequestIssuanceHelperTest = TrustTokenRequestHelperTest; using UnblindedTokens = @@ -72,7 +81,9 @@ base::NoDestructor<FixedKeyCommitmentGetter> g_fixed_key_commitment_getter{}; class MockCryptographer : public TrustTokenRequestIssuanceHelper::Cryptographer { public: - MOCK_METHOD1(Initialize, bool(int issuer_configured_batch_size)); + MOCK_METHOD2(Initialize, + bool(mojom::TrustTokenProtocolVersion issuer_configured_version, + int issuer_configured_batch_size)); MOCK_METHOD1(AddKey, bool(base::StringPiece key)); MOCK_METHOD1(BeginIssuance, base::Optional<std::string>(size_t num_tokens)); MOCK_METHOD1( @@ -80,6 +91,38 @@ class MockCryptographer std::unique_ptr<UnblindedTokens>(base::StringPiece response_header)); }; +// MockLocalOperationDelegate mocks out executing a Trust Tokens operation +// mediated by the OS. +class MockLocalOperationDelegate : public LocalTrustTokenOperationDelegate { + public: + MOCK_METHOD2( + FulfillIssuance, + void(mojom::FulfillTrustTokenIssuanceRequestPtr request, + base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)> + done)); +}; + +// Returns a key commitment result with reasonable values for all parameters. +mojom::TrustTokenKeyCommitmentResultPtr ReasonableKeyCommitmentResult() { + auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); + key_commitment_result->keys.push_back(mojom::TrustTokenVerificationKey::New( + "key", /*expiry=*/base::Time::Max())); + key_commitment_result->batch_size = + static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + key_commitment_result->id = 1; + return key_commitment_result; +} + +FixedKeyCommitmentGetter* ReasonableKeyCommitmentGetter() { + static base::NoDestructor<FixedKeyCommitmentGetter> + reasonable_key_commitment_getter{ + *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")), + ReasonableKeyCommitmentResult()}; + return reasonable_key_commitment_getter.get(); +} + } // namespace // Check that issuance fails if it would result in too many issuers being @@ -101,9 +144,11 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, RejectsIfTooManyIssuers) { toplevel)); } - TrustTokenRequestIssuanceHelper helper(toplevel, store.get(), - g_fixed_key_commitment_getter.get(), - std::make_unique<MockCryptographer>()); + TrustTokenRequestIssuanceHelper helper( + toplevel, store.get(), g_fixed_key_commitment_getter.get(), + std::make_unique<MockCryptographer>(), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -127,7 +172,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, RejectsIfAtCapacity) { TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), g_fixed_key_commitment_getter.get(), - std::make_unique<MockCryptographer>()); + std::make_unique<MockCryptographer>(), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -147,7 +194,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, RejectsIfKeyCommitmentFails) { auto getter = std::make_unique<FixedKeyCommitmentGetter>(issuer, nullptr); TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::make_unique<MockCryptographer>()); + store.get(), getter.get(), std::make_unique<MockCryptographer>(), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator( @@ -165,20 +214,14 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, SuitableTrustTokenOrigin issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); - auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - key_commitment_result->keys.push_back( - mojom::TrustTokenVerificationKey::New()); - key_commitment_result->batch_size = - static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); - auto getter = std::make_unique<FixedKeyCommitmentGetter>( - issuer, std::move(key_commitment_result)); - auto cryptographer = std::make_unique<MockCryptographer>(); - EXPECT_CALL(*cryptographer, Initialize(_)).WillOnce(Return(false)); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(false)); TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::move(cryptographer)); + store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -194,21 +237,15 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, RejectsIfAddingKeyFails) { SuitableTrustTokenOrigin issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); - auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - key_commitment_result->keys.push_back( - mojom::TrustTokenVerificationKey::New()); - key_commitment_result->batch_size = - static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); - auto getter = std::make_unique<FixedKeyCommitmentGetter>( - issuer, std::move(key_commitment_result)); - auto cryptographer = std::make_unique<MockCryptographer>(); - EXPECT_CALL(*cryptographer, Initialize(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(false)); TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::move(cryptographer)); + store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -225,16 +262,8 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, SuitableTrustTokenOrigin issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); - auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - key_commitment_result->keys.push_back( - mojom::TrustTokenVerificationKey::New()); - key_commitment_result->batch_size = - static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); - auto getter = std::make_unique<FixedKeyCommitmentGetter>( - issuer, std::move(key_commitment_result)); - auto cryptographer = std::make_unique<MockCryptographer>(); - EXPECT_CALL(*cryptographer, Initialize(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); // Return nullopt, denoting an error, when the issuance helper requests // blinded, unsigned tokens. @@ -242,7 +271,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::move(cryptographer)); + store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -254,26 +285,18 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, mojom::TrustTokenOperationStatus::kInternalError); } -// Check that the issuance helper sets the Sec-Trust-Token header on the -// outgoing request. -TEST_F(TrustTokenRequestIssuanceHelperTest, SetsRequestHeader) { +// Check that the issuance helper sets the Sec-Trust-Token and +// Sec-Trust-Token-Version headers on the outgoing request. +TEST_F(TrustTokenRequestIssuanceHelperTest, SetsRequestHeaders) { std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting(); SuitableTrustTokenOrigin issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); - auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - key_commitment_result->keys.push_back( - mojom::TrustTokenVerificationKey::New()); - key_commitment_result->batch_size = - static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); - auto getter = std::make_unique<FixedKeyCommitmentGetter>( - issuer, std::move(key_commitment_result)); - // The result of providing blinded, unsigned tokens should be the exact value // of the Sec-Trust-Token header attached to the request. auto cryptographer = std::make_unique<MockCryptographer>(); - EXPECT_CALL(*cryptographer, Initialize(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, BeginIssuance(_)) .WillOnce( @@ -281,7 +304,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, SetsRequestHeader) { TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::move(cryptographer)); + store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -293,6 +318,11 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, SetsRequestHeader) { EXPECT_TRUE(request->extra_request_headers().GetHeader( kTrustTokensSecTrustTokenHeader, &attached_header)); EXPECT_EQ(attached_header, "this string contains some blinded tokens"); + + std::string attached_version_header; + EXPECT_TRUE(request->extra_request_headers().GetHeader( + kTrustTokensSecTrustTokenVersionHeader, &attached_version_header)); + EXPECT_EQ(attached_version_header, "TrustTokenV2PMB"); } // Check that the issuance helper sets the LOAD_BYPASS_CACHE flag on the @@ -303,18 +333,10 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, SetsLoadFlag) { SuitableTrustTokenOrigin issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); - auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - key_commitment_result->keys.push_back( - mojom::TrustTokenVerificationKey::New()); - key_commitment_result->batch_size = - static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); - auto getter = std::make_unique<FixedKeyCommitmentGetter>( - issuer, std::move(key_commitment_result)); - // The result of providing blinded, unsigned tokens should be the exact value // of the Sec-Trust-Token header attached to the request. auto cryptographer = std::make_unique<MockCryptographer>(); - EXPECT_CALL(*cryptographer, Initialize(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, BeginIssuance(_)) .WillOnce( @@ -322,7 +344,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, SetsLoadFlag) { TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::move(cryptographer)); + store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -340,16 +364,8 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, RejectsIfResponseOmitsHeader) { SuitableTrustTokenOrigin issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); - auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - key_commitment_result->keys.push_back( - mojom::TrustTokenVerificationKey::New()); - key_commitment_result->batch_size = - static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); - auto getter = std::make_unique<FixedKeyCommitmentGetter>( - issuer, std::move(key_commitment_result)); - auto cryptographer = std::make_unique<MockCryptographer>(); - EXPECT_CALL(*cryptographer, Initialize(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, BeginIssuance(_)) .WillOnce( @@ -357,7 +373,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, RejectsIfResponseOmitsHeader) { TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::move(cryptographer)); + store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -380,16 +398,8 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, RejectsIfResponseIsUnusable) { SuitableTrustTokenOrigin issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); - auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - key_commitment_result->keys.push_back( - mojom::TrustTokenVerificationKey::New()); - key_commitment_result->batch_size = - static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); - auto getter = std::make_unique<FixedKeyCommitmentGetter>( - issuer, std::move(key_commitment_result)); - auto cryptographer = std::make_unique<MockCryptographer>(); - EXPECT_CALL(*cryptographer, Initialize(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, BeginIssuance(_)) .WillOnce( @@ -400,7 +410,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, RejectsIfResponseIsUnusable) { TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::move(cryptographer)); + store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -431,16 +443,8 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, Success) { SuitableTrustTokenOrigin issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); - auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - key_commitment_result->keys.push_back( - mojom::TrustTokenVerificationKey::New()); - key_commitment_result->batch_size = - static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); - auto getter = std::make_unique<FixedKeyCommitmentGetter>( - issuer, std::move(key_commitment_result)); - auto cryptographer = std::make_unique<MockCryptographer>(); - EXPECT_CALL(*cryptographer, Initialize(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, BeginIssuance(_)) .WillOnce( @@ -450,7 +454,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, Success) { TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::move(cryptographer)); + store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -481,16 +487,8 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, AssociatesIssuerWithToplevel) { SuitableTrustTokenOrigin issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); - auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - key_commitment_result->keys.push_back( - mojom::TrustTokenVerificationKey::New()); - key_commitment_result->batch_size = - static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); - auto getter = std::make_unique<FixedKeyCommitmentGetter>( - issuer, std::move(key_commitment_result)); - auto cryptographer = std::make_unique<MockCryptographer>(); - EXPECT_CALL(*cryptographer, Initialize(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, BeginIssuance(_)) .WillOnce( @@ -498,7 +496,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, AssociatesIssuerWithToplevel) { TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::move(cryptographer)); + store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -520,23 +520,16 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, StoresObtainedTokens) { SuitableTrustTokenOrigin issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); - auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - key_commitment_result->keys.push_back( - mojom::TrustTokenVerificationKey::New("key", /*expiry=*/base::Time())); - key_commitment_result->batch_size = - static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); - auto getter = std::make_unique<FixedKeyCommitmentGetter>( - issuer, std::move(key_commitment_result)); - // Have the Trust Tokens issuance conclude by the underlying cryptographic // library returning one signed, unblinded token associated with the same // returned from the key commitment. auto unblinded_tokens = std::make_unique<UnblindedTokens>(); - unblinded_tokens->body_of_verifying_key = "key"; + unblinded_tokens->body_of_verifying_key = + ReasonableKeyCommitmentResult()->keys.front()->body; unblinded_tokens->tokens.push_back("a signed, unblinded token"); auto cryptographer = std::make_unique<MockCryptographer>(); - EXPECT_CALL(*cryptographer, Initialize(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, BeginIssuance(_)) .WillOnce( @@ -546,7 +539,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, StoresObtainedTokens) { TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::move(cryptographer)); + store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); @@ -578,7 +573,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, RejectsUnsuitableInsecureIssuer) { TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), g_fixed_key_commitment_getter.get(), - std::make_unique<MockCryptographer>()); + std::make_unique<MockCryptographer>(), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("http://insecure-issuer.com/"); @@ -592,7 +589,9 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), g_fixed_key_commitment_getter.get(), - std::make_unique<MockCryptographer>()); + std::make_unique<MockCryptographer>(), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); auto request = MakeURLRequest("file:///non-https-issuer.txt"); @@ -606,16 +605,8 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, RespectsMaximumBatchsize) { SuitableTrustTokenOrigin issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); - auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); - key_commitment_result->keys.push_back( - mojom::TrustTokenVerificationKey::New("key", /*expiry=*/base::Time())); - key_commitment_result->batch_size = - static_cast<int>(kMaximumTrustTokenIssuanceBatchSize + 1); - auto getter = std::make_unique<FixedKeyCommitmentGetter>( - issuer, std::move(key_commitment_result)); - auto cryptographer = std::make_unique<MockCryptographer>(); - EXPECT_CALL(*cryptographer, Initialize(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); // The batch size should be clamped to the configured maximum. @@ -626,13 +617,308 @@ TEST_F(TrustTokenRequestIssuanceHelperTest, RespectsMaximumBatchsize) { TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), std::move(cryptographer)); + store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem)); + + auto request = MakeURLRequest("https://issuer.com/"); + request->set_initiator(issuer); + + ASSERT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()), + mojom::TrustTokenOperationStatus::kOk); +} + +class TrustTokenRequestIssuanceHelperTestWithPlatformIssuance + : public TrustTokenRequestIssuanceHelperTest { + public: + TrustTokenRequestIssuanceHelperTestWithPlatformIssuance() { + // This assertion helps safeguard against the brittleness of deserializing + // "true". + static_assert( + std::is_same<decltype(features::kPlatformProvidedTrustTokenIssuance + .default_value), + const bool>::value, + "Need to update this initializaiton logic if the type of the param " + "changes."); + features_.InitAndEnableFeatureWithParameters( + features::kTrustTokens, + {{features::kPlatformProvidedTrustTokenIssuance.name, "true"}}); + } + + private: + base::test::ScopedFeatureList features_; +}; + +TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance, + DiversionToOsSuccess) { + // When an operation's diverted to the operating system and succeeds, we + // should report kOperationSuccessfullyFulfilledLocally. + std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting(); + + SuitableTrustTokenOrigin issuer = + *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); + + auto key_commitment_result = ReasonableKeyCommitmentResult(); + key_commitment_result->request_issuance_locally_on.push_back( + mojom::TrustTokenKeyCommitmentResult::Os::kAndroid); + key_commitment_result->unavailable_local_issuance_fallback = + mojom::TrustTokenKeyCommitmentResult::UnavailableLocalIssuanceFallback:: + kReturnWithError; + auto getter = std::make_unique<FixedKeyCommitmentGetter>( + issuer, std::move(key_commitment_result)); + + // Have the Trust Tokens issuance conclude by the underlying cryptographic + // library returning one signed, unblinded token associated with the same + // returned from the key commitment. + auto unblinded_tokens = std::make_unique<UnblindedTokens>(); + unblinded_tokens->body_of_verifying_key = + ReasonableKeyCommitmentResult()->keys.front()->body; + unblinded_tokens->tokens.push_back("a signed, unblinded token"); + + auto cryptographer = std::make_unique<MockCryptographer>(); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, BeginIssuance(_)) + .WillOnce( + Return(std::string("this string contains some blinded tokens"))); + EXPECT_CALL(*cryptographer, ConfirmIssuance(StrEq("response from issuer"))) + .WillOnce(Return(ByMove(std::move((unblinded_tokens))))); + + auto local_operation_delegate = + std::make_unique<MockLocalOperationDelegate>(); + auto answer = mojom::FulfillTrustTokenIssuanceAnswer::New(); + answer->status = mojom::FulfillTrustTokenIssuanceAnswer::Status::kOk; + answer->response = "response from issuer"; + auto receive_answer = + [&answer]( + base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)> + callback) { std::move(callback).Run(std::move(answer)); }; + EXPECT_CALL(*local_operation_delegate, FulfillIssuance(_, _)) + .WillOnce(WithArgs<1>(Invoke(receive_answer))); + + TrustTokenRequestIssuanceHelper helper( + *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), + store.get(), getter.get(), std::move(cryptographer), + std::move(local_operation_delegate), + base::BindRepeating([](mojom::TrustTokenKeyCommitmentResult::Os os) { + return os == mojom::TrustTokenKeyCommitmentResult::Os::kAndroid; + })); + + auto request = MakeURLRequest("https://issuer.com/"); + request->set_initiator(issuer); + + ASSERT_EQ( + ExecuteBeginOperationAndWaitForResult(&helper, request.get()), + mojom::TrustTokenOperationStatus::kOperationSuccessfullyFulfilledLocally); + + // After the operation has successfully finished, the trust tokens parsed from + // the server response should be in the store. + auto match_all_keys = + base::BindRepeating([](const std::string&) { return true; }); + EXPECT_THAT( + store->RetrieveMatchingTokens(issuer, std::move(match_all_keys)), + ElementsAre(Property(&TrustToken::body, "a signed, unblinded token"))); +} + +TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance, + ErrorDivertingToOs) { + // When an operation's diverted to the operating system and fails because the + // operation can't be executed in the current environment, but *not* because + // we're on the wrong OS, we should report kUnavailable (no matter the + // issuer's configured fallback). + std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting(); + + SuitableTrustTokenOrigin issuer = + *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); + + auto key_commitment_result = ReasonableKeyCommitmentResult(); + key_commitment_result->request_issuance_locally_on.push_back( + mojom::TrustTokenKeyCommitmentResult::Os::kAndroid); + key_commitment_result->unavailable_local_issuance_fallback = + mojom::TrustTokenKeyCommitmentResult::UnavailableLocalIssuanceFallback:: + kWebIssuance; + auto getter = std::make_unique<FixedKeyCommitmentGetter>( + issuer, std::move(key_commitment_result)); + + auto cryptographer = std::make_unique<MockCryptographer>(); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, BeginIssuance(_)) + .WillOnce( + Return(std::string("this string contains some blinded tokens"))); + + // Respond to the local issuance request with kNotFound, indicating that there + // was no way to execute the operation locally: + auto local_operation_delegate = + std::make_unique<MockLocalOperationDelegate>(); + auto answer = mojom::FulfillTrustTokenIssuanceAnswer::New(); + answer->status = mojom::FulfillTrustTokenIssuanceAnswer::Status::kNotFound; + auto receive_answer = + [&answer]( + base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)> + callback) { std::move(callback).Run(std::move(answer)); }; + EXPECT_CALL(*local_operation_delegate, FulfillIssuance(_, _)) + .WillOnce(WithArgs<1>(Invoke(receive_answer))); + + TrustTokenRequestIssuanceHelper helper( + *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), + store.get(), getter.get(), std::move(cryptographer), + std::move(local_operation_delegate), + base::BindRepeating([](mojom::TrustTokenKeyCommitmentResult::Os os) { + return os == mojom::TrustTokenKeyCommitmentResult::Os::kAndroid; + })); auto request = MakeURLRequest("https://issuer.com/"); request->set_initiator(issuer); ASSERT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()), + mojom::TrustTokenOperationStatus::kUnavailable); +} + +TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance, + DiversionToOsWrongOsWithFallbackConfiguredToReturnWithError) { + // When an operation can't be diverted to the operating system because the + // current platform wasn't among those specified by the issuer for local + // execution, and the issuer specified a fallback behavior of + // "return_with_error" in its key commitment, we should return kUnavailable. + std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting(); + + SuitableTrustTokenOrigin issuer = + *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); + + auto key_commitment_result = ReasonableKeyCommitmentResult(); + key_commitment_result->request_issuance_locally_on.push_back( + mojom::TrustTokenKeyCommitmentResult::Os::kAndroid); + key_commitment_result->unavailable_local_issuance_fallback = + mojom::TrustTokenKeyCommitmentResult::UnavailableLocalIssuanceFallback:: + kReturnWithError; + auto getter = std::make_unique<FixedKeyCommitmentGetter>( + issuer, std::move(key_commitment_result)); + + TrustTokenRequestIssuanceHelper helper( + *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), + store.get(), getter.get(), std::make_unique<MockCryptographer>(), + std::make_unique<MockLocalOperationDelegate>(), + // Fail to match to the current OS... + base::BindLambdaForTesting( + [](mojom::TrustTokenKeyCommitmentResult::Os) { return false; })); + + auto request = MakeURLRequest("https://issuer.com/"); + request->set_initiator(issuer); + + // ... and the operation should fail. + ASSERT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()), + mojom::TrustTokenOperationStatus::kUnavailable); +} + +TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance, + DiversionToOsWrongOsWithFallbackConfiguredToRequestWebIssuance) { + // When an operation can't be diverted to the operating system because the + // current platform wasn't among those specified by the issuer for local + // execution, and the issuer specified a fallback behavior of + // "web_issuance" in its key commitment, we should attempt a web issuance. + std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting(); + + SuitableTrustTokenOrigin issuer = + *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); + + auto key_commitment_result = ReasonableKeyCommitmentResult(); + key_commitment_result->request_issuance_locally_on.push_back( + mojom::TrustTokenKeyCommitmentResult::Os::kAndroid); + key_commitment_result->unavailable_local_issuance_fallback = + mojom::TrustTokenKeyCommitmentResult::UnavailableLocalIssuanceFallback:: + kWebIssuance; + auto getter = std::make_unique<FixedKeyCommitmentGetter>( + issuer, std::move(key_commitment_result)); + + auto cryptographer = std::make_unique<MockCryptographer>(); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, BeginIssuance(_)) + .WillOnce( + Return(std::string("this string contains some blinded tokens"))); + + TrustTokenRequestIssuanceHelper helper( + *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), + store.get(), getter.get(), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + // Fail to match to the current OS... + base::BindLambdaForTesting( + [](mojom::TrustTokenKeyCommitmentResult::Os) { return false; })); + + auto request = MakeURLRequest("https://issuer.com/"); + request->set_initiator(issuer); + + // ... and the helper should finish beginning a standard Web issuance, because + // the issuer configured a fallback of |kWebIssuance|. + ASSERT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()), mojom::TrustTokenOperationStatus::kOk); } +TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance, + DivertsToAndroidOnAndroid) { + // Test that, when an issuer specifies that we should attempt issuance locally + // on Android, we do so. + std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting(); + + SuitableTrustTokenOrigin issuer = + *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); + + auto key_commitment_result = ReasonableKeyCommitmentResult(); + // Specify that we should request issuance locally on Android... + key_commitment_result->request_issuance_locally_on.push_back( + mojom::TrustTokenKeyCommitmentResult::Os::kAndroid); + key_commitment_result->unavailable_local_issuance_fallback = + mojom::TrustTokenKeyCommitmentResult::UnavailableLocalIssuanceFallback:: + kReturnWithError; + + auto getter = std::make_unique<FixedKeyCommitmentGetter>( + issuer, std::move(key_commitment_result)); + + auto cryptographer = std::make_unique<MockCryptographer>(); + + // Use a strict mock to make the test fail if the delegate gets called on + // non-Android platforms: + auto local_operation_delegate = + std::make_unique<StrictMock<MockLocalOperationDelegate>>(); +#if defined(OS_ANDROID) + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, BeginIssuance(_)) + .WillOnce( + Return(std::string("this string contains some blinded tokens"))); + + // If we're on Android, respond to the local issuance request with an error. + auto answer = mojom::FulfillTrustTokenIssuanceAnswer::New(); + answer->status = + mojom::FulfillTrustTokenIssuanceAnswer::Status::kUnknownError; + auto receive_answer = + [&answer]( + base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)> + callback) { std::move(callback).Run(std::move(answer)); }; + EXPECT_CALL(*local_operation_delegate, FulfillIssuance(_, _)) + .WillOnce(WithArgs<1>(Invoke(receive_answer))); +#endif // defined(OS_ANDROID) + + TrustTokenRequestIssuanceHelper helper( + *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), + store.get(), getter.get(), std::move(cryptographer), + std::move(local_operation_delegate), + base::BindRepeating(&IsCurrentOperatingSystem)); + + auto request = MakeURLRequest("https://issuer.com/"); + request->set_initiator(issuer); + + // If we're on Android, we should observe the error returned by the delegate; + // if we're not on Android, we should observe error saying we couldn't execute + // issuance locally. + ASSERT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()), +#if defined(OS_ANDROID) + mojom::TrustTokenOperationStatus::kUnknownError +#else + mojom::TrustTokenOperationStatus::kUnavailable +#endif // defined(OS_ANDROID) + ); +} + } // namespace network diff --git a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.cc b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.cc index db260dd5887..b479fdcbc3b 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.cc +++ b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.cc @@ -13,10 +13,10 @@ #include "net/http/http_response_headers.h" #include "net/url_request/url_request.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" +#include "services/network/public/cpp/trust_token_http_headers.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "services/network/trust_tokens/proto/public.pb.h" #include "services/network/trust_tokens/trust_token_database_owner.h" -#include "services/network/trust_tokens/trust_token_http_headers.h" #include "services/network/trust_tokens/trust_token_parameterization.h" #include "services/network/trust_tokens/trust_token_store.h" #include "url/url_constants.h" @@ -101,7 +101,7 @@ void TrustTokenRequestRedemptionHelper::Begin( if (refresh_policy_ == mojom::TrustTokenRefreshPolicy::kUseCached && token_store_->RetrieveNonstaleRedemptionRecord(*issuer_, top_level_origin_)) { - LogOutcome(net_log_, kBegin, "Signed redemption record cache hit"); + LogOutcome(net_log_, kBegin, "Redemption record cache hit"); std::move(done).Run(mojom::TrustTokenOperationStatus::kAlreadyExists); return; } @@ -134,20 +134,18 @@ void TrustTokenRequestRedemptionHelper::OnGotKeyCommitment( } if (!commitment_result->batch_size || - !cryptographer_->Initialize( - commitment_result->batch_size, - commitment_result->signed_redemption_record_verification_key)) { + !cryptographer_->Initialize(commitment_result->protocol_version, + commitment_result->batch_size)) { LogOutcome(net_log_, kBegin, "Internal error initializing BoringSSL redemption state " - "(possibly due to malformed SRR key or bad batch size)"); + "(possibly due to bad batch size)"); std::move(done).Run(mojom::TrustTokenOperationStatus::kInternalError); return; } if (!key_pair_generator_->Generate(&bound_signing_key_, &bound_verification_key_)) { - LogOutcome(net_log_, kBegin, - "Internal error generating SRR-bound key pair"); + LogOutcome(net_log_, kBegin, "Internal error generating RR-bound key pair"); std::move(done).Run(mojom::TrustTokenOperationStatus::kInternalError); return; } @@ -166,6 +164,12 @@ void TrustTokenRequestRedemptionHelper::OnGotKeyCommitment( std::move(*maybe_redemption_header), /*overwrite=*/true); + std::string protocol_string_version = + internal::ProtocolVersionToString(commitment_result->protocol_version); + request->SetExtraRequestHeaderByName(kTrustTokensSecTrustTokenVersionHeader, + protocol_string_version, + /*overwrite=*/true); + // We don't want cache reads, because the highest priority is to execute the // protocol operation by sending the server the Trust Tokens request header // and getting the corresponding response header, but we want cache writes @@ -208,27 +212,26 @@ void TrustTokenRequestRedemptionHelper::Finalize( } // 2. Strip the Sec-Trust-Token header, from the response and pass the header, - // base64-decoded, to BoringSSL, along with the issuer’s SRR-verification - // public key previously obtained from a key commitment. + // base64-decoded, to BoringSSL. response->headers->RemoveHeader(kTrustTokensSecTrustTokenHeader); - base::Optional<std::string> maybe_signed_redemption_record = + base::Optional<std::string> maybe_redemption_record = cryptographer_->ConfirmRedemption(header_value); // 3. If BoringSSL fails its structural validation / signature check, return // an error. - if (!maybe_signed_redemption_record) { + if (!maybe_redemption_record) { // The response was rejected by the underlying cryptographic library as // malformed or otherwise invalid. - LogOutcome(net_log_, kFinalize, "SRR validation failed"); + LogOutcome(net_log_, kFinalize, "RR validation failed"); std::move(done).Run(mojom::TrustTokenOperationStatus::kBadResponse); return; } - // 4. Otherwise, if these checks succeed, store the SRR and return success. + // 4. Otherwise, if these checks succeed, store the RR and return success. - SignedTrustTokenRedemptionRecord record_to_store; - record_to_store.set_body(std::move(*maybe_signed_redemption_record)); + TrustTokenRedemptionRecord record_to_store; + record_to_store.set_body(std::move(*maybe_redemption_record)); record_to_store.set_signing_key(std::move(bound_signing_key_)); record_to_store.set_public_key(std::move(bound_verification_key_)); record_to_store.set_token_verification_key( diff --git a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.h b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.h index 11a53657123..c37e2e087fb 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.h +++ b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.h @@ -34,18 +34,18 @@ class URLResponseHead; // Class TrustTokenRequestRedemptionHelper performs a single trust token // redemption operation (https://github.com/wicg/trust-token-api): it attaches a // single signed, unblinded token to an outgoing request, hands it to the -// token's issuer, and expects a signed redemption record (SRR) in response. The -// normal case involves a total of two network requests: one to get an -// up-to-date view of a key set the issuer provides for verifying that it's safe -// to perform the redemption, and another to send the token to the issuer. +// token's issuer, and expects a redemption record (RR) in response. The normal +// case involves a total of two network requests: one to get an up-to-date view +// of a key set the issuer provides for verifying that it's safe to perform the +// redemption, and another to send the token to the issuer. class TrustTokenRequestRedemptionHelper : public TrustTokenRequestHelper { public: // Class KeyPairGenerator generates a signing and verification key pair. // These are not used for any cryptographic operations during redemption // itself. Instead, a digest of the verification key goes into the redemption // request and, on redemption success, we store the key pair alongside the - // Signed Redemption Record obtained from the server; the key pair can - // subsequently be used to sign outgoing requests as part of the Trust Tokens + // Redemption Record obtained from the server; the key pair can subsequently + // be used to sign outgoing requests as part of the Trust Tokens // "request signing" operation. class KeyPairGenerator { public: @@ -68,16 +68,16 @@ class TrustTokenRequestRedemptionHelper : public TrustTokenRequestHelper { public: virtual ~Cryptographer() = default; - // Initializes the delegate. |issuer_configured_batch_size| must be the - // "batchsize" value, and |signed_Redemption_record_verification_key| the - // "srrkey" value, from an issuer-provided key commitment result. + // Initializes the delegate. |issuer_configured_version| and + // |issuer_configured_batch_size| must be the "protocol_version" and + // "batchsize" values, from an issuer-provided key commitment result. // // Returns true on success and false if the batch size or key is // unacceptable or an internal error occurred in the underlying // cryptographic library. virtual bool Initialize( - int issuer_configured_batch_size, - base::StringPiece signed_redemption_record_verification_key) = 0; + mojom::TrustTokenProtocolVersion issuer_configured_version, + int issuer_configured_batch_size) = 0; // Given a trust token to redeem and parameters to encode in the redemption // request, returns a base64-encoded string suitable for attachment in the @@ -95,11 +95,11 @@ class TrustTokenRequestRedemptionHelper : public TrustTokenRequestHelper { const url::Origin& top_level_origin) = 0; // Given a base64-encoded Sec-Trust-Token redemption response header, - // validates and extracts the signed redemption record (SRR) contained in - // the header. If successful, returns the SRR. Otherwise, returns nullopt. + // validates and extracts the redemption record (RR) contained in the + // header. If successful, returns the RR. Otherwise, returns nullopt. // // The Trust Tokens design doc is currently the normative source for the - // SRR's format. + // RR's format. virtual base::Optional<std::string> ConfirmRedemption( base::StringPiece response_header) = 0; }; @@ -115,7 +115,7 @@ class TrustTokenRequestRedemptionHelper : public TrustTokenRequestHelper { // 2. potentially trustworthy origin to satisfy Web security requirements. // // - |refresh_policy| controls whether to attempt to overwrite the cached - // SRR stored for the request's (issuer, top-level) origin pair. This is + // RR stored for the request's (issuer, top-level) origin pair. This is // permitted to have value |kRefresh| only when the redemption // request's initiator equals its issuer origin. // @@ -149,7 +149,7 @@ class TrustTokenRequestRedemptionHelper : public TrustTokenRequestHelper { // object's constructor has already reached its number-of-issuers limit, // or if the (issuer, top-level) pair has no tokens to redeem // * kAlreadyExists if the (issuer, top-level) pair already has a current - // SRR and this helper was not parameterized with |kRefresh|. + // RR and this helper was not parameterized with |kRefresh|. // * kFailedPrecondition if preconditions fail, including receiving a // malformed or otherwise invalid key commitment record from the issuer, // or if |kRefresh| was provided and the request was not initiated @@ -207,7 +207,7 @@ class TrustTokenRequestRedemptionHelper : public TrustTokenRequestHelper { // |token_verification_key_| is the token issuance verification key // corresponding to the token being redeemed. It's stored here speculatively // when beginning redemption so that it can be placed in persistent storage - // alongside the SRR if redemption succeeds. + // alongside the RR if redemption succeeds. std::string token_verification_key_; TrustTokenStore* const token_store_; diff --git a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc index 88888c91ea7..4b4008531ba 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc +++ b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc @@ -15,11 +15,11 @@ #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_test_util.h" +#include "services/network/public/cpp/trust_token_http_headers.h" #include "services/network/public/cpp/trust_token_parameterization.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "services/network/trust_tokens/proto/public.pb.h" #include "services/network/trust_tokens/test/trust_token_test_util.h" -#include "services/network/trust_tokens/trust_token_http_headers.h" #include "services/network/trust_tokens/trust_token_key_commitment_getter.h" #include "services/network/trust_tokens/trust_token_parameterization.h" #include "services/network/trust_tokens/trust_token_store.h" @@ -65,10 +65,9 @@ base::NoDestructor<FixedKeyCommitmentGetter> g_fixed_key_commitment_getter{}; class MockCryptographer : public TrustTokenRequestRedemptionHelper::Cryptographer { public: - MOCK_METHOD2( - Initialize, - bool(int issuer_configured_batch_size, - base::StringPiece signed_redemption_record_verification_key)); + MOCK_METHOD2(Initialize, + bool(mojom::TrustTokenProtocolVersion issuer_configured_version, + int issuer_configured_batch_size)); MOCK_METHOD3( BeginRedemption, @@ -219,6 +218,9 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); key_commitment_result->keys.push_back( mojom::TrustTokenVerificationKey::New()); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + key_commitment_result->id = 1; key_commitment_result->batch_size = static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); auto getter = std::make_unique<FixedKeyCommitmentGetter>( @@ -264,6 +266,9 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); key_commitment_result->keys.push_back( mojom::TrustTokenVerificationKey::New()); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + key_commitment_result->id = 1; key_commitment_result->batch_size = static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); auto getter = std::make_unique<FixedKeyCommitmentGetter>( @@ -310,6 +315,9 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, RejectsIfKeyPairGenerationFails) { auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); key_commitment_result->keys.push_back( mojom::TrustTokenVerificationKey::New()); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + key_commitment_result->id = 1; key_commitment_result->batch_size = static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); auto getter = std::make_unique<FixedKeyCommitmentGetter>( @@ -359,6 +367,9 @@ class TrustTokenBeginRedemptionPostconditionsTest auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); key_commitment_result->keys.push_back( mojom::TrustTokenVerificationKey::New()); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + key_commitment_result->id = 1; key_commitment_result->batch_size = static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); auto getter = std::make_unique<FixedKeyCommitmentGetter>( @@ -394,12 +405,14 @@ class TrustTokenBeginRedemptionPostconditionsTest } // namespace -// Check that the redemption helper sets the Sec-Trust-Token header on the -// outgoing request. -TEST_F(TrustTokenBeginRedemptionPostconditionsTest, SetsHeader) { +// Check that the redemption helper sets the Sec-Trust-Token and +// Sec-Trust-Token-Version headers on the outgoing request. +TEST_F(TrustTokenBeginRedemptionPostconditionsTest, SetsHeaders) { std::string attached_header; EXPECT_TRUE(request_->extra_request_headers().GetHeader( kTrustTokensSecTrustTokenHeader, &attached_header)); + EXPECT_TRUE(request_->extra_request_headers().GetHeader( + kTrustTokensSecTrustTokenVersionHeader, &attached_header)); } // Check that the redemption helper sets the LOAD_BYPASS_CACHE flag on the @@ -427,6 +440,9 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, RejectsIfResponseOmitsHeader) { auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); key_commitment_result->keys.push_back( mojom::TrustTokenVerificationKey::New()); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + key_commitment_result->id = 1; key_commitment_result->batch_size = static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); auto getter = std::make_unique<FixedKeyCommitmentGetter>( @@ -485,6 +501,9 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, RejectsIfResponseIsUnusable) { auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); key_commitment_result->keys.push_back( mojom::TrustTokenVerificationKey::New()); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + key_commitment_result->id = 1; key_commitment_result->batch_size = static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); auto getter = std::make_unique<FixedKeyCommitmentGetter>( @@ -551,6 +570,9 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, Success) { auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); key_commitment_result->keys.push_back( mojom::TrustTokenVerificationKey::New()); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + key_commitment_result->id = 1; key_commitment_result->batch_size = static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); auto getter = std::make_unique<FixedKeyCommitmentGetter>( @@ -564,7 +586,7 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, Success) { EXPECT_CALL(*cryptographer, BeginRedemption(_, _, _)) .WillOnce(Return("well-formed redemption request")); EXPECT_CALL(*cryptographer, ConfirmRedemption(_)) - .WillOnce(Return("a successfully-extracted SRR")); + .WillOnce(Return("a successfully-extracted RR")); TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), @@ -617,6 +639,9 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, AssociatesIssuerWithToplevel) { auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); key_commitment_result->keys.push_back( mojom::TrustTokenVerificationKey::New()); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + key_commitment_result->id = 1; key_commitment_result->batch_size = static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); auto getter = std::make_unique<FixedKeyCommitmentGetter>( @@ -655,7 +680,7 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, AssociatesIssuerWithToplevel) { } // Check that a successful end-to-end Begin/Finalize flow stores the obtained -// signed redemption record (and associated key pair) in the trust token store. +// redemption record (and associated key pair) in the trust token store. TEST_F(TrustTokenRequestRedemptionHelperTest, StoresObtainedRedemptionRecord) { // Establish the following state: // * One key commitment returned from the key commitment registry, with one @@ -673,6 +698,9 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, StoresObtainedRedemptionRecord) { auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); key_commitment_result->keys.push_back(mojom::TrustTokenVerificationKey::New( "token verification key", /*expiry=*/base::Time::Max())); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + key_commitment_result->id = 1; key_commitment_result->batch_size = static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); auto getter = std::make_unique<FixedKeyCommitmentGetter>( @@ -684,7 +712,7 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, StoresObtainedRedemptionRecord) { EXPECT_CALL(*cryptographer, BeginRedemption(_, _, _)) .WillOnce(Return("well-formed redemption request")); EXPECT_CALL(*cryptographer, ConfirmRedemption(_)) - .WillOnce(Return("a successfully-extracted SRR")); + .WillOnce(Return("a successfully-extracted RR")); TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), @@ -706,21 +734,19 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, StoresObtainedRedemptionRecord) { EXPECT_EQ(ExecuteFinalizeAndWaitForResult(&helper, response_head.get()), mojom::TrustTokenOperationStatus::kOk); - // After the operation has successfully finished, the SRR parsed from the + // After the operation has successfully finished, the RR parsed from the // server response should be in the store. EXPECT_THAT( store->RetrieveNonstaleRedemptionRecord( *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")), *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/"))), Optional(AllOf( - Property(&SignedTrustTokenRedemptionRecord::body, - "a successfully-extracted SRR"), - Property(&SignedTrustTokenRedemptionRecord::public_key, - "verification key"), - Property(&SignedTrustTokenRedemptionRecord::token_verification_key, + Property(&TrustTokenRedemptionRecord::body, + "a successfully-extracted RR"), + Property(&TrustTokenRedemptionRecord::public_key, "verification key"), + Property(&TrustTokenRedemptionRecord::token_verification_key, "token verification key"), - Property(&SignedTrustTokenRedemptionRecord::signing_key, - "signing key")))); + Property(&TrustTokenRedemptionRecord::signing_key, "signing key")))); } // Check that a "refresh" refresh mode is rejected unless the request's @@ -747,7 +773,7 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kFailedPrecondition); } -// On a redemption operation parameterized by kUseCachedSrr, if there's an SRR +// On a redemption operation parameterized by kUseCachedRr, if there's an RR // present in the store for the given issuer-toplevel pair, the request should // return early with kAlreadyExists. TEST_F(TrustTokenRequestRedemptionHelperTest, RedemptionRecordCacheHit) { @@ -755,7 +781,7 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, RedemptionRecordCacheHit) { store->SetRedemptionRecord( *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com")), *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com")), - SignedTrustTokenRedemptionRecord()); + TrustTokenRedemptionRecord()); TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), @@ -774,13 +800,13 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, RedemptionRecordCacheHit) { } // Check that a successful end-to-end Begin/Finalize flow with kRefresh -// overwrites the previously stored signed redemption record (and associated key -// pair) in the trust token store. +// overwrites the previously stored redemption record (and associated key pair) +// in the trust token store. TEST_F(TrustTokenRequestRedemptionHelperTest, - SuccessUsingRefreshSrrOverwritesStoredSrr) { + SuccessUsingRefreshRrOverwritesStoredRr) { // Establish the following state: - // * A signed redemption record is already stored for the issuer, toplevel - // pair at hand. + // * A redemption record is already stored for the issuer, toplevel pair at + // hand. // * One key commitment returned from the key commitment registry, with one // key, with body "". // * One token stored corresponding to the key "" (this will be the token @@ -791,7 +817,7 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, store->SetRedemptionRecord( *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com")), *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com")), - SignedTrustTokenRedemptionRecord()); + TrustTokenRedemptionRecord()); store->AddTokens( *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")), std::vector<std::string>{"a token"}, @@ -800,6 +826,9 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); key_commitment_result->keys.push_back( mojom::TrustTokenVerificationKey::New()); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb; + key_commitment_result->id = 1; key_commitment_result->batch_size = static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); auto getter = std::make_unique<FixedKeyCommitmentGetter>( @@ -811,7 +840,7 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, EXPECT_CALL(*cryptographer, BeginRedemption(_, _, _)) .WillOnce(Return("well-formed redemption request")); EXPECT_CALL(*cryptographer, ConfirmRedemption(_)) - .WillOnce(Return("a successfully-extracted SRR")); + .WillOnce(Return("a successfully-extracted RR")); TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), @@ -839,18 +868,17 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, EXPECT_EQ(ExecuteFinalizeAndWaitForResult(&helper, response_head.get()), mojom::TrustTokenOperationStatus::kOk); - // After the operation has successfully finished, the SRR parsed from the + // After the operation has successfully finished, the RR parsed from the // server response should be in the store. EXPECT_THAT( store->RetrieveNonstaleRedemptionRecord( *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")), *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/"))), - Optional(AllOf(Property(&SignedTrustTokenRedemptionRecord::body, - "a successfully-extracted SRR"), - Property(&SignedTrustTokenRedemptionRecord::public_key, - "verification key"), - Property(&SignedTrustTokenRedemptionRecord::signing_key, - "signing key")))); + Optional(AllOf( + Property(&TrustTokenRedemptionRecord::body, + "a successfully-extracted RR"), + Property(&TrustTokenRedemptionRecord::public_key, "verification key"), + Property(&TrustTokenRedemptionRecord::signing_key, "signing key")))); } TEST_F(TrustTokenRequestRedemptionHelperTest, RejectsUnsuitableInsecureIssuer) { @@ -882,7 +910,7 @@ TEST_F(TrustTokenRequestRedemptionHelperTest, mojom::TrustTokenOperationStatus::kInvalidArgument); } -TEST_F(TrustTokenRequestRedemptionHelperTest, RequiresInitiatorForSrrRefresh) { +TEST_F(TrustTokenRequestRedemptionHelperTest, RequiresInitiatorForRrRefresh) { // Refresh mode "refresh" requires that the request's initiator to // be same-origin with the request's issuer. Test that, in this case, the // redemption helper requires that the request have an initiator. diff --git a/chromium/services/network/trust_tokens/trust_token_request_signing_helper.cc b/chromium/services/network/trust_tokens/trust_token_request_signing_helper.cc index f5d2d7201d7..d63cf40cc92 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_signing_helper.cc +++ b/chromium/services/network/trust_tokens/trust_token_request_signing_helper.cc @@ -11,6 +11,7 @@ #include "base/base64.h" #include "base/containers/flat_set.h" #include "base/optional.h" +#include "base/ranges/algorithm.h" #include "base/stl_util.h" #include "base/strings/strcat.h" #include "base/strings/string_split.h" @@ -22,10 +23,10 @@ #include "net/http/structured_headers.h" #include "net/url_request/url_request.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" +#include "services/network/public/cpp/trust_token_http_headers.h" #include "services/network/public/cpp/trust_token_parameterization.h" #include "services/network/public/mojom/trust_tokens.mojom-shared.h" #include "services/network/trust_tokens/proto/public.pb.h" -#include "services/network/trust_tokens/trust_token_http_headers.h" #include "services/network/trust_tokens/trust_token_request_canonicalizer.h" #include "services/network/trust_tokens/trust_token_store.h" #include "url/url_constants.h" @@ -76,7 +77,7 @@ base::Optional<std::vector<std::string>> ParseTrustTokenSignedHeadersHeader( } // namespace internal const char* const TrustTokenRequestSigningHelper::kSignableRequestHeaders[]{ - kTrustTokensRequestHeaderSecSignedRedemptionRecord, + kTrustTokensRequestHeaderSecRedemptionRecord, kTrustTokensRequestHeaderSecTime, kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData, }; @@ -97,6 +98,7 @@ const char kSignatureHeaderSignRequestDataIncludeValue[] = "include"; const char kSignatureHeaderSignRequestDataHeadersOnlyValue[] = "headers-only"; const char kSignatureHeaderSignaturesKey[] = "signatures"; const char kSignatureHeaderSignRequestDataKey[] = "sign-request-data"; +const char kSignatureHeaderAlgorithmKey[] = "alg"; const char kSignatureHeaderPublicKeyKey[] = "public-key"; const char kSignatureHeaderSignatureKey[] = "sig"; const char kRedemptionRecordHeaderRedemptionRecordKey[] = "redemption-record"; @@ -168,8 +170,8 @@ GetHeadersToSignAndUpdateSignedHeadersHeader( if (deduped_lowercase_headers_to_sign.empty()) return std::vector<std::string>(); - if (!base::STLIncludes(LowercaseSignableHeaders(), - deduped_lowercase_headers_to_sign)) { + if (!base::ranges::includes(LowercaseSignableHeaders(), + deduped_lowercase_headers_to_sign)) { return base::nullopt; } @@ -183,20 +185,18 @@ GetHeadersToSignAndUpdateSignedHeadersHeader( return out; } -void AttachSignedRedemptionRecordHeader(net::URLRequest* request, - std::string value) { +void AttachRedemptionRecordHeader(net::URLRequest* request, std::string value) { request->SetExtraRequestHeaderByName( - kTrustTokensRequestHeaderSecSignedRedemptionRecord, value, + kTrustTokensRequestHeaderSecRedemptionRecord, value, /*overwrite=*/true); } -// Builds a Trust Tokens signed redemption record header, which is logically an -// issuer-to-SRR map but implemented as a Structured Headers Draft 15 +// Builds a Trust Tokens redemption record header, which is logically an +// issuer-to-RR map but implemented as a Structured Headers Draft 15 // parameterized list (essentially a list where each member has an associated // dictionary). -base::Optional<std::string> ConstructSignedRedemptionRecordHeader( - const base::flat_map<SuitableTrustTokenOrigin, - SignedTrustTokenRedemptionRecord>& +base::Optional<std::string> ConstructRedemptionRecordHeader( + const base::flat_map<SuitableTrustTokenOrigin, TrustTokenRedemptionRecord>& records_per_issuer) { net::structured_headers::List header_items; @@ -272,10 +272,10 @@ void TrustTokenRequestSigningHelper::Begin( mojom::TrustTokenOperationStatus result) { const auto& headers = request->extra_request_headers(); - std::string srr_header; - DCHECK(headers.GetHeader( - kTrustTokensRequestHeaderSecSignedRedemptionRecord, &srr_header)); - if (srr_header.empty()) { + std::string rr_header; + DCHECK(headers.GetHeader(kTrustTokensRequestHeaderSecRedemptionRecord, + &rr_header)); + if (rr_header.empty()) { DCHECK(!headers.HasHeader(kTrustTokensRequestHeaderSecTime)); DCHECK(!headers.HasHeader(kTrustTokensRequestHeaderSecSignature)); DCHECK(!headers.HasHeader(kTrustTokensRequestHeaderSignedHeaders)); @@ -288,7 +288,7 @@ void TrustTokenRequestSigningHelper::Begin( // This class is responsible for adding these headers; callers should not add // them. DCHECK(!request->extra_request_headers().HasHeader( - kTrustTokensRequestHeaderSecSignedRedemptionRecord)); + kTrustTokensRequestHeaderSecRedemptionRecord)); DCHECK(!request->extra_request_headers().HasHeader( kTrustTokensRequestHeaderSecTime)); DCHECK(!request->extra_request_headers().HasHeader( @@ -302,13 +302,13 @@ void TrustTokenRequestSigningHelper::Begin( // (Because of the chracteristics of the protocol, this map is expected to // have at most ~5 elements.) - base::flat_map<SuitableTrustTokenOrigin, SignedTrustTokenRedemptionRecord> + base::flat_map<SuitableTrustTokenOrigin, TrustTokenRedemptionRecord> records_per_issuer; - // 1. For each issuer specified, search storage for a non-expired SRR + // 1. For each issuer specified, search storage for a non-expired RR // corresponding to that issuer and the request’s initiating top-level origin. for (const SuitableTrustTokenOrigin& issuer : params_.issuers) { - base::Optional<SignedTrustTokenRedemptionRecord> maybe_redemption_record = + base::Optional<TrustTokenRedemptionRecord> maybe_redemption_record = token_store_->RetrieveNonstaleRedemptionRecord(issuer, params_.toplevel); if (!maybe_redemption_record) @@ -318,10 +318,10 @@ void TrustTokenRequestSigningHelper::Begin( } if (records_per_issuer.empty()) { - AttachSignedRedemptionRecordHeader(request, std::string()); + AttachRedemptionRecordHeader(request, std::string()); LogOutcome(net_log_, - "No SRR for any of the given issuers, in the operation's " + "No RR for any of the given issuers, in the operation's " "top-level context"); std::move(done).Run(mojom::TrustTokenOperationStatus::kOk); return; @@ -336,7 +336,7 @@ void TrustTokenRequestSigningHelper::Begin( kTrustTokenAdditionalSigningDataMaxSizeBytes) { LogOutcome(net_log_, "Overly long additionalSigningData"); - AttachSignedRedemptionRecordHeader(request, std::string()); + AttachRedemptionRecordHeader(request, std::string()); std::move(done).Run(mojom::TrustTokenOperationStatus::kOk); return; } @@ -348,7 +348,7 @@ void TrustTokenRequestSigningHelper::Begin( LogOutcome(net_log_, "additionalSigningData was not a valid HTTP header value"); - AttachSignedRedemptionRecordHeader(request, std::string()); + AttachRedemptionRecordHeader(request, std::string()); std::move(done).Run(mojom::TrustTokenOperationStatus::kOk); return; } @@ -383,7 +383,7 @@ void TrustTokenRequestSigningHelper::Begin( request, params_.additional_headers_to_sign); if (!maybe_headers_to_sign) { - AttachSignedRedemptionRecordHeader(request, std::string()); + AttachRedemptionRecordHeader(request, std::string()); LogOutcome(net_log_, "Unsignable header specified in Signed-Headers " @@ -392,18 +392,17 @@ void TrustTokenRequestSigningHelper::Begin( return; } - // 2.c. Attach the SRRs in a Sec-Signed-Redemption-Record header. - if (base::Optional<std::string> maybe_signed_redemption_record_header = - ConstructSignedRedemptionRecordHeader(records_per_issuer)) { - AttachSignedRedemptionRecordHeader( - request, std::move(*maybe_signed_redemption_record_header)); + // 2.c. Attach the RRs in a Sec-Redemption-Record header. + if (base::Optional<std::string> maybe_redemption_record_header = + ConstructRedemptionRecordHeader(records_per_issuer)) { + AttachRedemptionRecordHeader(request, + std::move(*maybe_redemption_record_header)); } else { - AttachSignedRedemptionRecordHeader(request, std::string()); + AttachRedemptionRecordHeader(request, std::string()); - LogOutcome( - net_log_, - "Unexpected internal error serializing Sec-Signed-Redemption-Record" - " header."); + LogOutcome(net_log_, + "Unexpected internal error serializing Sec-Redemption-Record" + " header."); std::move(done).Run(mojom::TrustTokenOperationStatus::kOk); return; } @@ -463,7 +462,7 @@ void TrustTokenRequestSigningHelper::Begin( std::move(*maybe_signature_header), /*overwrite=*/true); } else { - AttachSignedRedemptionRecordHeader(request, std::string()); + AttachRedemptionRecordHeader(request, std::string()); request->RemoveRequestHeaderByName(kTrustTokensRequestHeaderSecTime); request->RemoveRequestHeaderByName(kTrustTokensRequestHeaderSignedHeaders); @@ -493,7 +492,7 @@ namespace { // nested map, corresponding to a single entry in the Sec-Signature header's // top-level list. net::structured_headers::Parameters ConstructKeyAndSignaturePair( - const SignedTrustTokenRedemptionRecord& redemption_record, + const TrustTokenRedemptionRecord& redemption_record, base::span<const uint8_t> signature_bytes) { net::structured_headers::Item public_key( redemption_record.public_key(), @@ -512,8 +511,7 @@ net::structured_headers::Parameters ConstructKeyAndSignaturePair( base::Optional<std::string> TrustTokenRequestSigningHelper:: BuildSignatureHeaderIfAtLeastOneSignatureIsPresent( const base::flat_map<SuitableTrustTokenOrigin, - SignedTrustTokenRedemptionRecord>& - records_per_issuer, + TrustTokenRedemptionRecord>& records_per_issuer, const base::flat_map<SuitableTrustTokenOrigin, std::vector<uint8_t>>& signatures_per_issuer) { if (signatures_per_issuer.empty()) @@ -521,6 +519,10 @@ base::Optional<std::string> TrustTokenRequestSigningHelper:: net::structured_headers::Dictionary header_items; + header_items[kSignatureHeaderAlgorithmKey] = + net::structured_headers::ParameterizedMember( + net::structured_headers::Item(signer_->GetAlgorithmIdentifier()), {}); + std::vector<net::structured_headers::ParameterizedItem> keys_and_signatures; for (const auto& kv : signatures_per_issuer) { const SuitableTrustTokenOrigin& issuer = kv.first; @@ -571,14 +573,14 @@ base::Optional<std::string> TrustTokenRequestSigningHelper:: base::Optional<std::vector<uint8_t>> TrustTokenRequestSigningHelper::GetSignature( net::URLRequest* request, - const SignedTrustTokenRedemptionRecord& redemption_record, + const TrustTokenRedemptionRecord& redemption_record, const std::vector<std::string>& headers_to_sign) { // (This follows the normative pseudocode, labeled "signature // generation," in the Trust Tokens design doc.) // // 1. Generate a CBOR-encoded dictionary, the canonical request data. - // 2. Sign the concatenation of “Trust Token v0” and the CBOR-encoded - // dictionary. (The domain separator string “Trust Token v0” allows versioning + // 2. Sign the concatenation of the major protocol version and the + // CBOR-encoded dictionary. (The domain separator string allows versioning // otherwise-forward-compatible protocol structures, which is useful in case // the semantics change across versions.) diff --git a/chromium/services/network/trust_tokens/trust_token_request_signing_helper.h b/chromium/services/network/trust_tokens/trust_token_request_signing_helper.h index 16831045bc0..9534352d60b 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_signing_helper.h +++ b/chromium/services/network/trust_tokens/trust_token_request_signing_helper.h @@ -34,18 +34,18 @@ base::Optional<std::vector<std::string>> ParseTrustTokenSignedHeadersHeader( } // namespace internal class TrustTokenStore; -class SignedTrustTokenRedemptionRecord; +class TrustTokenRedemptionRecord; // Class TrustTokenRequestSigningHelper executes a single trust token signing // operation (https://github.com/wicg/trust-token-api): it searches storage for -// a Signed Redemption Record (SRR), attaches the SRR to the request, and, -// depending on how the operation is parameterized, potentially also computes -// and attaches a signature over the SRR, a canonical representation of some -// of the request's data (for instance, a collection of the request's headers), -// and some additional metadata. -// To compute this signature, it uses a signing key associated with the SRR +// a Redemption Record (RR), attaches the RR to the request, and, depending on +// how the operation is parameterized, potentially also computes and attaches a +// signature over the RR, a canonical representation of some of the request's +// data (for instance, a collection of the request's headers), and some +// additional metadata. +// To compute this signature, it uses a signing key associated with the RR // and generated during the previous Trust Tokens redemption operation that -// yielded the SRR. +// yielded the RR. class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper { public: // The list of headers that callers are allowed to specify @@ -69,7 +69,7 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper { // signatures forwards-incompatible, which is useful in case the signing // data's semantics change across protocol versions but its syntax does not. static constexpr uint8_t kRequestSigningDomainSeparator[] = { - 'T', 'r', 'u', 's', 't', ' ', 'T', 'o', 'k', 'e', 'n', ' ', 'v', '0'}; + 'T', 'r', 'u', 's', 't', 'T', 'o', 'k', 'e', 'n', 'V', '2'}; struct Params { // Refer to fields' comments for their semantics. @@ -92,7 +92,7 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper { Params& operator=(Params&&); // |issuers| contains the Trust Tokens issuer origins for which to retrieve - // Signed Redemption Records and matching signing keys. These must be both + // Redemption Records and matching signing keys. These must be both // (1) HTTP or HTTPS and (2) "potentially trustworthy". This precondition is // slightly involved because there are two needs: // 1. HTTP or HTTPS so that the scheme serializes in a sensible manner in @@ -150,6 +150,10 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper { virtual bool Verify(base::span<const uint8_t> data, base::span<const uint8_t> signature, base::span<const uint8_t> verification_key) = 0; + + // Returns the short-form name of the signing algorithm that this Signer + // uses. + virtual std::string GetAlgorithmIdentifier() = 0; }; // Creates a request signing helper with behavior determined by |params|, @@ -173,13 +177,13 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper { TrustTokenRequestSigningHelper& operator=( const TrustTokenRequestSigningHelper&) = delete; - // Attempts to attach Signed Redemption Records (SRRs) corresponding - // to |request|'s initiating top-level origin and the provided issuer origins. + // Attempts to attach Redemption Records (RRs) corresponding to |request|'s + // initiating top-level origin and the provided issuer origins. // // ATTACHING THE REDEMPTION RECORD: - // In the case that an SRR is found for at least one provided issuer and the + // In the case that an RR is found for at least one provided issuer and the // requested headers to sign are well-formed, attaches a - // Sec-Signed-Redemption-Record header bearing the SRRs and: + // Sec-Redemption-Record header bearing the RRs and: // 1. if the request is configured for adding a Trust Tokens timestamp, // adds a timestamp header; // 2. if the request is configured for signing, computes the request's @@ -190,7 +194,7 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper { // 1. The caller specified headers for signing other than those in // kSignableRequestHeaders (or if the request has a malformed or otherwise // invalid signed issuers list in its Signed-Headers header); or - // 2. none of the provided issuers has an SRR corresponding to this top-level + // 2. none of the provided issuers has an RR corresponding to this top-level // origin in |token_store_|; or // 3. an internal error occurs during signing or header serialization. // @@ -199,7 +203,7 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper { // failure during signing; see the Trust Tokens design doc for more // discussion. // - On failure, the request will contain an empty - // Sec-Signed-Redemption-Record header and no Sec-Time, Sec-Signature, or + // Sec-Redemption-Record header and no Sec-Time, Sec-Signature, or // Signed-Headers headers. void Begin( net::URLRequest* request, @@ -226,12 +230,11 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper { // empty. // // REQUIRES: Every issuer in |signatures_per_issuer| must have a corresponding - // signed redemption record in |records_per_issuer|. + // redemption record in |records_per_issuer|. base::Optional<std::string> BuildSignatureHeaderIfAtLeastOneSignatureIsPresent( const base::flat_map<SuitableTrustTokenOrigin, - SignedTrustTokenRedemptionRecord>& - records_per_issuer, + TrustTokenRedemptionRecord>& records_per_issuer, const base::flat_map<SuitableTrustTokenOrigin, std::vector<uint8_t>>& signatures_per_issuer); @@ -240,7 +243,7 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper { // of internal error. base::Optional<std::vector<uint8_t>> GetSignature( net::URLRequest* request, - const SignedTrustTokenRedemptionRecord& record, + const TrustTokenRedemptionRecord& record, const std::vector<std::string>& headers_to_sign); TrustTokenStore* token_store_; diff --git a/chromium/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc b/chromium/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc index aac5becb29b..3edc716a564 100644 --- a/chromium/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc +++ b/chromium/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc @@ -16,7 +16,7 @@ #include "base/ranges/algorithm.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/time/time_to_iso8601.h" #include "components/cbor/reader.h" @@ -69,6 +69,8 @@ class FakeSigner : public TrustTokenRequestSigningHelper::Signer { NOTREACHED(); return false; } + + std::string GetAlgorithmIdentifier() override { return "fake-signer"; } }; // IdentitySigner returns a "signature" over given signing data whose value @@ -87,6 +89,7 @@ class IdentitySigner : public TrustTokenRequestSigningHelper::Signer { base::span<const uint8_t> verification_key) override { return std::equal(data.begin(), data.end(), signature.begin()); } + std::string GetAlgorithmIdentifier() override { return "identity-signer"; } }; // FailingSigner always fails the Sign and Verify options. @@ -102,6 +105,7 @@ class FailingSigner : public TrustTokenRequestSigningHelper::Signer { base::span<const uint8_t> verification_key) override { return false; } + std::string GetAlgorithmIdentifier() override { return "failing-signer"; } }; // Reconstructs |request|'s canonical request data, extracts the signatures from @@ -119,8 +123,10 @@ void ReconstructSigningDataAndAssertSignaturesVerify( request->url(), request->extra_request_headers(), base::BindRepeating([](base::span<const uint8_t> data, base::span<const uint8_t> signature, - base::span<const uint8_t> verification_key) { - return Signer().Verify(data, signature, verification_key); + base::span<const uint8_t> verification_key, + const std::string& signing_alg) { + return Signer().Verify(data, signature, verification_key) && + signing_alg == Signer().GetAlgorithmIdentifier(); }), &error, &verification_keys_per_issuer); @@ -224,10 +230,10 @@ TEST_F(TrustTokenRequestSigningHelperTest, WontSignIfNoRedemptionRecord) { ExecuteBeginOperationAndWaitForResult(&helper, my_request.get()); // In failure cases---in particular, in this case where none of the provided - // issuers has a signed redemption record in storage---the signing helper - // should return kOk but attach an empty SRR header. + // issuers has a redemption record in storage---the signing helper should + // return kOk but attach an empty RR header. EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk); - EXPECT_THAT(*my_request, Header("Sec-Signed-Redemption-Record", IsEmpty())); + EXPECT_THAT(*my_request, Header("Sec-Redemption-Record", IsEmpty())); EXPECT_THAT(*my_request, Not(Header("Sec-Signature"))); } @@ -244,9 +250,9 @@ TEST_F(TrustTokenRequestSigningHelperTest, MergesHeaders) { params.sign_request_data = mojom::TrustTokenSignRequestData::kHeadersOnly; params.additional_headers_to_sign = std::vector<std::string>{"Sec-Time"}; - SignedTrustTokenRedemptionRecord my_record; + TrustTokenRedemptionRecord my_record; my_record.set_public_key("key"); - my_record.set_body("SRR body"); + my_record.set_body("RR body"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, my_record); @@ -259,7 +265,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, MergesHeaders) { url::Origin::Create(GURL("https://initiator.com/"))); my_request->SetExtraRequestHeaderByName( - "Signed-Headers", "Sec-Signed-Redemption-Record", /*overwrite=*/true); + "Signed-Headers", "Sec-Redemption-Record", /*overwrite=*/true); mojom::TrustTokenOperationStatus result = ExecuteBeginOperationAndWaitForResult(&helper, my_request.get()); @@ -270,10 +276,10 @@ TEST_F(TrustTokenRequestSigningHelperTest, MergesHeaders) { "Signed-Headers", &signed_headers_header_value)); // Headers should have been merged and lower-cased. - EXPECT_THAT(base::SplitString(signed_headers_header_value, ",", - base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL), - UnorderedElementsAre(StrEq("sec-time"), - StrEq("sec-signed-redemption-record"))); + EXPECT_THAT( + base::SplitString(signed_headers_header_value, ",", base::KEEP_WHITESPACE, + base::SPLIT_WANT_ALL), + UnorderedElementsAre(StrEq("sec-time"), StrEq("sec-redemption-record"))); } TEST_F(TrustTokenRequestSigningHelperTest, @@ -290,7 +296,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com"))); params.sign_request_data = mojom::TrustTokenSignRequestData::kHeadersOnly; - SignedTrustTokenRedemptionRecord my_record; + TrustTokenRedemptionRecord my_record; my_record.set_public_key("key"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, my_record); @@ -313,9 +319,9 @@ TEST_F(TrustTokenRequestSigningHelperTest, ExecuteBeginOperationAndWaitForResult(&helper, my_request.get()); // In failure cases, the signing helper should return kOk but attach an empty - // SRR header. + // RR header. EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk); - EXPECT_THAT(*my_request, Header("Sec-Signed-Redemption-Record", IsEmpty())); + EXPECT_THAT(*my_request, Header("Sec-Redemption-Record", IsEmpty())); EXPECT_THAT(*my_request, Not(Header("Signed-Headers"))); } @@ -336,7 +342,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, "this header name is definitely not in " "TrustTokenRequestSigningHelper::kSignableRequestHeaders"}; - SignedTrustTokenRedemptionRecord my_record; + TrustTokenRedemptionRecord my_record; my_record.set_public_key("key"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, my_record); @@ -352,7 +358,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, ExecuteBeginOperationAndWaitForResult(&helper, my_request.get()); EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk); - EXPECT_THAT(*my_request, Header("Sec-Signed-Redemption-Record", IsEmpty())); + EXPECT_THAT(*my_request, Header("Sec-Redemption-Record", IsEmpty())); EXPECT_THAT(*my_request, Not(Header("Signed-Headers"))); } @@ -374,9 +380,9 @@ TEST_F(TrustTokenRequestSigningHelperTestWithMockTime, ProvidesTimeHeader) { params.sign_request_data = mojom::TrustTokenSignRequestData::kHeadersOnly; params.should_add_timestamp = true; - SignedTrustTokenRedemptionRecord my_record; + TrustTokenRedemptionRecord my_record; my_record.set_public_key("key"); - my_record.set_body("look at me, I'm an SRR body"); + my_record.set_body("look at me, I'm an RR body"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, my_record); @@ -395,7 +401,7 @@ TEST_F(TrustTokenRequestSigningHelperTestWithMockTime, ProvidesTimeHeader) { Header("Sec-Time", StrEq(base::TimeToISO8601(base::Time::Now())))); } -// Test SRR attachment without request signing: +// Test RR attachment without request signing: // - The two issuers with stored redemption records should appear in the header. // - A third issuer without a corresponding redemption record in storage // shouldn't appear in the header. @@ -411,15 +417,15 @@ TEST_F(TrustTokenRequestSigningHelperTest, params.issuers.push_back( *SuitableTrustTokenOrigin::Create(GURL("https://second-issuer.example"))); - SignedTrustTokenRedemptionRecord first_issuer_record; - first_issuer_record.set_body("look at me! I'm a signed redemption record"); + TrustTokenRedemptionRecord first_issuer_record; + first_issuer_record.set_body("look at me! I'm a redemption record"); first_issuer_record.set_public_key("key"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, first_issuer_record); - SignedTrustTokenRedemptionRecord second_issuer_record; + TrustTokenRedemptionRecord second_issuer_record; second_issuer_record.set_body( - "I'm another signed redemption record, distinct from the first"); + "I'm another redemption record, distinct from the first"); second_issuer_record.set_public_key("some other key"); store->SetRedemptionRecord(params.issuers.back(), params.toplevel, second_issuer_record); @@ -442,7 +448,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, std::string redemption_record_header; ASSERT_TRUE(my_request->extra_request_headers().GetHeader( - "Sec-Signed-Redemption-Record", &redemption_record_header)); + "Sec-Redemption-Record", &redemption_record_header)); std::map<SuitableTrustTokenOrigin, std::string> redemption_records_per_issuer; std::string error; ASSERT_TRUE(test::ExtractRedemptionRecordsFromHeader( @@ -469,9 +475,9 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyMinimal) { *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com"))); params.sign_request_data = mojom::TrustTokenSignRequestData::kHeadersOnly; - SignedTrustTokenRedemptionRecord my_record; + TrustTokenRedemptionRecord my_record; my_record.set_public_key("key"); - my_record.set_body("look at me, I'm an SRR body"); + my_record.set_body("look at me, I'm an RR body"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, my_record); @@ -505,17 +511,17 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyWithHeaders) { *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com")), *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com"))); params.sign_request_data = mojom::TrustTokenSignRequestData::kHeadersOnly; - SignedTrustTokenRedemptionRecord record; - record.set_body("I am a signed token redemption record"); + TrustTokenRedemptionRecord record; + record.set_body("I am a token redemption record"); record.set_public_key("key"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, record); params.additional_headers_to_sign = - std::vector<std::string>{"Sec-Signed-Redemption-Record"}; + std::vector<std::string>{"Sec-Redemption-Record"}; params.issuers.push_back( *SuitableTrustTokenOrigin::Create(GURL("https://second-issuer.example"))); - SignedTrustTokenRedemptionRecord other_record; - other_record.set_body("I am a different signed token redemption record"); + TrustTokenRedemptionRecord other_record; + other_record.set_body("I am a different token redemption record"); other_record.set_public_key("some other key"); store->SetRedemptionRecord(params.issuers.back(), params.toplevel, other_record); @@ -548,8 +554,8 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyTimestampHeader) { params.additional_headers_to_sign = std::vector<std::string>{"sec-time"}; params.should_add_timestamp = true; - SignedTrustTokenRedemptionRecord record; - record.set_body("I am a signed token redemption record"); + TrustTokenRedemptionRecord record; + record.set_body("I am a token redemption record"); record.set_public_key("key"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, record); @@ -590,12 +596,12 @@ TEST_F(TrustTokenRequestSigningHelperTest, *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com"))); params.sign_request_data = mojom::TrustTokenSignRequestData::kInclude; - SignedTrustTokenRedemptionRecord record; - record.set_body("I am a signed token redemption record"); + TrustTokenRedemptionRecord record; + record.set_body("I am a token redemption record"); record.set_public_key("key"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, record); params.additional_headers_to_sign = - std::vector<std::string>{"Sec-Signed-Redemption-Record"}; + std::vector<std::string>{"Sec-Redemption-Record"}; auto canonicalizer = std::make_unique<TrustTokenRequestCanonicalizer>(); TrustTokenRequestSigningHelper helper(store.get(), std::move(params), @@ -630,7 +636,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, } // When signing fails, the request should have an empty -// Sec-Signed-Redemption-Record header attached, and none of the other headers +// Sec-Redemption-Record header attached, and none of the other headers // that could potentially be added during signing. TEST_F(TrustTokenRequestSigningHelperTest, CatchesSignatureFailure) { std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting(); @@ -640,7 +646,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, CatchesSignatureFailure) { *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com"))); params.sign_request_data = mojom::TrustTokenSignRequestData::kHeadersOnly; - SignedTrustTokenRedemptionRecord my_record; + TrustTokenRedemptionRecord my_record; my_record.set_public_key("key"); my_record.set_signing_key("signing key"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, @@ -648,7 +654,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, CatchesSignatureFailure) { params.should_add_timestamp = true; params.additional_headers_to_sign = - std::vector<std::string>{"Sec-Signed-Redemption-Record"}; + std::vector<std::string>{"Sec-Redemption-Record"}; // FailingSigner will fail to sign the request, so we should see the operation // fail. @@ -669,7 +675,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, CatchesSignatureFailure) { EXPECT_THAT(*my_request, Not(Header("Signed-Headers"))); EXPECT_THAT(*my_request, Not(Header("Sec-Time"))); EXPECT_THAT(*my_request, Not(Header("Sec-Signature"))); - EXPECT_THAT(*my_request, Header("Sec-Signed-Redemption-Record", IsEmpty())); + EXPECT_THAT(*my_request, Header("Sec-Redemption-Record", IsEmpty())); EXPECT_TRUE(base::ranges::any_of( net_log.GetEntriesWithType( net::NetLogEventType::TRUST_TOKEN_OPERATION_BEGIN_SIGNING), @@ -696,8 +702,8 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyAdditionalSigningData) { params.possibly_unsafe_additional_signing_data = "some additional data to sign"; - SignedTrustTokenRedemptionRecord record; - record.set_body("I am a signed token redemption record"); + TrustTokenRedemptionRecord record; + record.set_body("I am a token redemption record"); record.set_public_key("key"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, record); @@ -741,7 +747,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, params.possibly_unsafe_additional_signing_data = std::string(kTrustTokenAdditionalSigningDataMaxSizeBytes + 1, 'a'); - SignedTrustTokenRedemptionRecord my_record; + TrustTokenRedemptionRecord my_record; my_record.set_public_key("key"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, my_record); @@ -758,9 +764,9 @@ TEST_F(TrustTokenRequestSigningHelperTest, ExecuteBeginOperationAndWaitForResult(&helper, my_request.get()); // In failure cases, the signing helper should return kOk but attach an empty - // SRR header. + // RR header. EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk); - EXPECT_THAT(*my_request, Header("Sec-Signed-Redemption-Record", IsEmpty())); + EXPECT_THAT(*my_request, Header("Sec-Redemption-Record", IsEmpty())); EXPECT_THAT(*my_request, Not(Header("Signed-Headers"))); EXPECT_THAT(*my_request, Not(Header("Sec-Trust-Tokens-Additional-Signing-Data"))); @@ -776,7 +782,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, params.sign_request_data = mojom::TrustTokenSignRequestData::kHeadersOnly; params.possibly_unsafe_additional_signing_data = "\r"; - SignedTrustTokenRedemptionRecord my_record; + TrustTokenRedemptionRecord my_record; my_record.set_public_key("key"); store->SetRedemptionRecord(params.issuers.front(), params.toplevel, my_record); @@ -793,9 +799,9 @@ TEST_F(TrustTokenRequestSigningHelperTest, ExecuteBeginOperationAndWaitForResult(&helper, my_request.get()); // In failure cases, the signing helper should return kOk but attach an empty - // SRR header. + // RR header. EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk); - EXPECT_THAT(*my_request, Header("Sec-Signed-Redemption-Record", IsEmpty())); + EXPECT_THAT(*my_request, Header("Sec-Redemption-Record", IsEmpty())); EXPECT_THAT(*my_request, Not(Header("Signed-Headers"))); EXPECT_THAT(*my_request, Not(Header("Sec-Trust-Tokens-Additional-Signing-Data"))); diff --git a/chromium/services/network/trust_tokens/trust_token_store.cc b/chromium/services/network/trust_tokens/trust_token_store.cc index 090531035f4..615cb2e8ccc 100644 --- a/chromium/services/network/trust_tokens/trust_token_store.cc +++ b/chromium/services/network/trust_tokens/trust_token_store.cc @@ -28,7 +28,7 @@ namespace { class NeverExpiringExpiryDelegate : public TrustTokenStore::RecordExpiryDelegate { public: - bool IsRecordExpired(const SignedTrustTokenRedemptionRecord& record, + bool IsRecordExpired(const TrustTokenRedemptionRecord& record, const SuitableTrustTokenOrigin& issuer) override { return false; } @@ -244,15 +244,15 @@ void TrustTokenStore::DeleteToken(const SuitableTrustTokenOrigin& issuer, void TrustTokenStore::SetRedemptionRecord( const SuitableTrustTokenOrigin& issuer, const SuitableTrustTokenOrigin& top_level, - const SignedTrustTokenRedemptionRecord& record) { + const TrustTokenRedemptionRecord& record) { auto config = persister_->GetIssuerToplevelPairConfig(issuer, top_level); if (!config) config = std::make_unique<TrustTokenIssuerToplevelPairConfig>(); - *config->mutable_signed_redemption_record() = record; + *config->mutable_redemption_record() = record; persister_->SetIssuerToplevelPairConfig(issuer, top_level, std::move(config)); } -base::Optional<SignedTrustTokenRedemptionRecord> +base::Optional<TrustTokenRedemptionRecord> TrustTokenStore::RetrieveNonstaleRedemptionRecord( const SuitableTrustTokenOrigin& issuer, const SuitableTrustTokenOrigin& top_level) { @@ -260,14 +260,14 @@ TrustTokenStore::RetrieveNonstaleRedemptionRecord( if (!config) return base::nullopt; - if (!config->has_signed_redemption_record()) + if (!config->has_redemption_record()) return base::nullopt; - if (record_expiry_delegate_->IsRecordExpired( - config->signed_redemption_record(), issuer)) + if (record_expiry_delegate_->IsRecordExpired(config->redemption_record(), + issuer)) return base::nullopt; - return config->signed_redemption_record(); + return config->redemption_record(); } bool TrustTokenStore::ClearDataForFilter(mojom::ClearDataFilterPtr filter) { diff --git a/chromium/services/network/trust_tokens/trust_token_store.h b/chromium/services/network/trust_tokens/trust_token_store.h index edaefe39a9c..407c1358ed2 100644 --- a/chromium/services/network/trust_tokens/trust_token_store.h +++ b/chromium/services/network/trust_tokens/trust_token_store.h @@ -37,7 +37,7 @@ namespace network { // For example, it provides operations: // - checking preconditions for the different protocol steps; // - storing unblinded, signed tokens; and -// - managing Signed Redemption Records (SRRs) and corresponding key pairs. +// - managing Redemption Records (RRs). // // TrustTokenStore's methods do minimal precondition checking and, in // particular, only selectively verify protocol-level invariants and @@ -48,25 +48,25 @@ class TrustTokenStore { public: virtual ~RecordExpiryDelegate() = default; - // Returns whether the given Signed Redemption Record has expired. + // Returns whether the given Redemption Record has expired. // This is implemented with a delegate to abstract away reading - // the values of SRRs (they're opaque to this store). + // the values of RRs (they're opaque to this store). // - // |issuer| is the issuer that issued the SRR. - virtual bool IsRecordExpired(const SignedTrustTokenRedemptionRecord& record, + // |issuer| is the issuer that issued the RR. + virtual bool IsRecordExpired(const TrustTokenRedemptionRecord& record, const SuitableTrustTokenOrigin& issuer) = 0; }; // Creates a TrustTokenStore relying on the given persister for underlying - // storage and the given delegate for judging whether signed redemption - // records have expired. + // storage and the given delegate for judging whether redemption records + // have expired. TrustTokenStore(std::unique_ptr<TrustTokenPersister> persister, std::unique_ptr<RecordExpiryDelegate> expiry_delegate); virtual ~TrustTokenStore(); // Creates a TrustTokenStore with defaults useful for testing: an in-memory - // persister and never expiring stored SRRs. Callers may provide custom values + // persister and never expiring stored RRs. Callers may provide custom values // for one argument or both. static std::unique_ptr<TrustTokenStore> CreateForTesting( std::unique_ptr<TrustTokenPersister> persister = nullptr, @@ -164,20 +164,19 @@ class TrustTokenStore { void DeleteToken(const SuitableTrustTokenOrigin& issuer, const TrustToken& to_delete); - //// Methods concerning Signed Redemption Records (SRRs) + //// Methods concerning Redemption Records (RRs) - // Sets the cached SRR corresponding to the pair (issuer, top_level) + // Sets the cached RR corresponding to the pair (issuer, top_level) // to |record|. Overwrites any existing record. - virtual void SetRedemptionRecord( - const SuitableTrustTokenOrigin& issuer, - const SuitableTrustTokenOrigin& top_level, - const SignedTrustTokenRedemptionRecord& record); + virtual void SetRedemptionRecord(const SuitableTrustTokenOrigin& issuer, + const SuitableTrustTokenOrigin& top_level, + const TrustTokenRedemptionRecord& record); - // Attempts to retrieve the stored SRR for the given pair of (issuer, + // Attempts to retrieve the stored RR for the given pair of (issuer, // top-level) origins. - // - If the pair has a current (i.e., non-expired) SRR, returns that SRR. + // - If the pair has a current (i.e., non-expired) RR, returns that RR. // - Otherwise, returns nullopt. - WARN_UNUSED_RESULT virtual base::Optional<SignedTrustTokenRedemptionRecord> + WARN_UNUSED_RESULT virtual base::Optional<TrustTokenRedemptionRecord> RetrieveNonstaleRedemptionRecord(const SuitableTrustTokenOrigin& issuer, const SuitableTrustTokenOrigin& top_level); diff --git a/chromium/services/network/trust_tokens/trust_token_store_unittest.cc b/chromium/services/network/trust_tokens/trust_token_store_unittest.cc index 8819797097b..0f698a7ebd5 100644 --- a/chromium/services/network/trust_tokens/trust_token_store_unittest.cc +++ b/chromium/services/network/trust_tokens/trust_token_store_unittest.cc @@ -438,7 +438,7 @@ TEST(TrustTokenStore, DeleteTokenForMissingIssuer) { TEST(TrustTokenStore, SetsAndRetrievesRedemptionRecord) { // A newly initialized store should not think - // it has any signed redemption records. + // it has any redemption records. auto my_store = TrustTokenStore::CreateForTesting( std::make_unique<InMemoryTrustTokenPersister>()); @@ -456,8 +456,8 @@ TEST(TrustTokenStore, SetsAndRetrievesRedemptionRecord) { // queries (modulo the record's staleness) should return that // record. - SignedTrustTokenRedemptionRecord my_record; - my_record.set_body("Look at me! I'm a signed redemption record!"); + TrustTokenRedemptionRecord my_record; + my_record.set_body("Look at me! I'm a redemption record!"); my_store->SetRedemptionRecord(issuer, toplevel, my_record); EXPECT_THAT(my_store->RetrieveNonstaleRedemptionRecord(issuer, toplevel), @@ -495,11 +495,11 @@ TEST(TrustTokenStore, SetRedemptionRecordOverwritesExisting) { base::test::TaskEnvironment env( base::test::TaskEnvironment::TimeSource::MOCK_TIME); - SignedTrustTokenRedemptionRecord my_record; - my_record.set_body("Look at me! I'm a signed redemption record!"); + TrustTokenRedemptionRecord my_record; + my_record.set_body("Look at me! I'm a redemption record!"); my_store->SetRedemptionRecord(issuer, toplevel, my_record); - SignedTrustTokenRedemptionRecord another_record; + TrustTokenRedemptionRecord another_record; another_record.set_body( "If all goes well, this one should overwrite |my_record|."); my_store->SetRedemptionRecord(issuer, toplevel, another_record); @@ -509,11 +509,11 @@ TEST(TrustTokenStore, SetRedemptionRecordOverwritesExisting) { } namespace { -// Characterizes an SRR as expired if its body begins with an "a". +// Characterizes an RR as expired if its body begins with an "a". class LetterAExpiringExpiryDelegate : public TrustTokenStore::RecordExpiryDelegate { public: - bool IsRecordExpired(const SignedTrustTokenRedemptionRecord& record, + bool IsRecordExpired(const TrustTokenRedemptionRecord& record, const SuitableTrustTokenOrigin&) override { return record.body().size() > 1 && record.body().front() == 'a'; } @@ -531,8 +531,8 @@ TEST(TrustTokenStore, DoesNotReturnStaleRedemptionRecord) { SuitableTrustTokenOrigin toplevel = *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com")); - SignedTrustTokenRedemptionRecord my_record; - my_record.set_body("aLook at me! I'm an expired signed redemption record!"); + TrustTokenRedemptionRecord my_record; + my_record.set_body("aLook at me! I'm an expired redemption record!"); my_store->SetRedemptionRecord(issuer, toplevel, my_record); EXPECT_EQ(my_store->RetrieveNonstaleRedemptionRecord(issuer, toplevel), @@ -599,8 +599,7 @@ TEST(TrustTokenStore, ClearsIssuerToplevelPairKeyedData) { *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com")); { - store->SetRedemptionRecord(issuer, toplevel, - SignedTrustTokenRedemptionRecord()); + store->SetRedemptionRecord(issuer, toplevel, TrustTokenRedemptionRecord()); auto filter = mojom::ClearDataFilter::New(); filter->origins.push_back(issuer); EXPECT_TRUE(store->ClearDataForFilter(std::move(filter))); @@ -608,8 +607,7 @@ TEST(TrustTokenStore, ClearsIssuerToplevelPairKeyedData) { } { - store->SetRedemptionRecord(issuer, toplevel, - SignedTrustTokenRedemptionRecord()); + store->SetRedemptionRecord(issuer, toplevel, TrustTokenRedemptionRecord()); auto filter = mojom::ClearDataFilter::New(); filter->origins.push_back(toplevel); EXPECT_TRUE(store->ClearDataForFilter(std::move(filter))); @@ -638,8 +636,7 @@ TEST(TrustTokenStore, RemovesDataForInvertedFilters) { *SuitableTrustTokenOrigin::Create(GURL("https://www.toplevel.com")); store->AddTokens(issuer, std::vector<std::string>{"token"}, "key"); - store->SetRedemptionRecord(issuer, toplevel, - SignedTrustTokenRedemptionRecord{}); + store->SetRedemptionRecord(issuer, toplevel, TrustTokenRedemptionRecord{}); // With a "delete all origins not covered by this filter"-type filter // containing just the issuer, the issuer's data shouldn't be touched, but the @@ -668,8 +665,7 @@ TEST(TrustTokenStore, RemovesDataForNullFilter) { // some top level-keyed state, ASSERT_TRUE(store->SetAssociation(issuer, toplevel)); // and some (issuer, top level) pair-keyed state. - store->SetRedemptionRecord(issuer, toplevel, - SignedTrustTokenRedemptionRecord{}); + store->SetRedemptionRecord(issuer, toplevel, TrustTokenRedemptionRecord{}); EXPECT_TRUE(store->ClearDataForFilter(nullptr)); EXPECT_FALSE(store->CountTokens(issuer)); diff --git a/chromium/services/network/trust_tokens/types.cc b/chromium/services/network/trust_tokens/types.cc index 81e14c98971..a3e865ca324 100644 --- a/chromium/services/network/trust_tokens/types.cc +++ b/chromium/services/network/trust_tokens/types.cc @@ -33,5 +33,15 @@ base::StringPiece TrustTokenOperationTypeToString( } } +std::string ProtocolVersionToString( + mojom::TrustTokenProtocolVersion my_version) { + switch (my_version) { + case mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb: + return "TrustTokenV2PMB"; + case mojom::TrustTokenProtocolVersion::kTrustTokenV2Voprf: + return "TrustTokenV2VOPRF"; + } +} + } // namespace internal } // namespace network diff --git a/chromium/services/network/trust_tokens/types.h b/chromium/services/network/trust_tokens/types.h index 46f6e4be021..5e1f30e72aa 100644 --- a/chromium/services/network/trust_tokens/types.h +++ b/chromium/services/network/trust_tokens/types.h @@ -29,6 +29,9 @@ std::string TimeToString(base::Time my_time); base::StringPiece TrustTokenOperationTypeToString( mojom::TrustTokenOperationType type); +// Serializes a mojom::TrustTokenProtocolVersion. +std::string ProtocolVersionToString(mojom::TrustTokenProtocolVersion); + } // namespace internal } // namespace network diff --git a/chromium/services/network/url_loader.cc b/chromium/services/network/url_loader.cc index e13745d859c..75a96d80674 100644 --- a/chromium/services/network/url_loader.cc +++ b/chromium/services/network/url_loader.cc @@ -11,7 +11,7 @@ #include <vector> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/debug/alias.h" #include "base/debug/dump_without_crashing.h" @@ -224,10 +224,6 @@ std::unique_ptr<net::UploadDataStream> CreateUploadDataStream( element_readers.push_back(std::make_unique<FileElementReader>( body, file_task_runner, element, std::move(*opened_file++))); break; - case network::mojom::DataElementType::kBlob: { - CHECK(false) << "Network service always uses DATA_PIPE for blobs."; - break; - } case network::mojom::DataElementType::kDataPipe: { element_readers.push_back(std::make_unique<DataPipeElementReader>( body, element.CloneDataPipeGetter())); @@ -552,9 +548,9 @@ URLLoader::URLLoader( } } else if (factory_params_->automatically_assign_isolation_info) { url::Origin origin = url::Origin::Create(request.url); - url_request_->set_isolation_info(net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, origin, origin, - net::SiteForCookies())); + url_request_->set_isolation_info( + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + origin, origin, net::SiteForCookies())); } if (url_request_context_->require_network_isolation_key()) @@ -651,6 +647,25 @@ URLLoader::URLLoader( // Resolve elements from request_body and prepare upload data. if (request.request_body.get()) { + const auto& elements = *request.request_body->elements(); + // TODO(crbug.com/1156550): Move this logic to the deserialization part. + if (elements.size() == 1 && + (elements[0].type() == mojom::DataElementType::kChunkedDataPipe || + elements[0].type() == mojom::DataElementType::kReadOnceStream)) { + const bool chunked_data_pipe_getter_is_valid = + elements[0].chunked_data_pipe_getter().is_valid(); + UMA_HISTOGRAM_BOOLEAN( + "NetworkService.StreamingUploadDataPipeGetterValidity", + chunked_data_pipe_getter_is_valid); + if (!chunked_data_pipe_getter_is_valid) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&URLLoader::NotifyCompleted, base::Unretained(this), + net::ERR_INVALID_ARGUMENT)); + return; + } + } + OpenFilesForUpload(request); return; } @@ -982,15 +997,13 @@ void URLLoader::ResumeReadingBodyFromNet() { } } -int URLLoader::CanConnectToRemoteEndpoint( - const net::TransportInfo& info) const { - const mojom::IPAddressSpace remote_address_space = - IPAddressToIPAddressSpace(info.endpoint.address()); +bool URLLoader::CanConnectToAddressSpace( + mojom::IPAddressSpace resource_address_space) const { if (options_ & mojom::kURLLoadOptionBlockLocalRequest && - IsLessPublicAddressSpace(remote_address_space, + IsLessPublicAddressSpace(resource_address_space, network::mojom::IPAddressSpace::kPublic)) { DVLOG(1) << "CORS-RFC1918 check: failed due to loader options."; - return net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST; + return false; } // Depending on the type of URL request, we source the client security state @@ -1013,7 +1026,7 @@ int URLLoader::CanConnectToRemoteEndpoint( if (!security_state) { DVLOG(1) << "CORS-RFC1918 check: skipped, missing client security state."; - return net::OK; + return true; } DVLOG(1) << "CORS-RFC1918 check: running against client security state = { " @@ -1033,16 +1046,16 @@ int URLLoader::CanConnectToRemoteEndpoint( // insecure public websites from making requests to someone's printer, for // example. if (!security_state->is_web_secure_context && - IsLessPublicAddressSpace(remote_address_space, + IsLessPublicAddressSpace(resource_address_space, security_state->ip_address_space)) { DVLOG(1) << "CORS-RFC1918 check: " "failed, blocking insecure private network request."; - return net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST; + return false; } } DVLOG(1) << "CORS-RFC1918 check: success."; - return net::OK; + return true; } int URLLoader::OnConnected(net::URLRequest* url_request, @@ -1054,7 +1067,17 @@ int URLLoader::OnConnected(net::URLRequest* url_request, // Now that the request endpoint's address has been resolved, check if // this request should be blocked by CORS-RFC1918 rules. - return CanConnectToRemoteEndpoint(info); + mojom::IPAddressSpace resource_address_space = + IPAddressToIPAddressSpace(info.endpoint.address()); + if (!CanConnectToAddressSpace(resource_address_space)) { + // Remember the CORS error so we can annotate the URLLoaderCompletionStatus + // with it later, then fail the request with the same net error code as + // other CORS errors. + cors_error_status_ = CorsErrorStatus(resource_address_space); + return net::ERR_FAILED; + } + + return net::OK; } void URLLoader::OnReceivedRedirect(net::URLRequest* url_request, @@ -1370,7 +1393,7 @@ void URLLoader::ContinueOnResponseStarted() { // Create IsolationInfo as if this were an uncredentialed subresource // request of the original URL. net::IsolationInfo isolation_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, + net::IsolationInfo::RequestType::kOther, url_request_->isolation_info().top_frame_origin().value(), url_request_->isolation_info().frame_origin().value(), net::SiteForCookies()); @@ -1751,6 +1774,7 @@ void URLLoader::NotifyCompleted(int error_code) { url_request_->response_info().resolve_error_info; if (trust_token_status_) status.trust_token_operation_status = *trust_token_status_; + status.cors_error_status = cors_error_status_; if ((options_ & mojom::kURLLoadOptionSendSSLInfoForCertificateError) && net::IsCertStatusError(url_request_->ssl_info().cert_status)) { @@ -1806,16 +1830,6 @@ void URLLoader::SendResponseToClient() { TRACE_EVENT1("loading", "network::URLLoader::SendResponseToClient", "url", url_request_->url().possibly_invalid_spec()); url_loader_client_->OnReceiveResponse(std::move(response_)); - - net::IOBufferWithSize* metadata = - url_request_->response_info().metadata.get(); - if (metadata) { - const uint8_t* data = reinterpret_cast<const uint8_t*>(metadata->data()); - - url_loader_client_->OnReceiveCachedMetadata( - std::vector<uint8_t>(data, data + metadata->size())); - } - url_loader_client_->OnStartLoadingResponseBody(std::move(consumer_handle_)); } diff --git a/chromium/services/network/url_loader.h b/chromium/services/network/url_loader.h index 70518f42849..22515b2c051 100644 --- a/chromium/services/network/url_loader.h +++ b/chromium/services/network/url_loader.h @@ -29,11 +29,13 @@ #include "net/url_request/url_request.h" #include "services/network/keepalive_statistics_recorder.h" #include "services/network/network_service.h" +#include "services/network/public/cpp/cors/cors_error_status.h" #include "services/network/public/cpp/cross_origin_read_blocking.h" #include "services/network/public/cpp/initiator_lock_compatibility.h" #include "services/network/public/mojom/cookie_access_observer.mojom.h" #include "services/network/public/mojom/cross_origin_embedder_policy.mojom-forward.h" #include "services/network/public/mojom/fetch_api.mojom.h" +#include "services/network/public/mojom/ip_address_space.mojom-forward.h" #include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/trust_tokens.mojom-shared.h" #include "services/network/public/mojom/url_loader.mojom.h" @@ -345,15 +347,14 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader void StartReading(); void OnOriginPolicyManagerRetrieveDone(const OriginPolicy& origin_policy); - // Checks if the request initiator should be allowed to make requests to the - // remote endpoint, as described in |info|. - // - // Returns a net error code. + // Returns whether the request initiator should be allowed to make requests to + // an endpoint in |resource_address_space|. // // See the CORS-RFC1918 spec: https://wicg.github.io/cors-rfc1918. // // Helper for OnConnected(). - int CanConnectToRemoteEndpoint(const net::TransportInfo& info) const; + bool CanConnectToAddressSpace( + mojom::IPAddressSpace resource_address_space) const; net::URLRequestContext* url_request_context_; mojom::NetworkServiceClient* network_service_client_; @@ -398,6 +399,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader // True if there's a URLRequest::Read() call in progress. bool read_in_progress_ = false; + // Stores any CORS error encountered while processing |url_request_|. + base::Optional<CorsErrorStatus> cors_error_status_; + // Used when deferring sending the data to the client until mime sniffing is // finished. mojom::URLResponseHeadPtr response_; diff --git a/chromium/services/network/url_loader_factory.cc b/chromium/services/network/url_loader_factory.cc index 75ae8488efa..2b18ba12e28 100644 --- a/chromium/services/network/url_loader_factory.cc +++ b/chromium/services/network/url_loader_factory.cc @@ -26,6 +26,7 @@ #include "services/network/public/cpp/resource_request.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/resource_scheduler/resource_scheduler_client.h" +#include "services/network/trust_tokens/local_trust_token_operation_delegate_impl.h" #include "services/network/trust_tokens/trust_token_request_helper_factory.h" #include "services/network/url_loader.h" #include "url/gurl.h" @@ -81,8 +82,8 @@ URLLoaderFactory::URLLoaderFactory( DCHECK_NE(mojom::kInvalidProcessId, params_->process_id); DCHECK(!params_->factory_override); // Only non-navigation IsolationInfos should be bound to URLLoaderFactories. - DCHECK_EQ(net::IsolationInfo::RedirectMode::kUpdateNothing, - params_->isolation_info.redirect_mode()); + DCHECK_EQ(net::IsolationInfo::RequestType::kOther, + params_->isolation_info.request_type()); DCHECK(!params_->automatically_assign_isolation_info || params_->isolation_info.IsEmpty()); @@ -220,6 +221,11 @@ void URLLoaderFactory::CreateLoaderAndStart( trust_token_factory = std::make_unique<TrustTokenRequestHelperFactory>( context_->trust_token_store(), context_->network_service()->trust_token_key_commitments(), + // It's safe to use Unretained because |context_| is guaranteed to + // outlive the URLLoader that will own this + // TrustTokenRequestHelperFactory. + base::BindRepeating(&NetworkContext::client, + base::Unretained(context_)), // It's safe to use Unretained here because // NetworkContext::CookieManager outlives the URLLoaders associated with // the NetworkContext. diff --git a/chromium/services/network/url_loader_unittest.cc b/chromium/services/network/url_loader_unittest.cc index bd8415c7634..acd828b9a72 100644 --- a/chromium/services/network/url_loader_unittest.cc +++ b/chromium/services/network/url_loader_unittest.cc @@ -13,7 +13,7 @@ #include "base/auto_reset.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/files/file.h" #include "base/files/file_path.h" @@ -26,10 +26,9 @@ #include "base/path_service.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/gtest_util.h" #include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" @@ -82,6 +81,7 @@ #include "services/network/public/mojom/cookie_access_observer.mojom-forward.h" #include "services/network/public/mojom/cookie_access_observer.mojom.h" #include "services/network/public/mojom/ip_address_space.mojom.h" +#include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/origin_policy_manager.mojom.h" #include "services/network/public/mojom/trust_tokens.mojom-shared.h" #include "services/network/public/mojom/url_loader.mojom.h" @@ -1035,7 +1035,9 @@ TEST_F(URLLoaderTest, InsecureRequestToLocalResource) { set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), - IsError(net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST)); + IsError(net::ERR_FAILED)); + EXPECT_THAT(client()->completion_status().cors_error_status, + Optional(CorsErrorStatus(mojom::IPAddressSpace::kLocal))); } TEST_F(URLLoaderTest, InsecurePublicToLocalIsBlocked) { @@ -1045,7 +1047,9 @@ TEST_F(URLLoaderTest, InsecurePublicToLocalIsBlocked) { set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), - IsError(net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST)); + IsError(net::ERR_FAILED)); + EXPECT_THAT(client()->completion_status().cors_error_status, + Optional(CorsErrorStatus(mojom::IPAddressSpace::kLocal))); } TEST_F(URLLoaderTest, InsecurePrivateToLocalIsBlocked) { @@ -1055,7 +1059,9 @@ TEST_F(URLLoaderTest, InsecurePrivateToLocalIsBlocked) { set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), - IsError(net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST)); + IsError(net::ERR_FAILED)); + EXPECT_THAT(client()->completion_status().cors_error_status, + Optional(CorsErrorStatus(mojom::IPAddressSpace::kLocal))); } TEST_F(URLLoaderTest, InsecureLocalToLocalIsOk) { @@ -1078,7 +1084,9 @@ TEST_F(URLLoaderTest, TrustedParamsInsecurePublicToLocalIsBlocked) { set_request_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), - IsError(net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST)); + IsError(net::ERR_FAILED)); + EXPECT_THAT(client()->completion_status().cors_error_status, + Optional(CorsErrorStatus(mojom::IPAddressSpace::kLocal))); } // Bundles together the inputs to a parameterized private network request test. @@ -1150,6 +1158,10 @@ TEST_P(URLLoaderFakeTransportInfoTest, PrivateNetworkRequestLoadsCorrectly) { // Despite its name, IsError(OK) asserts that the matched value is OK. EXPECT_THAT(Load(url), IsError(params.expected_result)); + if (params.expected_result != net::OK) { + EXPECT_THAT(client()->completion_status().cors_error_status, + Optional(CorsErrorStatus(params.endpoint_address_space))); + } } // Lists all combinations we want to test in URLLoaderFakeTransportInfoTest. @@ -1169,12 +1181,12 @@ constexpr URLLoaderFakeTransportInfoTestParams { mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kPrivate, - net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST, + net::ERR_FAILED, }, { mojom::IPAddressSpace::kUnknown, mojom::IPAddressSpace::kLocal, - net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST, + net::ERR_FAILED, }, // Client: kPublic { @@ -1190,12 +1202,12 @@ constexpr URLLoaderFakeTransportInfoTestParams { mojom::IPAddressSpace::kPublic, mojom::IPAddressSpace::kPrivate, - net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST, + net::ERR_FAILED, }, { mojom::IPAddressSpace::kPublic, mojom::IPAddressSpace::kLocal, - net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST, + net::ERR_FAILED, }, // Client: kPrivate { @@ -1216,7 +1228,7 @@ constexpr URLLoaderFakeTransportInfoTestParams { mojom::IPAddressSpace::kPrivate, mojom::IPAddressSpace::kLocal, - net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST, + net::ERR_FAILED, }, // Client: kLocal { @@ -5241,7 +5253,7 @@ TEST_F(URLLoaderTest, OriginPolicyManagerCalled) { CreateResourceRequest("GET", server.GetURL("/with_policy")); // This is what the IsolationInfo for a main frame will normally look like. request.trusted_params->isolation_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateTopFrame, + net::IsolationInfo::RequestType::kMainFrame, test_server_origin /* top_frame_origin */, test_server_origin /* frame_origin */, net::SiteForCookies::FromOrigin(test_server_origin)); @@ -5285,13 +5297,13 @@ TEST_F(URLLoaderTest, OriginPolicyManagerCalled) { // Check IsolationInfo sent to the OriginPolicyManager. Both origins should // be the same as the |isolation_info| field of - // ResourceRequest::trusted_params, but the RedirectMode should be - // kUpdateNothing, and the SiteForCookies should be null. + // ResourceRequest::trusted_params, but the RequestType should be + // kOther, and the SiteForCookies should be null. EXPECT_TRUE( - net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, - test_server_origin /* top_frame_origin */, - test_server_origin /* frame_origin */, net::SiteForCookies()) + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + test_server_origin /* top_frame_origin */, + test_server_origin /* frame_origin */, + net::SiteForCookies()) .IsEqualForTesting(mock_origin_policy_manager.isolation_info())); } @@ -5385,7 +5397,7 @@ TEST_F(URLLoaderTest, OriginPolicyManagerCalled) { // IsolationInfo used for the ResourceRequest. This is what the // IsolationInfo for a cross-origin subframe will normally look like. request.trusted_params->isolation_info = net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateFrameOnly, top_frame_origin, + net::IsolationInfo::RequestType::kSubFrame, top_frame_origin, test_server_origin /* frame_origin */, net::SiteForCookies()); request.site_for_cookies = request.trusted_params->isolation_info.site_for_cookies(); @@ -5419,11 +5431,11 @@ TEST_F(URLLoaderTest, OriginPolicyManagerCalled) { // Check IsolationInfo sent to the OriginPolicyManager. Both origins should // be the same as the |isolation_info| field of - // ResourceRequest::trusted_params, but the RedirectMode should be - // kUpdateNothing, and the SiteForCookies should be null. + // ResourceRequest::trusted_params, but the RequestType should be + // kOther, and the SiteForCookies should be null. EXPECT_TRUE( net::IsolationInfo::Create( - net::IsolationInfo::RedirectMode::kUpdateNothing, top_frame_origin, + net::IsolationInfo::RequestType::kOther, top_frame_origin, test_server_origin /* frame_origin */, net::SiteForCookies()) .IsEqualForTesting(mock_origin_policy_manager.isolation_info())); } @@ -5540,15 +5552,21 @@ class NoopTrustTokenKeyCommitmentGetter : public TrustTokenKeyCommitmentGetter { base::NoDestructor<NoopTrustTokenKeyCommitmentGetter> noop_key_commitment_getter{}; +mojom::NetworkContextClient* ReturnNullNetworkContextClient() { + return nullptr; +} + class MockTrustTokenRequestHelperFactory : public TrustTokenRequestHelperFactory { public: MockTrustTokenRequestHelperFactory( mojom::TrustTokenOperationStatus creation_failure_error, SyncOrAsync sync_or_async) - : TrustTokenRequestHelperFactory(nullptr, - noop_key_commitment_getter.get(), - {}), + : TrustTokenRequestHelperFactory( + nullptr, + noop_key_commitment_getter.get(), + base::BindRepeating(&ReturnNullNetworkContextClient), + {}), sync_or_async_(sync_or_async), creation_failure_error_(creation_failure_error) {} @@ -5557,9 +5575,11 @@ class MockTrustTokenRequestHelperFactory base::Optional<mojom::TrustTokenOperationStatus> on_finalize, SyncOrAsync sync_or_async, bool* begin_done_flag) - : TrustTokenRequestHelperFactory(nullptr, - noop_key_commitment_getter.get(), - {}), + : TrustTokenRequestHelperFactory( + nullptr, + noop_key_commitment_getter.get(), + base::BindRepeating(&ReturnNullNetworkContextClient), + {}), sync_or_async_(sync_or_async), helper_( std::make_unique<MockTrustTokenRequestHelper>(on_begin, @@ -5685,11 +5705,11 @@ TEST_P(URLLoaderSyncOrAsyncTrustTokenOperationTest, // the load. // // (This is the case exactly when the request is for token redemption, and the -// Trust Tokens logic determines that there is already a cached signed -// redemption record stored locally, obviating the need to execute a redemption +// Trust Tokens logic determines that there is already a cached redemption +// record stored locally, obviating the need to execute a redemption // operation.) TEST_P(URLLoaderSyncOrAsyncTrustTokenOperationTest, - HandlesTrustTokenSignedRedemptionRecordCacheHit) { + HandlesTrustTokenRedemptionRecordCacheHit) { ResourceRequest request = CreateResourceRequest("GET", test_server()->GetURL("/simple_page.html")); request.trust_token_params = diff --git a/chromium/services/network/url_request_context_builder_mojo.cc b/chromium/services/network/url_request_context_builder_mojo.cc index a3cdf878a53..dc9195464a9 100644 --- a/chromium/services/network/url_request_context_builder_mojo.cc +++ b/chromium/services/network/url_request_context_builder_mojo.cc @@ -6,6 +6,7 @@ #include "base/check.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "net/proxy_resolution/configured_proxy_resolution_service.h" #include "net/proxy_resolution/pac_file_fetcher_impl.h" #include "net/proxy_resolution/proxy_config_service.h" @@ -14,7 +15,7 @@ #include "services/network/public/cpp/features.h" #if defined(OS_WIN) #include "net/proxy_resolution/win/dhcp_pac_file_fetcher_win.h" -#elif defined(OS_CHROMEOS) +#elif BUILDFLAG(IS_ASH) #include "services/network/dhcp_pac_file_fetcher_mojo.h" #endif @@ -30,20 +31,20 @@ void URLRequestContextBuilderMojo::SetMojoProxyResolverFactory( mojo_proxy_resolver_factory_ = std::move(mojo_proxy_resolver_factory); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void URLRequestContextBuilderMojo::SetDhcpWpadUrlClient( mojo::PendingRemote<network::mojom::DhcpWpadUrlClient> dhcp_wpad_url_client) { dhcp_wpad_url_client_ = std::move(dhcp_wpad_url_client); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) std::unique_ptr<net::DhcpPacFileFetcher> URLRequestContextBuilderMojo::CreateDhcpPacFileFetcher( net::URLRequestContext* context) { #if defined(OS_WIN) return std::make_unique<net::DhcpPacFileFetcherWin>(context); -#elif defined(OS_CHROMEOS) +#elif BUILDFLAG(IS_ASH) return std::make_unique<DhcpPacFileFetcherMojo>( context, std::move(dhcp_wpad_url_client_)); #else diff --git a/chromium/services/network/url_request_context_builder_mojo.h b/chromium/services/network/url_request_context_builder_mojo.h index 77cf6e37421..66d4bfa0d85 100644 --- a/chromium/services/network/url_request_context_builder_mojo.h +++ b/chromium/services/network/url_request_context_builder_mojo.h @@ -10,15 +10,16 @@ #include "base/component_export.h" #include "base/macros.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "net/url_request/url_request_context_builder.h" #include "services/network/public/mojom/network_service.mojom.h" #include "services/network/url_request_context_owner.h" #include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "services/network/public/mojom/dhcp_wpad_url_client.mojom.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) namespace net { class DhcpPacFileFetcher; @@ -47,11 +48,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLRequestContextBuilderMojo mojo::PendingRemote<proxy_resolver::mojom::ProxyResolverFactory> mojo_proxy_resolver_factory); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void SetDhcpWpadUrlClient( mojo::PendingRemote<network::mojom::DhcpWpadUrlClient> dhcp_wpad_url_client); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) private: std::unique_ptr<net::ProxyResolutionService> CreateProxyResolutionService( @@ -65,11 +66,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLRequestContextBuilderMojo std::unique_ptr<net::DhcpPacFileFetcher> CreateDhcpPacFileFetcher( net::URLRequestContext* context); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // If set, handles calls to get the PAC script URL from the browser process. // Only used if |mojo_proxy_resolver_factory_| is set. mojo::PendingRemote<network::mojom::DhcpWpadUrlClient> dhcp_wpad_url_client_; -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) mojo::PendingRemote<proxy_resolver::mojom::ProxyResolverFactory> mojo_proxy_resolver_factory_; diff --git a/chromium/services/network/url_request_context_builder_mojo_unittest.cc b/chromium/services/network/url_request_context_builder_mojo_unittest.cc index 5b90b7c7bd2..4d5fbf713cc 100644 --- a/chromium/services/network/url_request_context_builder_mojo_unittest.cc +++ b/chromium/services/network/url_request_context_builder_mojo_unittest.cc @@ -8,6 +8,7 @@ #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/test/task_environment.h" +#include "build/chromeos_buildflags.h" #include "net/base/host_port_pair.h" #include "net/proxy_resolution/proxy_config.h" #include "net/proxy_resolution/proxy_config_service_fixed.h" @@ -24,9 +25,9 @@ #include "testing/platform_test.h" #include "url/gurl.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "services/network/mock_mojo_dhcp_wpad_url_client.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) namespace network { @@ -76,10 +77,10 @@ TEST_F(URLRequestContextBuilderMojoTest, MojoProxyResolver) { builder_.SetMojoProxyResolverFactory( test_mojo_proxy_resolver_factory_.CreateFactoryRemote()); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) builder_.SetDhcpWpadUrlClient( MockMojoDhcpWpadUrlClient::CreateWithSelfOwnedReceiver(std::string())); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) std::unique_ptr<net::URLRequestContext> context(builder_.Build()); net::TestDelegate delegate; @@ -112,10 +113,10 @@ TEST_F(URLRequestContextBuilderMojoTest, ShutdownWithHungRequest) { builder_.SetMojoProxyResolverFactory( test_mojo_proxy_resolver_factory_.CreateFactoryRemote()); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) builder_.SetDhcpWpadUrlClient( MockMojoDhcpWpadUrlClient::CreateWithSelfOwnedReceiver(std::string())); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) std::unique_ptr<net::URLRequestContext> context(builder_.Build()); net::TestDelegate delegate; diff --git a/chromium/services/network/websocket.cc b/chromium/services/network/websocket.cc index 105b439d901..d3db7ac87df 100644 --- a/chromium/services/network/websocket.cc +++ b/chromium/services/network/websocket.cc @@ -10,7 +10,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/feature_list.h" #include "base/location.h" #include "base/logging.h" @@ -144,7 +144,9 @@ class WebSocket::WebSocketEventHandler final void OnDropChannel(bool was_clean, uint16_t code, const std::string& reason) override; - void OnFailChannel(const std::string& message) override; + void OnFailChannel(const std::string& message, + int net_error, + base::Optional<int> response_code) override; void OnStartOpeningHandshake( std::unique_ptr<net::WebSocketHandshakeRequestInfo> request) override; void OnSSLCertificateError( @@ -290,12 +292,22 @@ void WebSocket::WebSocketEventHandler::OnDropChannel( } void WebSocket::WebSocketEventHandler::OnFailChannel( - const std::string& message) { + const std::string& message, + int net_error, + base::Optional<int> response_code) { DVLOG(3) << "WebSocketEventHandler::OnFailChannel @" - << reinterpret_cast<void*>(this) << " message=\"" << message << "\""; - - impl_->handshake_client_.ResetWithReason(mojom::WebSocket::kInternalFailure, - message); + << reinterpret_cast<void*>(this) << " message=\"" << message << "\"" + << " error=" << net_error + << " response_code=" << response_code.value_or(-1); + + // OnAddChannelResponse may have already reset |impl_->handshake_client_| if + // the failure happened after a successful connection. + if (impl_->handshake_client_.is_bound()) { + impl_->handshake_client_->OnFailure(message, net_error, + response_code.value_or(-1)); + impl_->handshake_client_.ResetWithReason(mojom::WebSocket::kInternalFailure, + message); + } impl_->client_.ResetWithReason(mojom::WebSocket::kInternalFailure, message); impl_->Reset(); } diff --git a/chromium/services/network/websocket_factory.cc b/chromium/services/network/websocket_factory.cc index f5525ded93b..b7c8a8aa931 100644 --- a/chromium/services/network/websocket_factory.cc +++ b/chromium/services/network/websocket_factory.cc @@ -41,10 +41,10 @@ void WebSocketFactory::CreateWebSocket( mojo::PendingRemote<mojom::WebSocketHandshakeClient> handshake_client, mojo::PendingRemote<mojom::AuthenticationHandler> auth_handler, mojo::PendingRemote<mojom::TrustedHeaderClient> header_client) { - if (isolation_info.redirect_mode() != - net::IsolationInfo::RedirectMode::kUpdateNothing) { + if (isolation_info.request_type() != + net::IsolationInfo::RequestType::kOther) { mojo::ReportBadMessage( - "WebSocket's IsolationInfo::RedirectMode must be kUpdateNothing"); + "WebSocket's IsolationInfo::RequestType must be kOther"); return; } diff --git a/chromium/services/preferences/DIR_METADATA b/chromium/services/preferences/DIR_METADATA new file mode 100644 index 00000000000..3b080ff26b8 --- /dev/null +++ b/chromium/services/preferences/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Preferences>Service" +}
\ No newline at end of file diff --git a/chromium/services/preferences/OWNERS b/chromium/services/preferences/OWNERS index b1261bd1222..6662cdd5198 100644 --- a/chromium/services/preferences/OWNERS +++ b/chromium/services/preferences/OWNERS @@ -1,4 +1,2 @@ jonross@chromium.org sammc@chromium.org - -# COMPONENT: Internals>Preferences>Service diff --git a/chromium/services/preferences/tracked/BUILD.gn b/chromium/services/preferences/tracked/BUILD.gn index a1ad50b5745..ce1222e664d 100644 --- a/chromium/services/preferences/tracked/BUILD.gn +++ b/chromium/services/preferences/tracked/BUILD.gn @@ -2,19 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - source_set("tracked") { sources = [ "device_id.h", - "device_id_mac.cc", - "device_id_stub.cc", - "device_id_win.cc", "dictionary_hash_store_contents.cc", "dictionary_hash_store_contents.h", "hash_store_contents.h", @@ -28,8 +18,6 @@ source_set("tracked") { "pref_hash_store_impl.cc", "pref_hash_store_impl.h", "pref_hash_store_transaction.h", - "registry_hash_store_contents_win.cc", - "registry_hash_store_contents_win.h", "segregated_pref_store.cc", "segregated_pref_store.h", "temp_scoped_dir_cleaner.h", @@ -46,8 +34,16 @@ source_set("tracked") { "tracked_split_preference.h", ] - if (is_win || is_mac) { - sources -= [ "device_id_stub.cc" ] + if (is_win) { + sources += [ + "device_id_win.cc", + "registry_hash_store_contents_win.cc", + "registry_hash_store_contents_win.h", + ] + } else if (is_mac) { + sources += [ "device_id_mac.cc" ] + } else { + sources += [ "device_id_stub.cc" ] } # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. @@ -78,11 +74,14 @@ source_set("unit_tests") { "pref_hash_calculator_unittest.cc", "pref_hash_filter_unittest.cc", "pref_hash_store_impl_unittest.cc", - "registry_hash_store_contents_win_unittest.cc", "segregated_pref_store_unittest.cc", "tracked_preferences_migration_unittest.cc", ] + if (is_win) { + sources += [ "registry_hash_store_contents_win_unittest.cc" ] + } + deps = [ ":tracked", "//base", diff --git a/chromium/services/proxy_resolver/DIR_METADATA b/chromium/services/proxy_resolver/DIR_METADATA new file mode 100644 index 00000000000..e05317a9b32 --- /dev/null +++ b/chromium/services/proxy_resolver/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Network>Proxy" +}
\ No newline at end of file diff --git a/chromium/services/proxy_resolver/OWNERS b/chromium/services/proxy_resolver/OWNERS index d8ae3263b28..2fdb6e72c14 100644 --- a/chromium/services/proxy_resolver/OWNERS +++ b/chromium/services/proxy_resolver/OWNERS @@ -1,2 +1 @@ -file://services/network/OWNERS -# COMPONENT: Internals>Network>Proxy +file://services/network/OWNERS
\ No newline at end of file diff --git a/chromium/services/proxy_resolver/proxy_resolver_factory_impl_unittest.cc b/chromium/services/proxy_resolver/proxy_resolver_factory_impl_unittest.cc index 124158b4ffa..bcf969b6eea 100644 --- a/chromium/services/proxy_resolver/proxy_resolver_factory_impl_unittest.cc +++ b/chromium/services/proxy_resolver/proxy_resolver_factory_impl_unittest.cc @@ -7,7 +7,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/optional.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" diff --git a/chromium/services/resource_coordinator/BUILD.gn b/chromium/services/resource_coordinator/BUILD.gn index 87aeaa1f7a2..ef63860f979 100644 --- a/chromium/services/resource_coordinator/BUILD.gn +++ b/chromium/services/resource_coordinator/BUILD.gn @@ -54,6 +54,7 @@ source_set("tests") { "public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits_unittest.cc", "public/cpp/memory_instrumentation/os_metrics_unittest.cc", "public/cpp/memory_instrumentation/tracing_integration_unittest.cc", + "public/cpp/memory_instrumentation/tracing_observer_proto_unittest.cc", ] deps = [ @@ -64,6 +65,7 @@ source_set("tests") { "//mojo/public/cpp/bindings", "//services/resource_coordinator/public/cpp:resource_coordinator_cpp", "//services/resource_coordinator/public/cpp/memory_instrumentation:memory_instrumentation", + "//services/tracing:tests", "//testing/gmock", "//testing/gtest", ] diff --git a/chromium/services/resource_coordinator/DEPS b/chromium/services/resource_coordinator/DEPS index 7e714d03182..cc9f8cf75c4 100644 --- a/chromium/services/resource_coordinator/DEPS +++ b/chromium/services/resource_coordinator/DEPS @@ -3,4 +3,5 @@ include_rules = [ "+third_party/perfetto", "+third_party/smhasher", "+services/metrics/public", + "+services/tracing/public/cpp", ] diff --git a/chromium/services/resource_coordinator/DIR_METADATA b/chromium/services/resource_coordinator/DIR_METADATA new file mode 100644 index 00000000000..07ecfd7a90e --- /dev/null +++ b/chromium/services/resource_coordinator/DIR_METADATA @@ -0,0 +1,12 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>ResourceCoordinator" +} +team_email: "catan-team@chromium.org"
\ No newline at end of file diff --git a/chromium/services/resource_coordinator/OWNERS b/chromium/services/resource_coordinator/OWNERS index 2b8c9bcc9bb..021ff205f2f 100644 --- a/chromium/services/resource_coordinator/OWNERS +++ b/chromium/services/resource_coordinator/OWNERS @@ -8,6 +8,3 @@ oysteine@chromium.org zhenw@chromium.org per-file BUILD.gn=file://services/resource_coordinator/memory_instrumentation/OWNERS - -# TEAM: catan-team@chromium.org -# COMPONENT: Internals>ResourceCoordinator diff --git a/chromium/services/resource_coordinator/memory_instrumentation/DIR_METADATA b/chromium/services/resource_coordinator/memory_instrumentation/DIR_METADATA new file mode 100644 index 00000000000..970fc89f715 --- /dev/null +++ b/chromium/services/resource_coordinator/memory_instrumentation/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Instrumentation>Memory" +}
\ No newline at end of file diff --git a/chromium/services/resource_coordinator/memory_instrumentation/OWNERS b/chromium/services/resource_coordinator/memory_instrumentation/OWNERS index e13658dd0d4..822acf152ac 100644 --- a/chromium/services/resource_coordinator/memory_instrumentation/OWNERS +++ b/chromium/services/resource_coordinator/memory_instrumentation/OWNERS @@ -1,4 +1,3 @@ hjd@chromium.org primiano@chromium.org -ssid@chromium.org -# COMPONENT: Internals>Instrumentation>Memory +ssid@chromium.org
\ No newline at end of file diff --git a/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc b/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc index 37facb9f51b..c1ec3256ed2 100644 --- a/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc +++ b/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc @@ -10,7 +10,6 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" #include "base/callback_helpers.h" #include "base/command_line.h" #include "base/location.h" @@ -26,6 +25,8 @@ #include "services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h" #include "services/resource_coordinator/memory_instrumentation/switches.h" #include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h" @@ -62,14 +63,21 @@ class StringWrapper : public base::trace_event::ConvertableToTraceFormat { CoordinatorImpl::CoordinatorImpl() : next_dump_id_(0), - client_process_timeout_(base::TimeDelta::FromSeconds(15)) { + client_process_timeout_(base::TimeDelta::FromSeconds(15)), + use_proto_writer_(base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kUseMemoryTrackingProtoWriter)) { DCHECK(!g_coordinator_impl); g_coordinator_impl = this; base::trace_event::MemoryDumpManager::GetInstance()->set_tracing_process_id( mojom::kServiceTracingProcessId); - tracing_observer_ = std::make_unique<TracingObserver>( - base::trace_event::TraceLog::GetInstance(), nullptr); + if (use_proto_writer_) { + tracing_observer_ = std::make_unique<TracingObserverProto>( + base::trace_event::TraceLog::GetInstance(), nullptr); + } else { + tracing_observer_ = std::make_unique<TracingObserverTracedValue>( + base::trace_event::TraceLog::GetInstance(), nullptr); + } } CoordinatorImpl::~CoordinatorImpl() { @@ -567,7 +575,8 @@ void CoordinatorImpl::FinalizeGlobalMemoryDumpIfAllManagersReplied() { return; } - QueuedRequestDispatcher::Finalize(request, tracing_observer_.get()); + QueuedRequestDispatcher::Finalize(request, tracing_observer_.get(), + use_proto_writer_); queued_memory_dump_requests_.pop_front(); request = nullptr; diff --git a/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.h b/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.h index 2395d750ae3..531194d0e89 100644 --- a/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.h +++ b/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.h @@ -190,6 +190,8 @@ class CoordinatorImpl : public mojom::CoordinatorController, mojo::Receiver<mojom::HeapProfilerHelper> heap_profiler_helper_receiver_{ this}; + const bool use_proto_writer_; + THREAD_CHECKER(thread_checker_); base::WeakPtrFactory<CoordinatorImpl> weak_ptr_factory_{this}; diff --git a/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc b/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc index b6cf74f45e5..2a27c3b9b28 100644 --- a/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc +++ b/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc @@ -19,7 +19,12 @@ #include "services/resource_coordinator/memory_instrumentation/aggregate_metrics_processor.h" #include "services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.h" #include "services/resource_coordinator/memory_instrumentation/switches.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h" #include "third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h" +#include "third_party/perfetto/protos/perfetto/trace/memory_graph.pbzero.h" +#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h" #if defined(OS_MAC) #include "base/mac/mac_util.h" @@ -45,7 +50,8 @@ namespace { uint32_t CalculatePrivateFootprintKb(const mojom::RawOSMemDump& os_dump, uint32_t shared_resident_kb) { DCHECK(os_dump.platform_private_footprint); -#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || \ + defined(OS_FUCHSIA) uint64_t rss_anon_bytes = os_dump.platform_private_footprint->rss_anon_bytes; uint64_t vm_swap_bytes = os_dump.platform_private_footprint->vm_swap_bytes; return (rss_anon_bytes + vm_swap_bytes) / 1024; @@ -382,7 +388,8 @@ QueuedRequestDispatcher::FinalizeVmRegionRequest( } void QueuedRequestDispatcher::Finalize(QueuedRequest* request, - TracingObserver* tracing_observer) { + TracingObserver* tracing_observer, + bool use_proto_writer) { DCHECK(request->dump_in_progress); DCHECK(request->pending_responses.empty()); @@ -438,7 +445,7 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request, pid_to_os_dump[original_pid] = kv.second.get(); } #endif - } // for (response : request->responses) + } MemoryDumpMapConverter converter; perfetto::trace_processor::GraphProcessor::RawMemoryNodeMap perfettoNodeMap = @@ -446,6 +453,8 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request, // Generate the global memory graph from the map of pids to dumps, removing // weak nodes. + // TODO (crbug.com/1112671): We should avoid graph processing once we moved + // the shared footprint computation to perfetto. std::unique_ptr<GlobalNodeGraph> global_graph = GraphProcessor::CreateMemoryGraph(perfettoNodeMap); GraphProcessor::RemoveWeakNodesFromGraph(global_graph.get()); @@ -462,6 +471,9 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request, GraphProcessor::AddOverheadsAndPropagateEntries(global_graph.get()); GraphProcessor::CalculateSizesForGraph(global_graph.get()); + // The same timestamp needs to be set for all dumps in the memory snapshot. + base::TimeTicks timestamp = TRACE_TIME_TICKS_NOW(); + // Build up the global dump by iterating on the |valid| process dumps. mojom::GlobalMemoryDumpPtr global_dump(mojom::GlobalMemoryDump::New()); global_dump->start_time = request->start_time; @@ -511,8 +523,8 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request, if (request->args.add_to_trace) { if (raw_os_dump) { bool trace_os_success = tracing_observer->AddOsDumpToTraceIfEnabled( - request->GetRequestArgs(), pid, os_dump.get(), - &raw_os_dump->memory_maps); + request->GetRequestArgs(), pid, *os_dump, raw_os_dump->memory_maps, + timestamp); if (!trace_os_success) request->failed_memory_dump_count++; } @@ -520,7 +532,7 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request, if (raw_chrome_dump) { bool trace_chrome_success = AddChromeMemoryDumpToTrace( request->GetRequestArgs(), pid, *raw_chrome_dump, *global_graph, - pid_to_process_type, tracing_observer); + pid_to_process_type, tracing_observer, use_proto_writer, timestamp); if (!trace_chrome_success) request->failed_memory_dump_count++; } @@ -602,17 +614,24 @@ bool QueuedRequestDispatcher::AddChromeMemoryDumpToTrace( const base::trace_event::ProcessMemoryDump& raw_chrome_dump, const GlobalNodeGraph& global_graph, const std::map<base::ProcessId, mojom::ProcessType>& pid_to_process_type, - TracingObserver* tracing_observer) { + TracingObserver* tracing_observer, + bool use_proto_writer, + const base::TimeTicks& timestamp) { bool is_chrome_tracing_enabled = base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableChromeTracingComputation); if (!is_chrome_tracing_enabled) { - return tracing_observer->AddChromeDumpToTraceIfEnabled(args, pid, - &raw_chrome_dump); + return tracing_observer->AddChromeDumpToTraceIfEnabled( + args, pid, &raw_chrome_dump, timestamp); } if (!tracing_observer->ShouldAddToTrace(args)) return false; + if (use_proto_writer) { + return tracing_observer->AddChromeDumpToTraceIfEnabled( + args, pid, &raw_chrome_dump, timestamp); + } + const GlobalNodeGraph::Process& process = *global_graph.process_node_graphs().find(pid)->second; @@ -623,7 +642,7 @@ bool QueuedRequestDispatcher::AddChromeMemoryDumpToTrace( } else { traced_value = GetChromeDumpTracedValue(process); } - tracing_observer->AddToTrace(args, pid, std::move(traced_value)); + TracingObserverTracedValue::AddToTrace(args, pid, std::move(traced_value)); return true; } diff --git a/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h b/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h index 61ae4c5f48f..c56cc4b19cd 100644 --- a/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h +++ b/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h @@ -62,7 +62,8 @@ class QueuedRequestDispatcher { // dispatching to the appropriate callback. Also adds to tracing using // |tracing_observer| if the |request| requires it. static void Finalize(QueuedRequest* request, - TracingObserver* tracing_observer); + TracingObserver* tracing_observer, + bool use_proto_writer); static void SetUpAndDispatchVmRegionRequest( QueuedVmRegionRequest* request, @@ -78,7 +79,9 @@ class QueuedRequestDispatcher { const base::trace_event::ProcessMemoryDump& raw_chrome_dump, const perfetto::trace_processor::GlobalNodeGraph& global_graph, const std::map<base::ProcessId, mojom::ProcessType>& pid_to_process_type, - TracingObserver* tracing_observer); + TracingObserver* tracing_observer, + bool use_proto_writer, + const base::TimeTicks& timestamp); }; } // namespace memory_instrumentation diff --git a/chromium/services/resource_coordinator/memory_instrumentation/switches.cc b/chromium/services/resource_coordinator/memory_instrumentation/switches.cc index d4f0f689ce0..a944b4185fb 100644 --- a/chromium/services/resource_coordinator/memory_instrumentation/switches.cc +++ b/chromium/services/resource_coordinator/memory_instrumentation/switches.cc @@ -10,6 +10,7 @@ namespace switches { // Enable the tracing service. const char kEnableChromeTracingComputation[] = "enable-chrome-tracing-computation"; +const char kUseMemoryTrackingProtoWriter[] = "use-memory-tracking-proto-writer"; } // namespace switches -} // namespace memory_instrumentation
\ No newline at end of file +} // namespace memory_instrumentation diff --git a/chromium/services/resource_coordinator/memory_instrumentation/switches.h b/chromium/services/resource_coordinator/memory_instrumentation/switches.h index 9ca825da605..0c6b776e22d 100644 --- a/chromium/services/resource_coordinator/memory_instrumentation/switches.h +++ b/chromium/services/resource_coordinator/memory_instrumentation/switches.h @@ -11,8 +11,9 @@ namespace switches { // All switches in alphabetical order. The switches should be documented // alongside the definition of their values in the .cc file. extern const char kEnableChromeTracingComputation[]; +extern const char kUseMemoryTrackingProtoWriter[]; } // namespace switches } // namespace memory_instrumentation -#endif // SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_SWITCHES_H_
\ No newline at end of file +#endif // SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_SWITCHES_H_ diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn index 35f1858173b..faf0ddbc6b2 100644 --- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn @@ -2,13 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - component("memory_instrumentation") { sources = [ "client_process_impl.cc", @@ -19,18 +12,24 @@ component("memory_instrumentation") { "memory_instrumentation.h", "os_metrics.cc", "os_metrics.h", - "os_metrics_linux.cc", - "os_metrics_mac.cc", - "os_metrics_win.cc", "tracing_observer.cc", "tracing_observer.h", + "tracing_observer_proto.cc", + "tracing_observer_proto.h", + "tracing_observer_traced_value.cc", + "tracing_observer_traced_value.h", ] - if (is_android) { - # Disable the rule that excludes _linux.cc files from Android builds. - set_sources_assignment_filter([]) + if (is_mac) { + sources += [ "os_metrics_mac.cc" ] + } + + if (is_win) { + sources += [ "os_metrics_win.cc" ] + } + + if (is_android || is_linux || is_chromeos) { sources += [ "os_metrics_linux.cc" ] - set_sources_assignment_filter(deprecated_default_sources_assignment_filter) } if (is_fuchsia) { @@ -48,6 +47,7 @@ component("memory_instrumentation") { "//base", "//mojo/public/cpp/bindings", "//services/resource_coordinator/public/mojom", + "//services/tracing/public/cpp", ] } diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.cc index 7fe44758994..18429ea9a12 100644 --- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.cc +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.cc @@ -18,6 +18,7 @@ const char kBrowserHistogramName[] = "Browser"; const char kExtensionHistogramName[] = "Extension"; const char kGpuHistogramName[] = "Gpu"; const char kNetworkServiceHistogramName[] = "NetworkService"; +const char kPaintPreviewCompositorHistogramName[] = "PaintPreviewCompositor"; const char kRendererHistogramName[] = "Renderer"; const char kUtilityHistogramName[] = "Utility"; @@ -37,6 +38,8 @@ const char* HistogramProcessTypeToString(HistogramProcessType type) { return kGpuHistogramName; case HistogramProcessType::kNetworkService: return kNetworkServiceHistogramName; + case HistogramProcessType::kPaintPreviewCompositor: + return kPaintPreviewCompositorHistogramName; case HistogramProcessType::kRenderer: return kRendererHistogramName; case HistogramProcessType::kUtility: diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h index 5ed4e1acf1a..b1b1a46b10a 100644 --- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h @@ -29,6 +29,7 @@ enum class HistogramProcessType { kExtension, kGpu, kNetworkService, + kPaintPreviewCompositor, kRenderer, kUtility, }; diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc index b96cb6d7215..ca0e8d8441a 100644 --- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc @@ -5,7 +5,7 @@ #include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/containers/flat_map.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_piece.h" diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h index dcf1c9c863a..6dd8c55823d 100644 --- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h @@ -96,8 +96,9 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) mojo::Remote<mojom::Coordinator> coordinator_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - // TODO(ssid): This should be moved to coordinator instead of clients once we - // have the whole chrome dumps sent via mojo, crbug.com/728199. + // TODO(crbug.com/728199): The observer is only used to setup and tear down + // MemoryDumpManager in each process. Setting up MemoryDumpManager should + // be moved away from TracingObserver. std::unique_ptr<TracingObserver> tracing_observer_; DISALLOW_COPY_AND_ASSIGN(ClientProcessImpl); diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc index 5f9c55171c3..374ff2a3d14 100644 --- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc @@ -6,7 +6,7 @@ #include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/memory/ref_counted_memory.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc index 221956c6306..a80f9b35533 100644 --- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc @@ -1,4 +1,4 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. +// 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. @@ -25,29 +25,6 @@ bool IsMemoryInfraTracingEnabled() { return enabled; } -void OsDumpAsValueInto(TracedValue* value, const mojom::OSMemDump& os_dump) { - value->SetString( - "private_footprint_bytes", - base::StringPrintf( - "%" PRIx64, - static_cast<uint64_t>(os_dump.private_footprint_kb) * 1024)); - value->SetString( - "peak_resident_set_size", - base::StringPrintf( - "%" PRIx64, - static_cast<uint64_t>(os_dump.peak_resident_set_kb) * 1024)); - value->SetBoolean("is_peak_rss_resettable", os_dump.is_peak_rss_resettable); -} - -std::string ApplyPathFiltering(const std::string& file, - bool is_argument_filtering_enabled) { - if (is_argument_filtering_enabled) { - base::FilePath::StringType path(file.begin(), file.end()); - return base::FilePath(path).BaseName().AsUTF8Unsafe(); - } - return file; -} - } // namespace TracingObserver::TracingObserver( @@ -97,6 +74,23 @@ void TracingObserver::OnTraceLogDisabled() { memory_dump_config_.reset(); } +bool TracingObserver::AddChromeDumpToTraceIfEnabled( + const base::trace_event::MemoryDumpRequestArgs&, + const base::ProcessId pid, + const base::trace_event::ProcessMemoryDump*, + const base::TimeTicks& timestamp) { + return false; +} + +bool TracingObserver::AddOsDumpToTraceIfEnabled( + const base::trace_event::MemoryDumpRequestArgs& args, + const base::ProcessId pid, + const mojom::OSMemDump& os_dump, + const std::vector<mojom::VmRegionPtr>& memory_maps, + const base::TimeTicks& timestamp) { + return false; +} + bool TracingObserver::ShouldAddToTrace( const base::trace_event::MemoryDumpRequestArgs& args) { // If tracing has been disabled early out to avoid the cost of serializing the @@ -110,125 +104,15 @@ bool TracingObserver::ShouldAddToTrace( return true; } -void TracingObserver::AddToTrace( - const base::trace_event::MemoryDumpRequestArgs& args, - const base::ProcessId pid, - std::unique_ptr<TracedValue> traced_value) { - CHECK_NE(base::trace_event::MemoryDumpType::SUMMARY_ONLY, args.dump_type); - - traced_value->SetString( - "level_of_detail", - base::trace_event::MemoryDumpLevelOfDetailToString(args.level_of_detail)); - const uint64_t dump_guid = args.dump_guid; - const char* const event_name = - base::trace_event::MemoryDumpTypeToString(args.dump_type); - base::trace_event::TraceArguments trace_args("dumps", - std::move(traced_value)); - TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID( - TRACE_EVENT_PHASE_MEMORY_DUMP, - base::trace_event::TraceLog::GetCategoryGroupEnabled( - base::trace_event::MemoryDumpManager::kTraceCategory), - event_name, trace_event_internal::kGlobalScope, dump_guid, pid, - &trace_args, TRACE_EVENT_FLAG_HAS_ID); -} - -bool TracingObserver::AddChromeDumpToTraceIfEnabled( - const base::trace_event::MemoryDumpRequestArgs& args, - const base::ProcessId pid, - const ProcessMemoryDump* process_memory_dump) { - if (!ShouldAddToTrace(args)) - return false; - - std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>(); - process_memory_dump->SerializeAllocatorDumpsInto(traced_value.get()); - - AddToTrace(args, pid, std::move(traced_value)); - - return true; -} - -bool TracingObserver::AddOsDumpToTraceIfEnabled( - const base::trace_event::MemoryDumpRequestArgs& args, - const base::ProcessId pid, - const mojom::OSMemDump* os_dump, - const std::vector<mojom::VmRegionPtr>* memory_maps) { - if (!ShouldAddToTrace(args)) - return false; - - std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>(); - - traced_value->BeginDictionary("process_totals"); - OsDumpAsValueInto(traced_value.get(), *os_dump); - traced_value->EndDictionary(); - - if (memory_maps->size()) { - traced_value->BeginDictionary("process_mmaps"); - MemoryMapsAsValueInto(*memory_maps, traced_value.get(), false); - traced_value->EndDictionary(); - } - - AddToTrace(args, pid, std::move(traced_value)); - return true; -} - // static -void TracingObserver::MemoryMapsAsValueInto( - const std::vector<mojom::VmRegionPtr>& memory_maps, - TracedValue* value, +std::string TracingObserver::ApplyPathFiltering( + const std::string& file, bool is_argument_filtering_enabled) { - static const char kHexFmt[] = "%" PRIx64; - - // Refer to the design doc goo.gl/sxfFY8 for the semantics of these fields. - value->BeginArray("vm_regions"); - for (const auto& region : memory_maps) { - value->BeginDictionary(); - - value->SetString("sa", base::StringPrintf(kHexFmt, region->start_address)); - value->SetString("sz", base::StringPrintf(kHexFmt, region->size_in_bytes)); - if (region->module_timestamp) - value->SetString("ts", - base::StringPrintf(kHexFmt, region->module_timestamp)); - if (!region->module_debugid.empty()) - value->SetString("id", region->module_debugid); - if (!region->module_debug_path.empty()) { - value->SetString("df", ApplyPathFiltering(region->module_debug_path, - is_argument_filtering_enabled)); - } - value->SetInteger("pf", region->protection_flags); - - // The module path will be the basename when argument filtering is - // activated. The whitelisting implemented for filtering string values - // doesn't allow rewriting. Therefore, a different path is produced here - // when argument filtering is activated. - value->SetString("mf", ApplyPathFiltering(region->mapped_file, - is_argument_filtering_enabled)); - -// The following stats are only well defined on Linux-derived OSes. -#if !defined(OS_MAC) && !defined(OS_WIN) - value->BeginDictionary("bs"); // byte stats - value->SetString( - "pss", - base::StringPrintf(kHexFmt, region->byte_stats_proportional_resident)); - value->SetString( - "pd", - base::StringPrintf(kHexFmt, region->byte_stats_private_dirty_resident)); - value->SetString( - "pc", - base::StringPrintf(kHexFmt, region->byte_stats_private_clean_resident)); - value->SetString( - "sd", - base::StringPrintf(kHexFmt, region->byte_stats_shared_dirty_resident)); - value->SetString( - "sc", - base::StringPrintf(kHexFmt, region->byte_stats_shared_clean_resident)); - value->SetString("sw", - base::StringPrintf(kHexFmt, region->byte_stats_swapped)); - value->EndDictionary(); -#endif - - value->EndDictionary(); + if (is_argument_filtering_enabled) { + base::FilePath::StringType path(file.begin(), file.end()); + return base::FilePath(path).BaseName().AsUTF8Unsafe(); } - value->EndArray(); + return file; } bool TracingObserver::IsDumpModeAllowed( diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h index dca47ff417e..5c42ff39972 100644 --- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h @@ -2,14 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H -#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H +#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H_ +#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H_ #include "base/component_export.h" #include "base/macros.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_event.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h" +#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h" namespace memory_instrumentation { @@ -27,27 +28,26 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) void OnTraceLogEnabled() override; void OnTraceLogDisabled() override; - bool AddChromeDumpToTraceIfEnabled( + virtual bool AddChromeDumpToTraceIfEnabled( const base::trace_event::MemoryDumpRequestArgs&, const base::ProcessId pid, - const base::trace_event::ProcessMemoryDump*); - bool AddOsDumpToTraceIfEnabled( - const base::trace_event::MemoryDumpRequestArgs&, - const base::ProcessId, - const mojom::OSMemDump*, - const std::vector<mojom::VmRegionPtr>*); + const base::trace_event::ProcessMemoryDump*, + const base::TimeTicks& timestamp); - static void MemoryMapsAsValueInto( + virtual bool AddOsDumpToTraceIfEnabled( + const base::trace_event::MemoryDumpRequestArgs& args, + const base::ProcessId pid, + const mojom::OSMemDump& os_dump, const std::vector<mojom::VmRegionPtr>& memory_maps, - base::trace_event::TracedValue* value, - bool is_argument_filtering_enabled); + const base::TimeTicks& timestamp); // TODO(lalitm): make these private again after TracingObserver is moved // to private space. bool ShouldAddToTrace(const base::trace_event::MemoryDumpRequestArgs&); - void AddToTrace(const base::trace_event::MemoryDumpRequestArgs&, - const base::ProcessId, - std::unique_ptr<base::trace_event::TracedValue>); + + protected: + static std::string ApplyPathFiltering(const std::string& file, + bool is_argument_filtering_enabled); private: // Returns true if the dump mode is allowed for current tracing session. @@ -63,4 +63,4 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) } // namespace memory_instrumentation -#endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H +#endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H_ diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.cc new file mode 100644 index 00000000000..daf8af853d3 --- /dev/null +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.cc @@ -0,0 +1,200 @@ +// 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 "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h" + +#include "base/files/file_path.h" +#include "base/format_macros.h" +#include "base/strings/stringprintf.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/traced_value.h" +#include "build/build_config.h" +#include "services/tracing/public/cpp/perfetto/perfetto_producer.h" +#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" +#include "services/tracing/public/cpp/perfetto/trace_time.h" +#include "third_party/perfetto/protos/perfetto/trace/memory_graph.pbzero.h" +#include "third_party/perfetto/protos/perfetto/trace/profiling/smaps.pbzero.h" +#include "third_party/perfetto/protos/perfetto/trace/ps/process_stats.pbzero.h" +#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h" + +namespace memory_instrumentation { + +using base::trace_event::ProcessMemoryDump; + +namespace { + +void OsDumpAsProtoInto(perfetto::protos::pbzero::ProcessStats::Process* process, + const mojom::OSMemDump& os_dump) { + process->set_chrome_private_footprint_kb(os_dump.private_footprint_kb); + process->set_chrome_peak_resident_set_kb(os_dump.peak_resident_set_kb); + process->set_is_peak_rss_resettable(os_dump.is_peak_rss_resettable); +} + +perfetto::protos::pbzero::MemoryTrackerSnapshot::LevelOfDetail +MemoryDumpLevelOfDetailToProto( + const base::trace_event::MemoryDumpLevelOfDetail& level_of_detail) { + switch (level_of_detail) { + case base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND: + return perfetto::protos::pbzero::MemoryTrackerSnapshot::DETAIL_BACKGROUND; + case base::trace_event::MemoryDumpLevelOfDetail::LIGHT: + return perfetto::protos::pbzero::MemoryTrackerSnapshot::DETAIL_LIGHT; + case base::trace_event::MemoryDumpLevelOfDetail::DETAILED: + return perfetto::protos::pbzero::MemoryTrackerSnapshot::DETAIL_FULL; + } + NOTREACHED(); + return perfetto::protos::pbzero::MemoryTrackerSnapshot::DETAIL_BACKGROUND; +} + +} // namespace + +TracingObserverProto::TracingObserverProto( + base::trace_event::TraceLog* trace_log, + base::trace_event::MemoryDumpManager* memory_dump_manager) + : TracingObserver(trace_log, memory_dump_manager), + tracing::PerfettoTracedProcess::DataSourceBase( + tracing::mojom::kMemoryInstrumentationDataSourceName) { + tracing::PerfettoTracedProcess::Get()->AddDataSource(this); +} + +TracingObserverProto::~TracingObserverProto() = default; + +bool TracingObserverProto::AddChromeDumpToTraceIfEnabled( + const base::trace_event::MemoryDumpRequestArgs& args, + const base::ProcessId pid, + const ProcessMemoryDump* process_memory_dump, + const base::TimeTicks& timestamp) { + if (!ShouldAddToTrace(args)) + return false; + + base::AutoLock lock(producer_lock_); + + if (!trace_writer_) + return false; + + perfetto::TraceWriter::TracePacketHandle handle = + trace_writer_->NewTracePacket(); + handle->set_timestamp(timestamp.since_origin().InNanoseconds()); + handle->set_timestamp_clock_id(tracing::kTraceClockId); + perfetto::protos::pbzero::MemoryTrackerSnapshot* memory_snapshot = + handle->set_memory_tracker_snapshot(); + memory_snapshot->set_level_of_detail( + MemoryDumpLevelOfDetailToProto(args.level_of_detail)); + process_memory_dump->SerializeAllocatorDumpsInto(memory_snapshot, pid); + + return true; +} + +bool TracingObserverProto::AddOsDumpToTraceIfEnabled( + const base::trace_event::MemoryDumpRequestArgs& args, + const base::ProcessId pid, + const mojom::OSMemDump& os_dump, + const std::vector<mojom::VmRegionPtr>& memory_maps, + const base::TimeTicks& timestamp) { + if (!ShouldAddToTrace(args)) + return false; + + base::AutoLock lock(producer_lock_); + + if (!trace_writer_) + return false; + + perfetto::TraceWriter::TracePacketHandle process_stats_packet = + trace_writer_->NewTracePacket(); + process_stats_packet->set_timestamp(timestamp.since_origin().InNanoseconds()); + process_stats_packet->set_timestamp_clock_id(tracing::kTraceClockId); + perfetto::protos::pbzero::ProcessStats* process_stats = + process_stats_packet->set_process_stats(); + perfetto::protos::pbzero::ProcessStats::Process* process = + process_stats->add_processes(); + process->set_pid(static_cast<int>(pid)); + + OsDumpAsProtoInto(process, os_dump); + + process_stats_packet->Finalize(); + + if (memory_maps.size()) { + perfetto::TraceWriter::TracePacketHandle smaps_packet = + trace_writer_->NewTracePacket(); + smaps_packet->set_timestamp(timestamp.since_origin().InNanoseconds()); + smaps_packet->set_timestamp_clock_id(tracing::kTraceClockId); + perfetto::protos::pbzero::SmapsPacket* smaps = + smaps_packet->set_smaps_packet(); + + MemoryMapsAsProtoInto(memory_maps, smaps, false); + + smaps_packet->Finalize(); + } + + return true; +} + +void TracingObserverProto::StartTracing( + tracing::PerfettoProducer* producer, + const perfetto::DataSourceConfig& data_source_config) { + base::AutoLock lock(producer_lock_); + producer_ = producer; + // We rely on concurrent setup of TraceLog categories by the + // TraceEventDataSource so don't look at the trace config ourselves. + trace_writer_ = + producer->CreateTraceWriter(data_source_config.target_buffer()); +} + +void TracingObserverProto::StopTracing( + base::OnceClosure stop_complete_callback) { + // Scope to avoid reentrancy in case from the stop callback. + { + base::AutoLock lock(producer_lock_); + trace_writer_.reset(); + producer_ = nullptr; + } + + if (stop_complete_callback) { + std::move(stop_complete_callback).Run(); + } +} + +void TracingObserverProto::Flush( + base::RepeatingClosure flush_complete_callback) {} + +void TracingObserverProto::MemoryMapsAsProtoInto( + const std::vector<mojom::VmRegionPtr>& memory_maps, + perfetto::protos::pbzero::SmapsPacket* smaps, + bool is_argument_filtering_enabled) { + for (const auto& region : memory_maps) { + perfetto::protos::pbzero::SmapsEntry* entry = smaps->add_entries(); + + entry->set_start_address(region->start_address); + entry->set_size_kb(region->size_in_bytes / 1024); + + if (region->module_timestamp) + entry->set_module_timestamp(region->module_timestamp); + if (!region->module_debugid.empty()) + entry->set_module_debugid(region->module_debugid); + if (!region->module_debug_path.empty()) { + entry->set_module_debug_path(ApplyPathFiltering( + region->module_debug_path, is_argument_filtering_enabled)); + } + entry->set_protection_flags(region->protection_flags); + + entry->set_file_name( + ApplyPathFiltering(region->mapped_file, is_argument_filtering_enabled)); + +// The following stats are only well defined on Linux-derived OSes. +#if !defined(OS_MAC) && !defined(OS_WIN) + entry->set_proportional_resident_kb( + region->byte_stats_proportional_resident / 1024); + entry->set_private_dirty_kb(region->byte_stats_private_dirty_resident / + 1024); + entry->set_private_clean_resident_kb( + region->byte_stats_private_clean_resident / 1024); + entry->set_shared_dirty_resident_kb( + region->byte_stats_shared_dirty_resident / 1024); + entry->set_shared_clean_resident_kb( + region->byte_stats_shared_clean_resident / 1024); + entry->set_swap_kb(region->byte_stats_swapped / 1024); +#endif + } +} + +} // namespace memory_instrumentation diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h new file mode 100644 index 00000000000..ac0a3263b52 --- /dev/null +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h @@ -0,0 +1,73 @@ +// 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 SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_PROTO_H_ +#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_PROTO_H_ + +#include "base/component_export.h" +#include "base/macros.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/trace_event.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h" +#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h" +#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" +#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h" + +namespace perfetto { +namespace protos { +namespace pbzero { +class SmapsPacket; +} +} // namespace protos +} // namespace perfetto + +namespace memory_instrumentation { + +// Version of TracingObserver that serializes the dump into a proto TracePacket. +class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) + TracingObserverProto + : public TracingObserver, + public tracing::PerfettoTracedProcess::DataSourceBase { + public: + TracingObserverProto(base::trace_event::TraceLog*, + base::trace_event::MemoryDumpManager*); + ~TracingObserverProto() override; + + bool AddChromeDumpToTraceIfEnabled( + const base::trace_event::MemoryDumpRequestArgs&, + const base::ProcessId pid, + const base::trace_event::ProcessMemoryDump*, + const base::TimeTicks& timestamp) override; + bool AddOsDumpToTraceIfEnabled( + const base::trace_event::MemoryDumpRequestArgs&, + const base::ProcessId, + const mojom::OSMemDump&, + const std::vector<mojom::VmRegionPtr>&, + const base::TimeTicks& timestamp) override; + + void StartTracing( + tracing::PerfettoProducer* producer, + const perfetto::DataSourceConfig& data_source_config) override; + + void StopTracing( + base::OnceClosure stop_complete_callback = base::OnceClosure()) override; + + void Flush(base::RepeatingClosure flush_complete_callback) override; + + static void MemoryMapsAsProtoInto( + const std::vector<mojom::VmRegionPtr>& memory_maps, + perfetto::protos::pbzero::SmapsPacket* smaps, + bool is_argument_filtering_enabled); + + private: + std::unique_ptr<perfetto::TraceWriter> trace_writer_; + + base::Lock producer_lock_; + + DISALLOW_COPY_AND_ASSIGN(TracingObserverProto); +}; + +} // namespace memory_instrumentation + +#endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_PROTO_H_ diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto_unittest.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto_unittest.cc new file mode 100644 index 00000000000..33078471d85 --- /dev/null +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto_unittest.cc @@ -0,0 +1,462 @@ +// 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 "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h" + +#include <map> +#include <memory> +#include <set> +#include <utility> +#include <vector> + +#include "base/files/file_path.h" +#include "base/format_macros.h" +#include "base/strings/stringprintf.h" +#include "base/test/task_environment.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/traced_value.h" +#include "build/build_config.h" +#include "services/tracing/public/cpp/perfetto/perfetto_producer.h" +#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" +#include "services/tracing/public/cpp/perfetto/producer_test_utils.h" +#include "services/tracing/public/cpp/perfetto/trace_time.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/perfetto/protos/perfetto/trace/memory_graph.pbzero.h" +#include "third_party/perfetto/protos/perfetto/trace/profiling/smaps.pbzero.h" +#include "third_party/perfetto/protos/perfetto/trace/ps/process_stats.pbzero.h" +#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h" + +using TrackEvent = perfetto::protos::pbzero::TrackEvent; +using MemoryTrackerSnapshot = perfetto::protos::MemoryTrackerSnapshot; + +namespace tracing { + +namespace { + +class TracingObserverProtoTest : public testing::Test { + public: + void SetUp() override { + auto perfetto_wrapper = std::make_unique<PerfettoTaskRunner>( + task_environment_.GetMainThreadTaskRunner()); + producer_client_ = + std::make_unique<TestProducerClient>(std::move(perfetto_wrapper)); + } + + void TearDown() override { producer_client_.reset(); } + + TestProducerClient* GetProducerClient() { return producer_client_.get(); } + + void EnableTraceLog() { + base::trace_event::TraceLog::GetInstance()->SetEnabled( + base::trace_event::TraceConfig( + base::trace_event::MemoryDumpManager::kTraceCategory, ""), + base::trace_event::TraceLog::RECORDING_MODE); + } + + void DisableTraceLog() { + base::trace_event::TraceLog::GetInstance()->SetDisabled(); + } + + base::trace_event::MemoryDumpRequestArgs FillMemoryDumpRequestArgs() { + base::trace_event::MemoryDumpRequestArgs args; + args.dump_guid = 1; + args.dump_type = base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED; + args.level_of_detail = base::trace_event::MemoryDumpLevelOfDetail::DETAILED; + args.determinism = base::trace_event::MemoryDumpDeterminism::FORCE_GC; + + return args; + } + + base::trace_event::ProcessMemoryDump FillSamplePmd() { + base::trace_event::MemoryDumpArgs dump_args = { + base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; + base::trace_event::ProcessMemoryDump pmd = + base::trace_event::ProcessMemoryDump(dump_args); + pmd.CreateAllocatorDump("mad1", + base::trace_event::MemoryAllocatorDumpGuid(421)); + pmd.CreateAllocatorDump("mad2", + base::trace_event::MemoryAllocatorDumpGuid(422)); + pmd.CreateAllocatorDump("mad3", + base::trace_event::MemoryAllocatorDumpGuid(423)); + pmd.AddOwnershipEdge(base::trace_event::MemoryAllocatorDumpGuid(421), + base::trace_event::MemoryAllocatorDumpGuid(422)); + pmd.AddOwnershipEdge(base::trace_event::MemoryAllocatorDumpGuid(422), + base::trace_event::MemoryAllocatorDumpGuid(423)); + + return pmd; + } + + protected: + base::test::TaskEnvironment task_environment_; + + std::unique_ptr<TestProducerClient> producer_client_; +}; + +const base::ProcessId kTestPid = 1; +const int kRegionsCount = 3; + +const uint32_t kResidentSetKb = 1; +const uint32_t kPrivateFootprintKb = 2; +const uint32_t kSharedFootprintKb = 3; + +const base::TimeTicks kTimestamp = + base::TimeTicks() + base::TimeDelta::FromMicroseconds(100000); +const uint64_t kTimestampProto = kTimestamp.since_origin().InNanoseconds(); + +uint64_t GetFakeAddrForVmRegion(int pid, int region_index) { + return 0x100000ul * pid * (region_index + 1); +} + +uint64_t GetFakeSizeForVmRegion(int pid, int region_index) { + return 4096 * pid * (region_index + 1); +} + +std::vector<memory_instrumentation::mojom::VmRegionPtr> FillMemoryMap(int pid) { + std::vector<memory_instrumentation::mojom::VmRegionPtr> memory_map; + + for (int i = 0; i < kRegionsCount; i++) { + memory_instrumentation::mojom::VmRegionPtr vm_region = + memory_instrumentation::mojom::VmRegion::New(); + vm_region->start_address = GetFakeAddrForVmRegion(pid, i); + vm_region->size_in_bytes = GetFakeSizeForVmRegion(pid, i); + memory_map.push_back(std::move(vm_region)); + } + return memory_map; +} + +memory_instrumentation::mojom::OSMemDump GetFakeOSMemDump( + uint32_t resident_set_kb, + uint32_t private_footprint_kb, + uint32_t shared_footprint_kb) { + return memory_instrumentation::mojom::OSMemDump( + resident_set_kb, /*peak_resident_set_kb=*/resident_set_kb, + /*is_peak_rss_resettable=*/true, private_footprint_kb, shared_footprint_kb +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) + , + 0 +#endif + ); +} + +TEST_F(TracingObserverProtoTest, + AddChromeDumpToTraceIfEnabled_When_TraceLog_Disabled) { + auto tracing_observer = + std::make_unique<memory_instrumentation::TracingObserverProto>( + base::trace_event::TraceLog::GetInstance(), nullptr); + + perfetto::DataSourceConfig config; + tracing_observer->StartTracing(GetProducerClient(), config); + + DisableTraceLog(); + + base::trace_event::MemoryDumpRequestArgs args = FillMemoryDumpRequestArgs(); + + base::trace_event::ProcessMemoryDump pmd = FillSamplePmd(); + + EXPECT_FALSE(tracing_observer->AddChromeDumpToTraceIfEnabled( + args, kTestPid, &pmd, kTimestamp)); + + EnableTraceLog(); + + EXPECT_TRUE(tracing_observer->AddChromeDumpToTraceIfEnabled( + args, kTestPid, &pmd, kTimestamp)); + + tracing_observer->StopTracing(); +} + +TEST_F(TracingObserverProtoTest, + AddChromeDumpToTraceIfEnabled_When_Before_StartTracing) { + auto tracing_observer = + std::make_unique<memory_instrumentation::TracingObserverProto>( + base::trace_event::TraceLog::GetInstance(), nullptr); + + EnableTraceLog(); + + base::trace_event::MemoryDumpRequestArgs args = FillMemoryDumpRequestArgs(); + + base::trace_event::ProcessMemoryDump pmd = FillSamplePmd(); + + EXPECT_FALSE(tracing_observer->AddChromeDumpToTraceIfEnabled( + args, kTestPid, &pmd, kTimestamp)); + + perfetto::DataSourceConfig config; + tracing_observer->StartTracing(GetProducerClient(), config); + + EXPECT_TRUE(tracing_observer->AddChromeDumpToTraceIfEnabled( + args, kTestPid, &pmd, kTimestamp)); + + tracing_observer->StopTracing(); +} + +TEST_F(TracingObserverProtoTest, + AddOsDumpToTraceIfEnabled_When_TraceLog_Disabled) { + auto tracing_observer = + std::make_unique<memory_instrumentation::TracingObserverProto>( + base::trace_event::TraceLog::GetInstance(), nullptr); + + perfetto::DataSourceConfig config; + tracing_observer->StartTracing(GetProducerClient(), config); + + DisableTraceLog(); + + base::trace_event::MemoryDumpRequestArgs args = FillMemoryDumpRequestArgs(); + + memory_instrumentation::mojom::OSMemDump os_dump = GetFakeOSMemDump(1, 1, 1); + + std::vector<memory_instrumentation::mojom::VmRegionPtr> memory_map = + FillMemoryMap(kTestPid); + EXPECT_FALSE(tracing_observer->AddOsDumpToTraceIfEnabled( + args, kTestPid, os_dump, memory_map, kTimestamp)); + + EnableTraceLog(); + + EXPECT_TRUE(tracing_observer->AddOsDumpToTraceIfEnabled( + args, kTestPid, os_dump, memory_map, kTimestamp)); + + tracing_observer->StopTracing(); +} + +TEST_F(TracingObserverProtoTest, + AddOsDumpToTraceIfEnabled_Before_StartTracing) { + auto tracing_observer = + std::make_unique<memory_instrumentation::TracingObserverProto>( + base::trace_event::TraceLog::GetInstance(), nullptr); + + EnableTraceLog(); + + base::trace_event::MemoryDumpRequestArgs args = FillMemoryDumpRequestArgs(); + + memory_instrumentation::mojom::OSMemDump os_dump = GetFakeOSMemDump(1, 1, 1); + + std::vector<memory_instrumentation::mojom::VmRegionPtr> memory_map = + FillMemoryMap(kTestPid); + EXPECT_FALSE(tracing_observer->AddOsDumpToTraceIfEnabled( + args, kTestPid, os_dump, memory_map, kTimestamp)); + + perfetto::DataSourceConfig config; + tracing_observer->StartTracing(GetProducerClient(), config); + + EXPECT_TRUE(tracing_observer->AddOsDumpToTraceIfEnabled( + args, kTestPid, os_dump, memory_map, kTimestamp)); + + tracing_observer->StopTracing(); +} + +TEST_F(TracingObserverProtoTest, AddChromeDumpToTraceIfEnabled) { + auto tracing_observer = + std::make_unique<memory_instrumentation::TracingObserverProto>( + base::trace_event::TraceLog::GetInstance(), nullptr); + + perfetto::DataSourceConfig config; + tracing_observer->StartTracing(GetProducerClient(), config); + + EnableTraceLog(); + + base::trace_event::MemoryDumpRequestArgs args = FillMemoryDumpRequestArgs(); + + base::trace_event::ProcessMemoryDump pmd = FillSamplePmd(); + + EXPECT_TRUE(tracing_observer->AddChromeDumpToTraceIfEnabled( + args, kTestPid, &pmd, kTimestamp)); + + ASSERT_EQ(1ul, GetProducerClient()->GetFinalizedPacketCount()); + + const perfetto::protos::TracePacket* packet = + GetProducerClient()->GetFinalizedPacket(0); + ASSERT_NE(nullptr, packet); + EXPECT_TRUE(packet->has_timestamp()); + EXPECT_EQ(kTimestampProto, packet->timestamp()); + EXPECT_TRUE(packet->has_timestamp_clock_id()); + EXPECT_EQ(static_cast<uint32_t>(kTraceClockId), packet->timestamp_clock_id()); + EXPECT_TRUE(packet->has_memory_tracker_snapshot()); + + const MemoryTrackerSnapshot& snapshot = packet->memory_tracker_snapshot(); + EXPECT_TRUE(snapshot.has_level_of_detail()); + EXPECT_EQ(MemoryTrackerSnapshot::DETAIL_FULL, snapshot.level_of_detail()); + EXPECT_EQ(1, snapshot.process_memory_dumps_size()); + + const MemoryTrackerSnapshot::ProcessSnapshot& process_memory_dump = + snapshot.process_memory_dumps(0); + EXPECT_EQ(3, process_memory_dump.allocator_dumps_size()); + + EXPECT_TRUE(process_memory_dump.has_pid()); + EXPECT_EQ(static_cast<int>(kTestPid), process_memory_dump.pid()); + + const MemoryTrackerSnapshot::ProcessSnapshot::MemoryNode& dump0 = + process_memory_dump.allocator_dumps(0); + EXPECT_EQ("mad1", dump0.absolute_name()); + const MemoryTrackerSnapshot::ProcessSnapshot::MemoryNode& dump1 = + process_memory_dump.allocator_dumps(1); + EXPECT_EQ("mad2", dump1.absolute_name()); + const MemoryTrackerSnapshot::ProcessSnapshot::MemoryNode& dump2 = + process_memory_dump.allocator_dumps(2); + EXPECT_EQ("mad3", dump2.absolute_name()); + + EXPECT_EQ(2, process_memory_dump.memory_edges_size()); + + const MemoryTrackerSnapshot::ProcessSnapshot::MemoryEdge& edge0 = + process_memory_dump.memory_edges(0); + EXPECT_EQ(421ul, edge0.source_id()); + EXPECT_EQ(422ul, edge0.target_id()); + + const MemoryTrackerSnapshot::ProcessSnapshot::MemoryEdge& edge1 = + process_memory_dump.memory_edges(1); + EXPECT_EQ(422ul, edge1.source_id()); + EXPECT_EQ(423ul, edge1.target_id()); + + tracing_observer->StopTracing(); +} + +TEST_F(TracingObserverProtoTest, AddOsDumpToTraceIfEnabled) { + auto tracing_observer = + std::make_unique<memory_instrumentation::TracingObserverProto>( + base::trace_event::TraceLog::GetInstance(), nullptr); + + perfetto::DataSourceConfig config; + tracing_observer->StartTracing(GetProducerClient(), config); + + EnableTraceLog(); + + base::trace_event::MemoryDumpRequestArgs args = FillMemoryDumpRequestArgs(); + + memory_instrumentation::mojom::OSMemDump os_dump = + GetFakeOSMemDump(kResidentSetKb, kPrivateFootprintKb, kSharedFootprintKb); + + std::vector<memory_instrumentation::mojom::VmRegionPtr> memory_map = + FillMemoryMap(kTestPid); + EXPECT_TRUE(tracing_observer->AddOsDumpToTraceIfEnabled( + args, kTestPid, os_dump, memory_map, kTimestamp)); + + EXPECT_EQ(2ul, GetProducerClient()->GetFinalizedPacketCount()); + + const perfetto::protos::TracePacket* process_stats_trace_packet = + GetProducerClient()->GetFinalizedPacket(0); + ASSERT_NE(nullptr, process_stats_trace_packet); + EXPECT_TRUE(process_stats_trace_packet->has_timestamp()); + EXPECT_EQ(kTimestampProto, process_stats_trace_packet->timestamp()); + EXPECT_TRUE(process_stats_trace_packet->has_timestamp_clock_id()); + EXPECT_EQ(static_cast<uint32_t>(kTraceClockId), + process_stats_trace_packet->timestamp_clock_id()); + EXPECT_TRUE(process_stats_trace_packet->has_process_stats()); + + const ::perfetto::protos::ProcessStats& process_stats = + process_stats_trace_packet->process_stats(); + EXPECT_EQ(1, process_stats.processes_size()); + + const ::perfetto::protos::ProcessStats::Process& process = + process_stats.processes(0); + + EXPECT_TRUE(process.has_pid()); + EXPECT_EQ(static_cast<int>(kTestPid), process.pid()); + + EXPECT_TRUE(process.has_chrome_private_footprint_kb()); + EXPECT_EQ(kPrivateFootprintKb, process.chrome_private_footprint_kb()); + + EXPECT_TRUE(process.has_chrome_peak_resident_set_kb()); + EXPECT_EQ(kResidentSetKb, process.chrome_peak_resident_set_kb()); + + EXPECT_TRUE(process.has_is_peak_rss_resettable()); + EXPECT_TRUE(process.is_peak_rss_resettable()); + + const perfetto::protos::TracePacket* smaps_trace_packet = + GetProducerClient()->GetFinalizedPacket(1); + + EXPECT_TRUE(smaps_trace_packet->has_smaps_packet()); + const ::perfetto::protos::SmapsPacket& smaps_packet = + smaps_trace_packet->smaps_packet(); + + EXPECT_EQ(kRegionsCount, smaps_packet.entries_size()); + + for (int i = 0; i < kRegionsCount; i++) { + const ::perfetto::protos::SmapsEntry& entry = smaps_packet.entries(i); + + uint64_t start_address = GetFakeAddrForVmRegion(kTestPid, i); + EXPECT_EQ(start_address, entry.start_address()); + + uint64_t size_kb = GetFakeSizeForVmRegion(kTestPid, i) / 1024; + EXPECT_EQ(size_kb, entry.size_kb()); + } + + tracing_observer->StopTracing(); +} + +TEST_F(TracingObserverProtoTest, AsProtoInto) { + perfetto::DataSourceConfig config; + std::unique_ptr<perfetto::TraceWriter> trace_writer = + GetProducerClient()->CreateTraceWriter(config.target_buffer()); + + base::trace_event::MemoryDumpArgs dump_args = { + base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; + base::trace_event::ProcessMemoryDump pmd = + base::trace_event::ProcessMemoryDump(dump_args); + + using MemoryAllocatorDump = base::trace_event::MemoryAllocatorDump; + + MemoryAllocatorDump* dump = pmd.CreateAllocatorDump( + "mad1", base::trace_event::MemoryAllocatorDumpGuid(421)); + dump->AddScalar("size", MemoryAllocatorDump::kUnitsBytes, 10); + dump->AddScalar("one", MemoryAllocatorDump::kUnitsBytes, 1); + dump->AddString("two", MemoryAllocatorDump::kUnitsObjects, "one"); + + perfetto::TraceWriter::TracePacketHandle handle = + trace_writer->NewTracePacket(); + perfetto::protos::pbzero::MemoryTrackerSnapshot* memory_snapshot = + handle->set_memory_tracker_snapshot(); + perfetto::protos::pbzero::MemoryTrackerSnapshot::ProcessSnapshot* + process_snapshot = memory_snapshot->add_process_memory_dumps(); + perfetto::protos::pbzero::MemoryTrackerSnapshot::ProcessSnapshot::MemoryNode* + memory_node = process_snapshot->add_allocator_dumps(); + + dump->AsProtoInto(memory_node); + handle->Finalize(); + + EXPECT_EQ(1ul, GetProducerClient()->GetFinalizedPacketCount()); + + const perfetto::protos::TracePacket* packet = + GetProducerClient()->GetFinalizedPacket(0); + ASSERT_NE(nullptr, packet); + EXPECT_TRUE(packet->has_memory_tracker_snapshot()); + + const MemoryTrackerSnapshot& snapshot = packet->memory_tracker_snapshot(); + const MemoryTrackerSnapshot::ProcessSnapshot& process_memory_dump = + snapshot.process_memory_dumps(0); + EXPECT_EQ(1, process_memory_dump.allocator_dumps_size()); + + const MemoryTrackerSnapshot::ProcessSnapshot::MemoryNode& dump0 = + process_memory_dump.allocator_dumps(0); + EXPECT_TRUE(dump0.has_absolute_name()); + EXPECT_EQ("mad1", dump0.absolute_name()); + EXPECT_TRUE(dump0.has_id()); + EXPECT_EQ(421ul, dump0.id()); + EXPECT_TRUE(dump0.has_size_bytes()); + EXPECT_EQ(10ul, dump0.size_bytes()); + EXPECT_EQ(2, dump0.entries_size()); + + const MemoryTrackerSnapshot::ProcessSnapshot::MemoryNode::MemoryNodeEntry& + entry0 = dump0.entries(0); + const MemoryTrackerSnapshot::ProcessSnapshot::MemoryNode::MemoryNodeEntry& + entry1 = dump0.entries(1); + + EXPECT_TRUE(entry0.has_name()); + EXPECT_EQ("one", entry0.name()); + EXPECT_TRUE(entry0.has_units()); + EXPECT_EQ(MemoryTrackerSnapshot::ProcessSnapshot::MemoryNode:: + MemoryNodeEntry::BYTES, + entry0.units()); + EXPECT_TRUE(entry0.has_value_uint64()); + EXPECT_EQ(1ul, entry0.value_uint64()); + + EXPECT_TRUE(entry1.has_name()); + EXPECT_EQ("two", entry1.name()); + EXPECT_TRUE(entry0.has_units()); + EXPECT_EQ(MemoryTrackerSnapshot::ProcessSnapshot::MemoryNode:: + MemoryNodeEntry::COUNT, + entry1.units()); + EXPECT_TRUE(entry1.has_value_string()); + EXPECT_EQ("one", entry1.value_string()); +} + +} // namespace + +} // namespace tracing diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.cc new file mode 100644 index 00000000000..402bb5020c0 --- /dev/null +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.cc @@ -0,0 +1,168 @@ +// 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 "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h" + +#include "base/files/file_path.h" +#include "base/format_macros.h" +#include "base/strings/stringprintf.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/traced_value.h" +#include "build/build_config.h" + +namespace memory_instrumentation { + +using base::trace_event::ProcessMemoryDump; +using base::trace_event::TracedValue; + +namespace { + +void OsDumpAsValueInto(TracedValue* value, const mojom::OSMemDump& os_dump) { + value->SetString( + "private_footprint_bytes", + base::StringPrintf( + "%" PRIx64, + static_cast<uint64_t>(os_dump.private_footprint_kb) * 1024)); + value->SetString( + "peak_resident_set_size", + base::StringPrintf( + "%" PRIx64, + static_cast<uint64_t>(os_dump.peak_resident_set_kb) * 1024)); + value->SetBoolean("is_peak_rss_resettable", os_dump.is_peak_rss_resettable); +} + +} // namespace + +TracingObserverTracedValue::TracingObserverTracedValue( + base::trace_event::TraceLog* trace_log, + base::trace_event::MemoryDumpManager* memory_dump_manager) + : TracingObserver(trace_log, memory_dump_manager) {} + +TracingObserverTracedValue::~TracingObserverTracedValue() = default; + +// static +void TracingObserverTracedValue::AddToTrace( + const base::trace_event::MemoryDumpRequestArgs& args, + const base::ProcessId pid, + std::unique_ptr<TracedValue> traced_value) { + CHECK_NE(base::trace_event::MemoryDumpType::SUMMARY_ONLY, args.dump_type); + + traced_value->SetString( + "level_of_detail", + base::trace_event::MemoryDumpLevelOfDetailToString(args.level_of_detail)); + const uint64_t dump_guid = args.dump_guid; + const char* const event_name = + base::trace_event::MemoryDumpTypeToString(args.dump_type); + base::trace_event::TraceArguments trace_args("dumps", + std::move(traced_value)); + TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID( + TRACE_EVENT_PHASE_MEMORY_DUMP, + base::trace_event::TraceLog::GetCategoryGroupEnabled( + base::trace_event::MemoryDumpManager::kTraceCategory), + event_name, trace_event_internal::kGlobalScope, dump_guid, pid, + &trace_args, TRACE_EVENT_FLAG_HAS_ID); +} + +bool TracingObserverTracedValue::AddChromeDumpToTraceIfEnabled( + const base::trace_event::MemoryDumpRequestArgs& args, + const base::ProcessId pid, + const ProcessMemoryDump* process_memory_dump, + const base::TimeTicks& timastamp) { + if (!ShouldAddToTrace(args)) + return false; + + std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>(); + process_memory_dump->SerializeAllocatorDumpsInto(traced_value.get()); + + AddToTrace(args, pid, std::move(traced_value)); + + return true; +} + +bool TracingObserverTracedValue::AddOsDumpToTraceIfEnabled( + const base::trace_event::MemoryDumpRequestArgs& args, + const base::ProcessId pid, + const mojom::OSMemDump& os_dump, + const std::vector<mojom::VmRegionPtr>& memory_maps, + const base::TimeTicks& timestamp) { + if (!ShouldAddToTrace(args)) + return false; + + std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>(); + + traced_value->BeginDictionary("process_totals"); + OsDumpAsValueInto(traced_value.get(), os_dump); + traced_value->EndDictionary(); + + if (memory_maps.size()) { + traced_value->BeginDictionary("process_mmaps"); + MemoryMapsAsValueInto(memory_maps, traced_value.get(), false); + traced_value->EndDictionary(); + } + + AddToTrace(args, pid, std::move(traced_value)); + return true; +} + +// static +void TracingObserverTracedValue::MemoryMapsAsValueInto( + const std::vector<mojom::VmRegionPtr>& memory_maps, + TracedValue* value, + bool is_argument_filtering_enabled) { + static const char kHexFmt[] = "%" PRIx64; + + // Refer to the design doc goo.gl/sxfFY8 for the semantics of these fields. + value->BeginArray("vm_regions"); + for (const auto& region : memory_maps) { + value->BeginDictionary(); + + value->SetString("sa", base::StringPrintf(kHexFmt, region->start_address)); + value->SetString("sz", base::StringPrintf(kHexFmt, region->size_in_bytes)); + if (region->module_timestamp) + value->SetString("ts", + base::StringPrintf(kHexFmt, region->module_timestamp)); + if (!region->module_debugid.empty()) + value->SetString("id", region->module_debugid); + if (!region->module_debug_path.empty()) { + value->SetString("df", ApplyPathFiltering(region->module_debug_path, + is_argument_filtering_enabled)); + } + value->SetInteger("pf", region->protection_flags); + + // The module path will be the basename when argument filtering is + // activated. The whitelisting implemented for filtering string values + // doesn't allow rewriting. Therefore, a different path is produced here + // when argument filtering is activated. + value->SetString("mf", ApplyPathFiltering(region->mapped_file, + is_argument_filtering_enabled)); + +// The following stats are only well defined on Linux-derived OSes. +#if !defined(OS_MAC) && !defined(OS_WIN) + value->BeginDictionary("bs"); // byte stats + value->SetString( + "pss", + base::StringPrintf(kHexFmt, region->byte_stats_proportional_resident)); + value->SetString( + "pd", + base::StringPrintf(kHexFmt, region->byte_stats_private_dirty_resident)); + value->SetString( + "pc", + base::StringPrintf(kHexFmt, region->byte_stats_private_clean_resident)); + value->SetString( + "sd", + base::StringPrintf(kHexFmt, region->byte_stats_shared_dirty_resident)); + value->SetString( + "sc", + base::StringPrintf(kHexFmt, region->byte_stats_shared_clean_resident)); + value->SetString("sw", + base::StringPrintf(kHexFmt, region->byte_stats_swapped)); + value->EndDictionary(); +#endif + + value->EndDictionary(); + } + value->EndArray(); +} + +} // namespace memory_instrumentation diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h new file mode 100644 index 00000000000..155c8ae3541 --- /dev/null +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h @@ -0,0 +1,51 @@ +// 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 SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_TRACED_VALUE_H_ +#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_TRACED_VALUE_H_ + +#include "base/component_export.h" +#include "base/macros.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/trace_event.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h" +#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h" + +namespace memory_instrumentation { + +// Version of TracingObserver that serialized the dump into a TracedValue +class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) + TracingObserverTracedValue : public TracingObserver { + public: + TracingObserverTracedValue(base::trace_event::TraceLog*, + base::trace_event::MemoryDumpManager*); + ~TracingObserverTracedValue() override; + + bool AddChromeDumpToTraceIfEnabled( + const base::trace_event::MemoryDumpRequestArgs&, + const base::ProcessId pid, + const base::trace_event::ProcessMemoryDump*, + const base::TimeTicks& timestamp) override; + bool AddOsDumpToTraceIfEnabled( + const base::trace_event::MemoryDumpRequestArgs&, + const base::ProcessId, + const mojom::OSMemDump&, + const std::vector<mojom::VmRegionPtr>&, + const base::TimeTicks& timastamp) override; + + static void MemoryMapsAsValueInto( + const std::vector<mojom::VmRegionPtr>& memory_maps, + base::trace_event::TracedValue* value, + bool is_argument_filtering_enabled); + + static void AddToTrace(const base::trace_event::MemoryDumpRequestArgs&, + const base::ProcessId, + std::unique_ptr<base::trace_event::TracedValue>); + + DISALLOW_COPY_AND_ASSIGN(TracingObserverTracedValue); +}; + +} // namespace memory_instrumentation + +#endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_TRACED_VALUE_H_ diff --git a/chromium/services/service_manager/BUILD.gn b/chromium/services/service_manager/BUILD.gn index 7de1fb1d77f..51ca59e213a 100644 --- a/chromium/services/service_manager/BUILD.gn +++ b/chromium/services/service_manager/BUILD.gn @@ -40,6 +40,7 @@ source_set("service_manager") { deps = [ "//base/third_party/dynamic_annotations", + "//build:chromeos_buildflags", "//components/services/filesystem:lib", "//components/services/filesystem/public/mojom", "//ui/base", diff --git a/chromium/services/service_manager/OWNERS b/chromium/services/service_manager/OWNERS index db7d7c4349d..fd5952b559b 100644 --- a/chromium/services/service_manager/OWNERS +++ b/chromium/services/service_manager/OWNERS @@ -1,5 +1,3 @@ jam@chromium.org rockot@google.com sky@chromium.org - -# COMPONENT: Internals>Services diff --git a/chromium/services/service_manager/background_service_manager.cc b/chromium/services/service_manager/background_service_manager.cc index 84f74ef3d03..22656514c8d 100644 --- a/chromium/services/service_manager/background_service_manager.cc +++ b/chromium/services/service_manager/background_service_manager.cc @@ -5,7 +5,7 @@ #include "services/service_manager/background_service_manager.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/check.h" #include "base/command_line.h" #include "base/memory/ref_counted.h" diff --git a/chromium/services/service_manager/public/cpp/interface_provider.cc b/chromium/services/service_manager/public/cpp/interface_provider.cc index d46dcfcdd60..dd64443650f 100644 --- a/chromium/services/service_manager/public/cpp/interface_provider.cc +++ b/chromium/services/service_manager/public/cpp/interface_provider.cc @@ -8,15 +8,23 @@ namespace service_manager { -InterfaceProvider::InterfaceProvider() { - pending_receiver_ = interface_provider_.BindNewPipeAndPassReceiver(); +InterfaceProvider::InterfaceProvider( + scoped_refptr<base::SequencedTaskRunner> task_runner) + : pending_receiver_( + interface_provider_.BindNewPipeAndPassReceiver(task_runner)), + task_runner_(std::move(task_runner)) { + DCHECK(task_runner_); } InterfaceProvider::InterfaceProvider( - mojo::PendingRemote<mojom::InterfaceProvider> interface_provider) - : interface_provider_(std::move(interface_provider)) {} + mojo::PendingRemote<mojom::InterfaceProvider> interface_provider, + scoped_refptr<base::SequencedTaskRunner> task_runner) + : interface_provider_(std::move(interface_provider), task_runner), + task_runner_(std::move(task_runner)) { + DCHECK(task_runner_); +} -InterfaceProvider::~InterfaceProvider() {} +InterfaceProvider::~InterfaceProvider() = default; void InterfaceProvider::Close() { if (pending_receiver_) @@ -32,7 +40,7 @@ void InterfaceProvider::Bind( mojo::FusePipes(std::move(pending_receiver_), std::move(interface_provider)); } else { - interface_provider_.Bind(std::move(interface_provider)); + interface_provider_.Bind(std::move(interface_provider), task_runner_); } } diff --git a/chromium/services/service_manager/public/cpp/interface_provider.h b/chromium/services/service_manager/public/cpp/interface_provider.h index 9d65071c00c..496f37ca471 100644 --- a/chromium/services/service_manager/public/cpp/interface_provider.h +++ b/chromium/services/service_manager/public/cpp/interface_provider.h @@ -57,12 +57,16 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT InterfaceProvider { // Constructs an InterfaceProvider which is usable immediately despite not // being bound to any actual remote implementation. Must call Bind() // eventually in order for the provider to function properly. - InterfaceProvider(); + // The task_runner argument is used for mojo remote connection. + explicit InterfaceProvider( + scoped_refptr<base::SequencedTaskRunner> task_runner); // Constructs an InterfaceProvider which uses |interface_provider| to issue // remote interface requests. - explicit InterfaceProvider( - mojo::PendingRemote<mojom::InterfaceProvider> interface_provider); + // The task_runner argument is used for mojo remote connection. + InterfaceProvider( + mojo::PendingRemote<mojom::InterfaceProvider> interface_provider, + scoped_refptr<base::SequencedTaskRunner> task_runner); ~InterfaceProvider(); @@ -116,6 +120,7 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT InterfaceProvider { mojo::Remote<mojom::InterfaceProvider> interface_provider_; mojo::PendingReceiver<mojom::InterfaceProvider> pending_receiver_; + scoped_refptr<base::SequencedTaskRunner> task_runner_; // A callback to receive all GetInterface() requests in lieu of the // InterfaceProvider pipe. diff --git a/chromium/services/service_manager/public/cpp/standalone_connector_impl_unittest.cc b/chromium/services/service_manager/public/cpp/standalone_connector_impl_unittest.cc index 64c41918ee9..60eb9530b96 100644 --- a/chromium/services/service_manager/public/cpp/standalone_connector_impl_unittest.cc +++ b/chromium/services/service_manager/public/cpp/standalone_connector_impl_unittest.cc @@ -7,7 +7,7 @@ #include "base/macros.h" #include "base/optional.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "mojo/public/cpp/bindings/generic_pending_receiver.h" #include "mojo/public/cpp/bindings/remote.h" diff --git a/chromium/services/service_manager/service_manager.cc b/chromium/services/service_manager/service_manager.cc index df2a4200202..af7d55cd6a9 100644 --- a/chromium/services/service_manager/service_manager.cc +++ b/chromium/services/service_manager/service_manager.cc @@ -8,7 +8,7 @@ #include "base/base_paths.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/logging.h" diff --git a/chromium/services/service_manager/service_process_launcher.cc b/chromium/services/service_manager/service_process_launcher.cc index c424df90cea..6424ec69988 100644 --- a/chromium/services/service_manager/service_process_launcher.cc +++ b/chromium/services/service_manager/service_process_launcher.cc @@ -27,6 +27,7 @@ #include "base/task_runner_util.h" #include "base/threading/thread.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/interface_ptr_info.h" #include "mojo/public/cpp/platform/platform_channel.h" #include "mojo/public/cpp/system/core.h" @@ -247,7 +248,7 @@ base::ProcessId ServiceProcessLauncher::ProcessState::LaunchInBackground( return base::kNullProcessId; } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // Always log instead of DVLOG because knowing which pid maps to which // service is vital for interpreting crashes after-the-fact and Chrome OS // devices generally run release builds, even in development. diff --git a/chromium/services/service_manager/tests/BUILD.gn b/chromium/services/service_manager/tests/BUILD.gn index 4cef17398a9..01adf232e33 100644 --- a/chromium/services/service_manager/tests/BUILD.gn +++ b/chromium/services/service_manager/tests/BUILD.gn @@ -51,28 +51,6 @@ mojom("interfaces") { "background.test-mojom", "test_support.test-mojom", ] - - if (is_linux || is_chromeos) { - sources += [ "sandbox_status.test-mojom" ] - } -} - -if (is_linux || is_chromeos) { - source_set("sandbox_status_service") { - testonly = true - sources = [ - "sandbox_status_service.cc", - "sandbox_status_service.h", - ] - - deps = [ - ":interfaces", - "//base", - "//sandbox/policy", - "//services/service_manager/public/cpp", - "//services/service_manager/public/mojom", - ] - } } source_set("util") { diff --git a/chromium/services/shape_detection/BUILD.gn b/chromium/services/shape_detection/BUILD.gn index abce530ea58..8b6b3e147ff 100644 --- a/chromium/services/shape_detection/BUILD.gn +++ b/chromium/services/shape_detection/BUILD.gn @@ -2,15 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//testing/test.gni") -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - source_set("lib") { sources = [ "shape_detection_service.cc", @@ -54,6 +48,16 @@ source_set("lib") { "text_detection_impl_win.cc", "text_detection_impl_win.h", ] + } else if (is_ash && is_chrome_branded) { + sources += [ + "barcode_detection_impl_barhopper.cc", + "barcode_detection_impl_barhopper.h", + "barcode_detection_provider_barhopper.cc", + "barcode_detection_provider_barhopper.h", + "face_detection_provider_impl.cc", + "face_detection_provider_impl.h", + "text_detection_impl.cc", + ] } else { sources += [ "barcode_detection_provider_impl.cc", @@ -67,11 +71,17 @@ source_set("lib") { configs += [ "//build/config/compiler:wexit_time_destructors" ] deps = [ + "//build:branding_buildflags", + "//build:chromeos_buildflags", "//mojo/public/cpp/bindings", "//ui/gfx", "//ui/gfx/geometry", ] + if (is_ash && is_chrome_branded) { + deps += [ "//third_party/barhopper:barhopper" ] + } + public_deps = [ "//base", "//media/capture", @@ -114,6 +124,7 @@ if (is_android) { "//mojo/public/java/system:system_impl_java", "//services/shape_detection/public/mojom:mojom_java", "//skia/public/mojom:mojom_java", + "//third_party/android_deps:chromium_play_services_availability_java", "//ui/gfx/geometry/mojom:mojom_java", ] } @@ -121,21 +132,30 @@ if (is_android) { source_set("tests") { testonly = true - sources = [ - "barcode_detection_impl_mac_unittest.mm", - "barcode_detection_provider_mac_unittest.mm", - "face_detection_impl_mac_unittest.mm", - "face_detection_impl_win_unittest.cc", - "text_detection_impl_mac_unittest.mm", - "text_detection_impl_win_unittest.cc", - ] + sources = [] if (is_mac) { + sources += [ + "barcode_detection_impl_mac_unittest.mm", + "barcode_detection_provider_mac_unittest.mm", + "face_detection_impl_mac_unittest.mm", + "text_detection_impl_mac_unittest.mm", + ] frameworks = [ "CoreFoundation.framework", "CoreGraphics.framework", "QuartzCore.framework", ] } + if (is_win) { + sources += [ + "face_detection_impl_win_unittest.cc", + "text_detection_impl_win_unittest.cc", + ] + } + + if (is_ash && is_chrome_branded) { + sources += [ "barcode_detection_impl_barhopper_unittest.cc" ] + } deps = [ ":lib", @@ -149,8 +169,20 @@ source_set("tests") { "//ui/gl", ] data = [ + "//services/test/data/codabar.png", + "//services/test/data/code_39.png", + "//services/test/data/code_93.png", + "//services/test/data/code_128.png", + "//services/test/data/data_matrix.png", + "//services/test/data/ean_8.png", + "//services/test/data/ean_13.png", + "//services/test/data/itf.png", "//services/test/data/mona_lisa.jpg", + "//services/test/data/pdf417.png", + "//services/test/data/qr_code.png", "//services/test/data/text_detection.png", "//services/test/data/the_beatles.jpg", + "//services/test/data/upc_a.png", + "//services/test/data/upc_e.png", ] } diff --git a/chromium/services/shape_detection/DEPS b/chromium/services/shape_detection/DEPS index eda4b66e016..205187d75a8 100644 --- a/chromium/services/shape_detection/DEPS +++ b/chromium/services/shape_detection/DEPS @@ -3,5 +3,6 @@ include_rules = [ "+third_party/skia/include", "+ui/gfx/codec", "+ui/gfx/geometry/rect_f.h", - "+ui/gl/gl_switches.h" + "+ui/gl/gl_switches.h", + "+third_party/barhopper/barhopper", ] diff --git a/chromium/services/shape_detection/DIR_METADATA b/chromium/services/shape_detection/DIR_METADATA new file mode 100644 index 00000000000..88c96d75286 --- /dev/null +++ b/chromium/services/shape_detection/DIR_METADATA @@ -0,0 +1,12 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Blink>ShapeDetection" +} +team_email: "device-dev@chromium.org"
\ No newline at end of file diff --git a/chromium/services/shape_detection/OWNERS b/chromium/services/shape_detection/OWNERS index aee8252f683..47d63bcce6b 100644 --- a/chromium/services/shape_detection/OWNERS +++ b/chromium/services/shape_detection/OWNERS @@ -1,4 +1 @@ file://third_party/blink/renderer/modules/shapedetection/OWNERS - -# COMPONENT: Blink>ShapeDetection -# TEAM: device-dev@chromium.org diff --git a/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java b/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java index ca26cabe414..8c00055d9d0 100644 --- a/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java +++ b/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java @@ -81,9 +81,9 @@ public class FaceDetectionImplTest { Assert.assertEquals(1, results.length); Assert.assertEquals( api == DetectionProviderType.GMS_CORE ? 4 : 0, results[0].landmarks.length); - Assert.assertEquals(40.0, results[0].boundingBox.width, BOUNDING_BOX_SIZE_ERROR); - Assert.assertEquals(40.0, results[0].boundingBox.height, BOUNDING_BOX_SIZE_ERROR); - Assert.assertEquals(24.0, results[0].boundingBox.x, BOUNDING_BOX_POSITION_ERROR); + Assert.assertEquals(36.0, results[0].boundingBox.width, BOUNDING_BOX_SIZE_ERROR); + Assert.assertEquals(38.0, results[0].boundingBox.height, BOUNDING_BOX_SIZE_ERROR); + Assert.assertEquals(26.0, results[0].boundingBox.x, BOUNDING_BOX_POSITION_ERROR); Assert.assertEquals(20.0, results[0].boundingBox.y, BOUNDING_BOX_POSITION_ERROR); } @@ -117,9 +117,9 @@ public class FaceDetectionImplTest { FaceDetectionResult[] results = detect(mojoBitmap, true, DetectionProviderType.ANDROID); Assert.assertEquals(1, results.length); - Assert.assertEquals(40.0, results[0].boundingBox.width, BOUNDING_BOX_SIZE_ERROR); - Assert.assertEquals(40.0, results[0].boundingBox.height, BOUNDING_BOX_SIZE_ERROR); - Assert.assertEquals(24.0, results[0].boundingBox.x, BOUNDING_BOX_POSITION_ERROR); + Assert.assertEquals(36.0, results[0].boundingBox.width, BOUNDING_BOX_SIZE_ERROR); + Assert.assertEquals(38.0, results[0].boundingBox.height, BOUNDING_BOX_SIZE_ERROR); + Assert.assertEquals(26.0, results[0].boundingBox.x, BOUNDING_BOX_POSITION_ERROR); Assert.assertEquals(20.0, results[0].boundingBox.y, BOUNDING_BOX_POSITION_ERROR); } diff --git a/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/TestUtils.java b/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/TestUtils.java index fd8fea95a0d..afd00963bc1 100644 --- a/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/TestUtils.java +++ b/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/TestUtils.java @@ -10,11 +10,9 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; - import org.chromium.base.ContextUtils; import org.chromium.base.test.util.UrlUtils; +import org.chromium.gms.ChromiumPlayServicesAvailability; import org.chromium.skia.mojom.ColorType; import org.chromium.skia.mojom.ImageInfo; @@ -29,9 +27,8 @@ public class TestUtils { public static final boolean IS_GMS_CORE_SUPPORTED = isGmsCoreSupported(); private static boolean isGmsCoreSupported() { - return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable( - ContextUtils.getApplicationContext()) - == ConnectionResult.SUCCESS; + return ChromiumPlayServicesAvailability.isGooglePlayServicesAvailable( + ContextUtils.getApplicationContext()); } public static org.chromium.skia.mojom.Bitmap mojoBitmapFromBitmap(Bitmap bitmap) { diff --git a/chromium/services/shape_detection/barcode_detection_impl_barhopper.cc b/chromium/services/shape_detection/barcode_detection_impl_barhopper.cc new file mode 100644 index 00000000000..aa48a27bc5a --- /dev/null +++ b/chromium/services/shape_detection/barcode_detection_impl_barhopper.cc @@ -0,0 +1,193 @@ +// 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 "services/shape_detection/barcode_detection_impl_barhopper.h" + +#include <stdint.h> +#include <limits> +#include <memory> + +#include "base/logging.h" +#include "services/shape_detection/public/mojom/barcodedetection.mojom-shared.h" +#include "third_party/barhopper/barhopper/barcode.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/geometry/rect_f.h" + +namespace shape_detection { + +namespace { + +gfx::RectF CornerPointsToBoundingBox( + std::vector<barhopper::Point>& corner_points) { + float xmin = std::numeric_limits<float>::infinity(); + float ymin = std::numeric_limits<float>::infinity(); + float xmax = -std::numeric_limits<float>::infinity(); + float ymax = -std::numeric_limits<float>::infinity(); + for (auto& point : corner_points) { + xmin = std::min(xmin, point.x); + ymin = std::min(ymin, point.y); + xmax = std::max(xmax, point.x); + ymax = std::max(ymax, point.y); + } + return gfx::RectF(xmin, ymin, (xmax - xmin), (ymax - ymin)); +} + +mojom::BarcodeFormat BarhopperFormatToMojo(barhopper::BarcodeFormat format) { + switch (format) { + case barhopper::BarcodeFormat::AZTEC: + return mojom::BarcodeFormat::AZTEC; + case barhopper::BarcodeFormat::CODE_128: + return mojom::BarcodeFormat::CODE_128; + case barhopper::BarcodeFormat::CODE_39: + return mojom::BarcodeFormat::CODE_39; + case barhopper::BarcodeFormat::CODE_93: + return mojom::BarcodeFormat::CODE_93; + case barhopper::BarcodeFormat::CODABAR: + return mojom::BarcodeFormat::CODABAR; + case barhopper::BarcodeFormat::DATA_MATRIX: + return mojom::BarcodeFormat::DATA_MATRIX; + case barhopper::BarcodeFormat::EAN_13: + return mojom::BarcodeFormat::EAN_13; + case barhopper::BarcodeFormat::EAN_8: + return mojom::BarcodeFormat::EAN_8; + case barhopper::BarcodeFormat::ITF: + return mojom::BarcodeFormat::ITF; + case barhopper::BarcodeFormat::PDF417: + return mojom::BarcodeFormat::PDF417; + case barhopper::BarcodeFormat::QR_CODE: + return mojom::BarcodeFormat::QR_CODE; + case barhopper::BarcodeFormat::UPC_A: + return mojom::BarcodeFormat::UPC_A; + case barhopper::BarcodeFormat::UPC_E: + return mojom::BarcodeFormat::UPC_E; + case barhopper::BarcodeFormat::UNRECOGNIZED: + return mojom::BarcodeFormat::UNKNOWN; + default: + NOTREACHED() << "Invalid barcode format"; + return mojom::BarcodeFormat::UNKNOWN; + } +} + +barhopper::RecognitionOptions GetRecognitionOptions( + const shape_detection::mojom::BarcodeDetectorOptionsPtr& options) { + barhopper::RecognitionOptions recognition_options; + if (options->formats.empty()) { + recognition_options.barcode_formats = + barhopper::BarcodeFormat::AZTEC | barhopper::BarcodeFormat::CODE_128 | + barhopper::BarcodeFormat::CODE_39 | barhopper::BarcodeFormat::CODE_93 | + barhopper::BarcodeFormat::CODABAR | + barhopper::BarcodeFormat::DATA_MATRIX | + barhopper::BarcodeFormat::EAN_13 | barhopper::BarcodeFormat::EAN_8 | + barhopper::BarcodeFormat::ITF | barhopper::BarcodeFormat::PDF417 | + barhopper::BarcodeFormat::QR_CODE | barhopper::BarcodeFormat::UPC_A | + barhopper::BarcodeFormat::UPC_E; + return recognition_options; + } + + int recognition_formats = 0; + for (const auto& format : options->formats) { + switch (format) { + case mojom::BarcodeFormat::AZTEC: + recognition_formats |= barhopper::BarcodeFormat::AZTEC; + break; + case mojom::BarcodeFormat::CODE_128: + recognition_formats |= barhopper::BarcodeFormat::CODE_128; + break; + case mojom::BarcodeFormat::CODE_39: + recognition_formats |= barhopper::BarcodeFormat::CODE_39; + break; + case mojom::BarcodeFormat::CODE_93: + recognition_formats |= barhopper::BarcodeFormat::CODE_93; + break; + case mojom::BarcodeFormat::CODABAR: + recognition_formats |= barhopper::BarcodeFormat::CODABAR; + break; + case mojom::BarcodeFormat::DATA_MATRIX: + recognition_formats |= barhopper::BarcodeFormat::DATA_MATRIX; + break; + case mojom::BarcodeFormat::EAN_13: + recognition_formats |= barhopper::BarcodeFormat::EAN_13; + break; + case mojom::BarcodeFormat::EAN_8: + recognition_formats |= barhopper::BarcodeFormat::EAN_8; + break; + case mojom::BarcodeFormat::ITF: + recognition_formats |= barhopper::BarcodeFormat::ITF; + break; + case mojom::BarcodeFormat::PDF417: + recognition_formats |= barhopper::BarcodeFormat::PDF417; + break; + case mojom::BarcodeFormat::QR_CODE: + recognition_formats |= barhopper::BarcodeFormat::QR_CODE; + break; + case mojom::BarcodeFormat::UPC_E: + recognition_formats |= barhopper::BarcodeFormat::UPC_E; + break; + case mojom::BarcodeFormat::UPC_A: + recognition_formats |= barhopper::BarcodeFormat::UPC_A; + break; + case mojom::BarcodeFormat::UNKNOWN: + recognition_formats |= barhopper::BarcodeFormat::UNRECOGNIZED; + break; + } + } + recognition_options.barcode_formats = recognition_formats; + return recognition_options; +} + +} // namespace + +BarcodeDetectionImplBarhopper::BarcodeDetectionImplBarhopper( + mojom::BarcodeDetectorOptionsPtr options) + : recognition_options_(GetRecognitionOptions(options)) {} + +BarcodeDetectionImplBarhopper::~BarcodeDetectionImplBarhopper() = default; + +void BarcodeDetectionImplBarhopper::Detect( + const SkBitmap& bitmap, + shape_detection::mojom::BarcodeDetection::DetectCallback callback) { + int width = bitmap.width(); + int height = bitmap.height(); + auto luminances = std::make_unique<uint8_t[]>(height * width); + uint8_t* luminances_ptr = luminances.get(); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + SkColor color = bitmap.getColor(x, y); + // Fast and approximate luminance calculation: (2*R + 5*G + B) / 8 + uint32_t luminance = + 2 * SkColorGetR(color) + 5 * SkColorGetG(color) + SkColorGetB(color); + luminances_ptr[y * width + x] = luminance / 8; + } + } + std::vector<barhopper::Barcode> barcodes; + barhopper::Barhopper::Recognize(width, height, luminances_ptr, + recognition_options_, &barcodes); + + std::vector<mojom::BarcodeDetectionResultPtr> results; + for (auto& barcode : barcodes) { + auto result = shape_detection::mojom::BarcodeDetectionResult::New(); + result->bounding_box = CornerPointsToBoundingBox(barcode.corner_point); + for (auto& corner_point : barcode.corner_point) { + result->corner_points.emplace_back(corner_point.x, corner_point.y); + } + result->raw_value = barcode.raw_value; + result->format = BarhopperFormatToMojo(barcode.format); + results.push_back(std::move(result)); + } + std::move(callback).Run(std::move(results)); +} + +// static +std::vector<mojom::BarcodeFormat> +BarcodeDetectionImplBarhopper::GetSupportedFormats() { + return {mojom::BarcodeFormat::AZTEC, mojom::BarcodeFormat::CODE_128, + mojom::BarcodeFormat::CODE_39, mojom::BarcodeFormat::CODE_93, + mojom::BarcodeFormat::CODABAR, mojom::BarcodeFormat::DATA_MATRIX, + mojom::BarcodeFormat::EAN_13, mojom::BarcodeFormat::EAN_8, + mojom::BarcodeFormat::ITF, mojom::BarcodeFormat::PDF417, + mojom::BarcodeFormat::QR_CODE, mojom::BarcodeFormat::UPC_A, + mojom::BarcodeFormat::UPC_E}; +} + +} // namespace shape_detection
\ No newline at end of file diff --git a/chromium/services/shape_detection/barcode_detection_impl_barhopper.h b/chromium/services/shape_detection/barcode_detection_impl_barhopper.h new file mode 100644 index 00000000000..c0fc0cfe27f --- /dev/null +++ b/chromium/services/shape_detection/barcode_detection_impl_barhopper.h @@ -0,0 +1,38 @@ +// 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 SERVICES_SHAPE_DETECTION_BARCODE_DETECTION_IMPL_BARHOPPER_H_ +#define SERVICES_SHAPE_DETECTION_BARCODE_DETECTION_IMPL_BARHOPPER_H_ + +#include "services/shape_detection/public/mojom/barcodedetection.mojom.h" +#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom.h" +#include "third_party/barhopper/barhopper/barhopper.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace shape_detection { + +class BarcodeDetectionImplBarhopper : public mojom::BarcodeDetection { + public: + explicit BarcodeDetectionImplBarhopper( + mojom::BarcodeDetectorOptionsPtr options); + BarcodeDetectionImplBarhopper(const BarcodeDetectionImplBarhopper&) = delete; + BarcodeDetectionImplBarhopper& operator=( + const BarcodeDetectionImplBarhopper&) = delete; + ~BarcodeDetectionImplBarhopper() override; + + // mojom::BarcodeDetection: + void Detect(const SkBitmap& bitmap, + shape_detection::mojom::BarcodeDetection::DetectCallback callback) + override; + + static std::vector<shape_detection::mojom::BarcodeFormat> + GetSupportedFormats(); + + private: + barhopper::RecognitionOptions recognition_options_; +}; + +} // namespace shape_detection + +#endif // SERVICES_SHAPE_DETECTION_BARCODE_DETECTION_IMPL_BARHOPPER_H_
\ No newline at end of file diff --git a/chromium/services/shape_detection/barcode_detection_impl_barhopper_unittest.cc b/chromium/services/shape_detection/barcode_detection_impl_barhopper_unittest.cc new file mode 100644 index 00000000000..d934ca7585b --- /dev/null +++ b/chromium/services/shape_detection/barcode_detection_impl_barhopper_unittest.cc @@ -0,0 +1,117 @@ +// 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 "base/files/file_util.h" +#include "base/path_service.h" +#include "base/test/bind.h" +#include "base/test/task_environment.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "services/shape_detection/barcode_detection_provider_barhopper.h" +#include "services/shape_detection/public/mojom/barcodedetection.mojom.h" +#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/codec/png_codec.h" + +namespace shape_detection { + +struct TestParams { + std::string filename; + std::string expected_value; + float x; + float y; + float width; + float height; +} kTestParams[] = {{"codabar.png", "A6.2831853B", 24, 24, 448, 95}, + {"code_39.png", "CHROMIUM", 20, 20, 318, 75}, + {"code_93.png", "CHROMIUM", 20, 20, 216, 75}, + {"code_128.png", "Chromium", 20, 20, 246, 75}, + {"data_matrix.png", "Chromium", 11, 11, 53, 53}, + {"ean_8.png", "62831857", 14, 10, 134, 75}, + {"ean_13.png", "6283185307179", 27, 10, 190, 75}, + {"itf.png", "62831853071795", 10, 10, 135, 39}, + {"pdf417.png", "Chromium", 20, 20, 240, 44}, + {"qr_code.png", "https://chromium.org", 40, 40, 250, 250}, + {"upc_a.png", "628318530714", 23, 10, 190, 75}, + {"upc_e.png", "06283186", 23, 10, 102, 75}}; + +class BarcodeDetectionImplBarhopperTest + : public testing::TestWithParam<struct TestParams> { + protected: + BarcodeDetectionImplBarhopperTest() = default; + BarcodeDetectionImplBarhopperTest(const BarcodeDetectionImplBarhopperTest&) = + delete; + BarcodeDetectionImplBarhopperTest& operator=( + const BarcodeDetectionImplBarhopperTest&) = delete; + ~BarcodeDetectionImplBarhopperTest() override = default; + + mojo::Remote<mojom::BarcodeDetection> ConnectToBarcodeDetector() { + mojo::Remote<mojom::BarcodeDetectionProvider> provider; + mojo::Remote<mojom::BarcodeDetection> barcode_service; + + BarcodeDetectionProviderBarhopper::Create( + provider.BindNewPipeAndPassReceiver()); + + auto options = mojom::BarcodeDetectorOptions::New(); + provider->CreateBarcodeDetection( + barcode_service.BindNewPipeAndPassReceiver(), std::move(options)); + return barcode_service; + } + + std::unique_ptr<SkBitmap> LoadTestImage(std::string filename) { + // Load image data from test directory. + base::FilePath image_path; + EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &image_path)); + image_path = image_path.Append(FILE_PATH_LITERAL("services")) + .Append(FILE_PATH_LITERAL("test")) + .Append(FILE_PATH_LITERAL("data")) + .Append(FILE_PATH_LITERAL(filename)); + EXPECT_TRUE(base::PathExists(image_path)); + std::string image_data; + EXPECT_TRUE(base::ReadFileToString(image_path, &image_data)); + + std::unique_ptr<SkBitmap> image(new SkBitmap()); + EXPECT_TRUE(gfx::PNGCodec::Decode( + reinterpret_cast<const uint8_t*>(image_data.data()), image_data.size(), + image.get())); + + const gfx::Size size(image->width(), image->height()); + const uint32_t num_bytes = size.GetArea() * 4 /* bytes per pixel */; + EXPECT_EQ(num_bytes, image->computeByteSize()); + + return image; + } + + private: + base::test::TaskEnvironment task_environment_; +}; + +TEST_P(BarcodeDetectionImplBarhopperTest, Scan) { + mojo::Remote<mojom::BarcodeDetection> barcode_detector = + ConnectToBarcodeDetector(); + + std::unique_ptr<SkBitmap> image = LoadTestImage(GetParam().filename); + ASSERT_TRUE(image); + + std::vector<mojom::BarcodeDetectionResultPtr> results; + base::RunLoop run_loop; + barcode_detector->Detect( + *image, base::BindLambdaForTesting( + [&](std::vector<mojom::BarcodeDetectionResultPtr> barcodes) { + results = std::move(barcodes); + run_loop.Quit(); + })); + run_loop.Run(); + EXPECT_EQ(1u, results.size()); + EXPECT_EQ(GetParam().expected_value, results.front()->raw_value); + EXPECT_EQ(GetParam().x, results.front()->bounding_box.x()); + EXPECT_EQ(GetParam().y, results.front()->bounding_box.y()); + EXPECT_EQ(GetParam().width, results.front()->bounding_box.width()); + EXPECT_EQ(GetParam().height, results.front()->bounding_box.height()); +} + +INSTANTIATE_TEST_SUITE_P(, + BarcodeDetectionImplBarhopperTest, + testing::ValuesIn(kTestParams)); + +} // namespace shape_detection
\ No newline at end of file diff --git a/chromium/services/shape_detection/barcode_detection_impl_mac_unittest.mm b/chromium/services/shape_detection/barcode_detection_impl_mac_unittest.mm index 2a1216b7e4f..d5ca22ea513 100644 --- a/chromium/services/shape_detection/barcode_detection_impl_mac_unittest.mm +++ b/chromium/services/shape_detection/barcode_detection_impl_mac_unittest.mm @@ -10,8 +10,8 @@ #include <string> #include "base/bind.h" -#include "base/bind_helpers.h" #include "base/callback_forward.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" diff --git a/chromium/services/shape_detection/barcode_detection_provider_barhopper.cc b/chromium/services/shape_detection/barcode_detection_provider_barhopper.cc new file mode 100644 index 00000000000..9d1d9b8884b --- /dev/null +++ b/chromium/services/shape_detection/barcode_detection_provider_barhopper.cc @@ -0,0 +1,39 @@ +// 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 "services/shape_detection/barcode_detection_provider_barhopper.h" + +#include <memory> +#include <utility> + +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" +#include "services/shape_detection/barcode_detection_impl_barhopper.h" +#include "services/shape_detection/public/mojom/barcodedetection.mojom.h" +#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom.h" + +namespace shape_detection { + +// static +void BarcodeDetectionProviderBarhopper::Create( + mojo::PendingReceiver<mojom::BarcodeDetectionProvider> receiver) { + mojo::MakeSelfOwnedReceiver( + std::make_unique<BarcodeDetectionProviderBarhopper>(), + std::move(receiver)); +} + +void BarcodeDetectionProviderBarhopper::CreateBarcodeDetection( + mojo::PendingReceiver<shape_detection::mojom::BarcodeDetection> receiver, + shape_detection::mojom::BarcodeDetectorOptionsPtr options) { + mojo::MakeSelfOwnedReceiver( + std::make_unique<BarcodeDetectionImplBarhopper>(std::move(options)), + std::move(receiver)); +} + +void BarcodeDetectionProviderBarhopper::EnumerateSupportedFormats( + EnumerateSupportedFormatsCallback callback) { + std::move(callback).Run(BarcodeDetectionImplBarhopper::GetSupportedFormats()); +} + +} // namespace shape_detection
\ No newline at end of file diff --git a/chromium/services/shape_detection/barcode_detection_provider_barhopper.h b/chromium/services/shape_detection/barcode_detection_provider_barhopper.h new file mode 100644 index 00000000000..7aa8bd20b53 --- /dev/null +++ b/chromium/services/shape_detection/barcode_detection_provider_barhopper.h @@ -0,0 +1,37 @@ +// 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 SERVICES_SHAPE_DETECTION_BARCODE_DETECTION_PROVIDER_BARHOPPER_H_ +#define SERVICES_SHAPE_DETECTION_BARCODE_DETECTION_PROVIDER_BARHOPPER_H_ + +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom.h" + +namespace shape_detection { + +// BarcodeDetectionProviderBarhopper class is a provider that binds to +// a BarcodeDetection implementation based on the barhopper library. +class BarcodeDetectionProviderBarhopper + : public mojom::BarcodeDetectionProvider { + public: + BarcodeDetectionProviderBarhopper() = default; + BarcodeDetectionProviderBarhopper(const BarcodeDetectionProviderBarhopper&) = + delete; + BarcodeDetectionProviderBarhopper& operator=( + const BarcodeDetectionProviderBarhopper&) = delete; + ~BarcodeDetectionProviderBarhopper() override = default; + + static void Create( + mojo::PendingReceiver<mojom::BarcodeDetectionProvider> receiver); + + // mojom::BarcodeDetectionProvider: + void CreateBarcodeDetection( + mojo::PendingReceiver<shape_detection::mojom::BarcodeDetection> receiver, + shape_detection::mojom::BarcodeDetectorOptionsPtr options) override; + void EnumerateSupportedFormats( + EnumerateSupportedFormatsCallback callback) override; +}; + +} // namespace shape_detection +#endif // SERVICES_SHAPE_DETECTION_BARCODE_DETECTION_PROVIDER_BARHOPPER_H_
\ No newline at end of file diff --git a/chromium/services/shape_detection/barcode_detection_provider_mac_unittest.mm b/chromium/services/shape_detection/barcode_detection_provider_mac_unittest.mm index afdf7c75804..bd58060f5a0 100644 --- a/chromium/services/shape_detection/barcode_detection_provider_mac_unittest.mm +++ b/chromium/services/shape_detection/barcode_detection_provider_mac_unittest.mm @@ -12,7 +12,7 @@ #include "base/bind.h" #include "base/callback_forward.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/gmock_callback_support.h" #include "base/test/task_environment.h" #include "mojo/public/cpp/bindings/remote.h" diff --git a/chromium/services/shape_detection/detection_utils_win.cc b/chromium/services/shape_detection/detection_utils_win.cc index f865ebb60ca..f2b91618650 100644 --- a/chromium/services/shape_detection/detection_utils_win.cc +++ b/chromium/services/shape_detection/detection_utils_win.cc @@ -20,11 +20,17 @@ ComPtr<ISoftwareBitmap> CreateWinBitmapFromSkBitmap( const SkBitmap& bitmap, ISoftwareBitmapStatics* bitmap_factory) { DCHECK(bitmap_factory); - DCHECK_EQ(bitmap.colorType(), kN32_SkColorType); if (!base::CheckedNumeric<uint32_t>(bitmap.computeByteSize()).IsValid()) { DLOG(ERROR) << "Data overflow."; return nullptr; } + // CreateCopyFromBuffer() assumes the pixels we pass in are 32bits each and + // are tightly packed. Receiving a bitmap of a different bits-per-pixel would + // create a buffer overflow. The `pixel_format` we use below assumes the + // format of the bitmap is N32. + CHECK_EQ(bitmap.colorType(), kN32_SkColorType); + CHECK_EQ(4, bitmap.info().bytesPerPixel()); + CHECK_EQ(bitmap.rowBytes(), bitmap.width() * static_cast<size_t>(4)); // Create IBuffer from bitmap data. ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer; diff --git a/chromium/services/shape_detection/shape_detection_service.cc b/chromium/services/shape_detection/shape_detection_service.cc index 96c15eea3c4..fa1a5a19f1c 100644 --- a/chromium/services/shape_detection/shape_detection_service.cc +++ b/chromium/services/shape_detection/shape_detection_service.cc @@ -9,12 +9,17 @@ #include "base/bind.h" #include "base/macros.h" +#include "build/branding_buildflags.h" +#include "build/chromeos_buildflags.h" #if defined(OS_WIN) #include "services/shape_detection/barcode_detection_provider_impl.h" #include "services/shape_detection/face_detection_provider_win.h" #elif defined(OS_MAC) #include "services/shape_detection/barcode_detection_provider_mac.h" #include "services/shape_detection/face_detection_provider_mac.h" +#elif BUILDFLAG(GOOGLE_CHROME_BRANDING) && BUILDFLAG(IS_ASH) +#include "services/shape_detection/barcode_detection_provider_barhopper.h" +#include "services/shape_detection/face_detection_provider_impl.h" #else #include "services/shape_detection/barcode_detection_provider_impl.h" #include "services/shape_detection/face_detection_provider_impl.h" @@ -43,6 +48,8 @@ void ShapeDetectionService::BindBarcodeDetectionProvider( receiver.PassPipe().release().value()); #elif defined(OS_MAC) BarcodeDetectionProviderMac::Create(std::move(receiver)); +#elif BUILDFLAG(GOOGLE_CHROME_BRANDING) && BUILDFLAG(IS_ASH) + BarcodeDetectionProviderBarhopper::Create(std::move(receiver)); #else BarcodeDetectionProviderImpl::Create(std::move(receiver)); #endif diff --git a/chromium/services/test/echo/public/mojom/BUILD.gn b/chromium/services/test/echo/public/mojom/BUILD.gn index 3d10b85f973..11f7d7393af 100644 --- a/chromium/services/test/echo/public/mojom/BUILD.gn +++ b/chromium/services/test/echo/public/mojom/BUILD.gn @@ -7,4 +7,5 @@ import("//mojo/public/tools/bindings/mojom.gni") mojom("mojom") { generate_java = true sources = [ "echo.mojom" ] + public_deps = [ "//mojo/public/mojom/base" ] } diff --git a/chromium/services/test/echo/public/mojom/echo.mojom b/chromium/services/test/echo/public/mojom/echo.mojom index ae4896b9f18..93c23b1f81e 100644 --- a/chromium/services/test/echo/public/mojom/echo.mojom +++ b/chromium/services/test/echo/public/mojom/echo.mojom @@ -4,11 +4,17 @@ module echo.mojom; +import "mojo/public/mojom/base/shared_memory.mojom"; + // Echos its input. interface EchoService { // Echos the passed-in string. EchoString(string input) => (string echoed_input); + // Echos the passed-in string into the provided shared memory buffer. + EchoStringToSharedMemory(string input, + mojo_base.mojom.UnsafeSharedMemoryRegion region); + // Causes the service to disconnect itself. Quit(); diff --git a/chromium/services/tracing/BUILD.gn b/chromium/services/tracing/BUILD.gn index b9b39543791..5d54f9483d6 100644 --- a/chromium/services/tracing/BUILD.gn +++ b/chromium/services/tracing/BUILD.gn @@ -9,13 +9,6 @@ import("//build/config/compiler/compiler.gni") import("//services/tracing/public/cpp/stack_sampling/loader_lock_sampling.gni") -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - if (is_android) { import("//build/config/android/rules.gni") } @@ -38,7 +31,11 @@ source_set("lib") { "//base", "//mojo/public/cpp/bindings", "//services/tracing/public/cpp", + "//services/tracing/public/mojom:mojom", "//third_party/perfetto:libperfetto", + "//third_party/perfetto/include/perfetto/ext/trace_processor:export_json", + "//third_party/perfetto/include/perfetto/trace_processor:basic_types", + "//third_party/perfetto/include/perfetto/trace_processor:storage", "//third_party/perfetto/protos/perfetto/config:lite", ] } @@ -87,21 +84,26 @@ source_set("tests") { sources = [ "perfetto/consumer_host_unittest.cc", "perfetto/perfetto_integration_unittest.cc", - "public/cpp/perfetto/java_heap_profiler/hprof_buffer_android_unittest.cc", - "public/cpp/perfetto/java_heap_profiler/hprof_parser_android_unittest.cc", "public/cpp/perfetto/producer_test_utils.cc", "public/cpp/perfetto/producer_test_utils.h", "public/cpp/perfetto/task_runner_unittest.cc", "public/cpp/perfetto/trace_event_data_source_unittest.cc", "public/cpp/perfetto/trace_packet_tokenizer_unittest.cc", "public/cpp/perfetto/traced_value_proto_writer_unittest.cc", - "public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc", "public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc", ] - if (is_android && current_cpu == "arm64") { - sources += - [ "public/cpp/stack_sampling/stack_unwinder_arm64_android_unittest.cc" ] + if (is_android) { + sources += [ + "public/cpp/perfetto/java_heap_profiler/hprof_buffer_android_unittest.cc", + "public/cpp/perfetto/java_heap_profiler/hprof_parser_android_unittest.cc", + "public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc", + ] + if (current_cpu == "arm64") { + sources += [ + "public/cpp/stack_sampling/stack_unwinder_arm64_android_unittest.cc", + ] + } } if (!is_android) { @@ -116,6 +118,7 @@ source_set("tests") { "//mojo/public/cpp/bindings", "//services/tracing/public/cpp:buildflags", "//services/tracing/public/cpp/background_tracing:unit_tests", + "//services/tracing/public/mojom:mojom", "//testing/gmock", "//testing/gtest", "//third_party/perfetto/include/perfetto/protozero:protozero", @@ -130,8 +133,10 @@ source_set("tests") { sources += [ "perfetto/system_perfetto_unittest.cc" ] if (can_unwind_with_cfi_table && is_official_build) { - sources += - [ "public/cpp/stack_sampling/stack_unwinder_android_unittest.cc" ] + if (is_android) { + sources += + [ "public/cpp/stack_sampling/stack_unwinder_android_unittest.cc" ] + } deps += [ ":jni_headers", ":tracing_test_helper_java", @@ -140,8 +145,10 @@ source_set("tests") { } if (enable_loader_lock_sampling) { - sources += - [ "public/cpp/stack_sampling/loader_lock_sampler_win_unittest.cc" ] + if (is_win) { + sources += + [ "public/cpp/stack_sampling/loader_lock_sampler_win_unittest.cc" ] + } deps += [ ":loader_lock_sampler_test_strings" ] data_deps = [ ":loader_lock_sampler_test_dll" ] diff --git a/chromium/services/tracing/DIR_METADATA b/chromium/services/tracing/DIR_METADATA new file mode 100644 index 00000000000..2b8a972d77d --- /dev/null +++ b/chromium/services/tracing/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Speed>Tracing" +}
\ No newline at end of file diff --git a/chromium/services/tracing/OWNERS b/chromium/services/tracing/OWNERS index 2f82ce6fe16..2c2f79b514a 100644 --- a/chromium/services/tracing/OWNERS +++ b/chromium/services/tracing/OWNERS @@ -1,2 +1 @@ -file://base/trace_event/OWNERS -# COMPONENT: Speed>Tracing +file://base/trace_event/OWNERS
\ No newline at end of file diff --git a/chromium/services/tracing/perfetto/consumer_host.cc b/chromium/services/tracing/perfetto/consumer_host.cc index 7a80f83844f..b310366f52e 100644 --- a/chromium/services/tracing/perfetto/consumer_host.cc +++ b/chromium/services/tracing/perfetto/consumer_host.cc @@ -167,6 +167,9 @@ ConsumerHost::TracingSession::TracingSession( if (data_source.config().chrome_config().privacy_filtering_enabled()) { privacy_filtering_enabled_ = true; } + if (data_source.config().chrome_config().convert_to_legacy_json()) { + convert_to_legacy_json_ = true; + } } #if DCHECK_IS_ON() if (privacy_filtering_enabled_) { @@ -194,7 +197,25 @@ ConsumerHost::TracingSession::TracingSession( base::EraseIf(*pending_enable_tracing_ack_pids_, [this](base::ProcessId pid) { return !IsExpectedPid(pid); }); - host_->consumer_endpoint()->EnableTracing(trace_config); + perfetto::TraceConfig effective_config(trace_config); + // If we're going to convert the data to JSON, don't enable privacy filtering + // at the data source level since it will be performed at conversion time + // (otherwise there's nothing to pass through the allowlist). + if (convert_to_legacy_json_ && privacy_filtering_enabled_) { + for (auto& data_source : *effective_config.mutable_data_sources()) { + auto* chrome_config = + data_source.mutable_config()->mutable_chrome_config(); + chrome_config->set_privacy_filtering_enabled(false); + // Argument filtering should still be enabled together with privacy + // filtering to ensure, for example, that only the expected metadata gets + // written. + base::trace_event::TraceConfig base_config(chrome_config->trace_config()); + base_config.EnableArgumentFilter(); + chrome_config->set_trace_config(base_config.ToString()); + } + } + + host_->consumer_endpoint()->EnableTracing(effective_config); MaybeSendEnableTracingAck(); if (pending_enable_tracing_ack_pids_) { @@ -327,7 +348,7 @@ void ConsumerHost::TracingSession::DisableTracing() { host_->consumer_endpoint()->DisableTracing(); } -void ConsumerHost::TracingSession::OnTracingDisabled() { +void ConsumerHost::TracingSession::OnTracingDisabled(const std::string& error) { DCHECK(tracing_session_client_); if (enable_tracing_ack_timer_.IsRunning()) { @@ -335,7 +356,8 @@ void ConsumerHost::TracingSession::OnTracingDisabled() { } DCHECK(!pending_enable_tracing_ack_pids_); - tracing_session_client_->OnTracingDisabled(); + tracing_session_client_->OnTracingDisabled( + /*tracing_succeeded=*/error.empty()); if (trace_processor_) { host_->consumer_endpoint()->ReadBuffers(); @@ -356,6 +378,7 @@ void ConsumerHost::TracingSession::OnConsumerClientDisconnected() { void ConsumerHost::TracingSession::ReadBuffers( mojo::ScopedDataPipeProducerHandle stream, ReadBuffersCallback callback) { + DCHECK(!convert_to_legacy_json_); read_buffers_stream_writer_ = base::SequenceBound<StreamWriter>( StreamWriter::CreateTaskRunner(), std::move(stream), std::move(callback), base::BindOnce(&TracingSession::OnConsumerClientDisconnected, @@ -393,7 +416,7 @@ void ConsumerHost::TracingSession::DisableTracingAndEmitJson( // For filtering/allowlisting to be possible at JSON export time, // filtering must not have been enabled during proto emission time // (or there's nothing to pass through the allowlist). - DCHECK(!privacy_filtering_enabled_); + DCHECK(!privacy_filtering_enabled_ || convert_to_legacy_json_); privacy_filtering_enabled_ = true; } @@ -473,8 +496,8 @@ void ConsumerHost::TracingSession::OnJSONTraceData(std::string json, bool has_more) { auto slice = std::make_unique<StreamWriter::Slice>(); slice->swap(json); - read_buffers_stream_writer_.Post(FROM_HERE, &StreamWriter::WriteToStream, - std::move(slice), has_more); + read_buffers_stream_writer_.AsyncCall(&StreamWriter::WriteToStream) + .WithArgs(std::move(slice), has_more); if (!has_more) { read_buffers_stream_writer_.Reset(); @@ -537,8 +560,8 @@ void ConsumerHost::TracingSession::OnTraceData( chunk->append(static_cast<const char*>(slice.start), slice.size); } } - read_buffers_stream_writer_.Post(FROM_HERE, &StreamWriter::WriteToStream, - std::move(chunk), has_more); + read_buffers_stream_writer_.AsyncCall(&StreamWriter::WriteToStream) + .WithArgs(std::move(chunk), has_more); if (!has_more) { read_buffers_stream_writer_.Reset(); } @@ -603,11 +626,31 @@ ConsumerHost::~ConsumerHost() { void ConsumerHost::EnableTracing( mojo::PendingReceiver<mojom::TracingSessionHost> tracing_session_host, mojo::PendingRemote<mojom::TracingSessionClient> tracing_session_client, - const perfetto::TraceConfig& trace_config, - mojom::TracingClientPriority priority) { + const perfetto::TraceConfig& trace_config) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!tracing_session_); + auto priority = mojom::TracingClientPriority::kUnknown; + for (const auto& data_source : trace_config.data_sources()) { + if (!data_source.has_config() || + !data_source.config().has_chrome_config()) { + continue; + } + switch (data_source.config().chrome_config().client_priority()) { + case perfetto::protos::gen::ChromeConfig::BACKGROUND: + priority = + std::max(priority, mojom::TracingClientPriority::kBackground); + break; + case perfetto::protos::gen::ChromeConfig::USER_INITIATED: + priority = + std::max(priority, mojom::TracingClientPriority::kUserInitiated); + break; + default: + case perfetto::protos::gen::ChromeConfig::UNKNOWN: + break; + } + } + // We create our new TracingSession async, if the PerfettoService allows // us to, after it's stopped any currently running lower or equal priority // tracing sessions. @@ -638,10 +681,10 @@ void ConsumerHost::OnConnect() {} void ConsumerHost::OnDisconnect() {} -void ConsumerHost::OnTracingDisabled() { +void ConsumerHost::OnTracingDisabled(const std::string& error) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (tracing_session_) { - tracing_session_->OnTracingDisabled(); + tracing_session_->OnTracingDisabled(error); } } diff --git a/chromium/services/tracing/perfetto/consumer_host.h b/chromium/services/tracing/perfetto/consumer_host.h index 97c7e36f6f8..6efa14f009c 100644 --- a/chromium/services/tracing/perfetto/consumer_host.h +++ b/chromium/services/tracing/perfetto/consumer_host.h @@ -54,7 +54,7 @@ class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost { void OnPerfettoEvents(const perfetto::ObservableEvents&); void OnTraceData(std::vector<perfetto::TracePacket> packets, bool has_more); void OnTraceStats(bool success, const perfetto::TraceStats&); - void OnTracingDisabled(); + void OnTracingDisabled(const std::string& error); void OnConsumerClientDisconnected(); void Flush(uint32_t timeout, base::OnceCallback<void(bool)> callback); @@ -94,6 +94,7 @@ class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost { mojo::Remote<mojom::TracingSessionClient> tracing_session_client_; mojo::Receiver<mojom::TracingSessionHost> receiver_; bool privacy_filtering_enabled_ = false; + bool convert_to_legacy_json_ = false; base::SequenceBound<StreamWriter> read_buffers_stream_writer_; RequestBufferUsageCallback request_buffer_usage_callback_; std::unique_ptr<perfetto::trace_processor::TraceProcessorStorage> @@ -137,15 +138,14 @@ class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost { void EnableTracing( mojo::PendingReceiver<mojom::TracingSessionHost> tracing_session_host, mojo::PendingRemote<mojom::TracingSessionClient> tracing_session_client, - const perfetto::TraceConfig& config, - mojom::TracingClientPriority priority) override; + const perfetto::TraceConfig& config) override; // perfetto::Consumer implementation. // This gets called by the Perfetto service as control signals, // and to send finished protobufs over. void OnConnect() override; void OnDisconnect() override; - void OnTracingDisabled() override; + void OnTracingDisabled(const std::string& error) override; void OnTraceData(std::vector<perfetto::TracePacket> packets, bool has_more) override; void OnObservableEvents(const perfetto::ObservableEvents&) override; diff --git a/chromium/services/tracing/perfetto/consumer_host_unittest.cc b/chromium/services/tracing/perfetto/consumer_host_unittest.cc index a026b35ceda..1c6b6522f3f 100644 --- a/chromium/services/tracing/perfetto/consumer_host_unittest.cc +++ b/chromium/services/tracing/perfetto/consumer_host_unittest.cc @@ -10,14 +10,14 @@ #include <utility> #include <vector> -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/run_loop.h" #include "base/sequenced_task_runner.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/system/data_pipe.h" @@ -105,7 +105,7 @@ class ThreadedPerfettoService : public mojom::TracingSessionClient { tracing_enabled_ = true; } - void OnTracingDisabled() override {} + void OnTracingDisabled(bool) override {} void CreateProducer(const std::string& data_source_name, size_t num_packets, @@ -154,8 +154,7 @@ class ThreadedPerfettoService : public mojom::TracingSessionClient { consumer_->EnableTracing( tracing_session_host_->BindNewPipeAndPassReceiver(), - std::move(tracing_session_client), std::move(config), - tracing::mojom::TracingClientPriority::kUserInitiated); + std::move(tracing_session_client), std::move(config)); } void ReadBuffers(mojo::ScopedDataPipeProducerHandle stream, @@ -379,7 +378,9 @@ class TracingConsumerTest : public testing::Test, } perfetto::TraceConfig GetDefaultTraceConfig( - const std::string& data_source_name) { + const std::string& data_source_name, + perfetto::protos::gen::ChromeConfig::ClientPriority priority = + perfetto::protos::gen::ChromeConfig::UNKNOWN) { perfetto::TraceConfig trace_config; trace_config.add_buffers()->set_size_kb(32 * 1024); @@ -387,12 +388,14 @@ class TracingConsumerTest : public testing::Test, trace_config.add_data_sources()->mutable_config(); trace_event_config->set_name(data_source_name); trace_event_config->set_target_buffer(0); + trace_event_config->mutable_chrome_config()->set_client_priority(priority); return trace_config; } void EnableTracingWithDataSourceName(const std::string& data_source_name, - bool enable_privacy_filtering = false) { + bool enable_privacy_filtering = false, + bool convert_to_legacy_json = false) { perfetto::TraceConfig config = GetDefaultTraceConfig(data_source_name); if (enable_privacy_filtering) { for (auto& source : *config.mutable_data_sources()) { @@ -401,6 +404,13 @@ class TracingConsumerTest : public testing::Test, ->set_privacy_filtering_enabled(true); } } + if (convert_to_legacy_json) { + for (auto& source : *config.mutable_data_sources()) { + source.mutable_config() + ->mutable_chrome_config() + ->set_convert_to_legacy_json(true); + } + } threaded_service_->EnableTracingWithConfig(config); } @@ -623,7 +633,8 @@ TEST_F(TracingConsumerTest, TEST_F(TracingConsumerTest, PrivacyFilterConfig) { EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName, - /* enable_privacy_filtering =*/true); + /* enable_privacy_filtering =*/true, + /* convert_to_legacy_json =*/false); base::RunLoop wait_for_tracing_start; threaded_perfetto_service()->CreateProducer( @@ -635,11 +646,40 @@ TEST_F(TracingConsumerTest, PrivacyFilterConfig) { ->GetProducerClientConfig() .chrome_config() .privacy_filtering_enabled()); + base::trace_event::TraceConfig base_config(threaded_perfetto_service() + ->GetProducerClientConfig() + .chrome_config() + .trace_config()); + EXPECT_FALSE(base_config.IsArgumentFilterEnabled()); +} + +TEST_F(TracingConsumerTest, NoPrivacyFilterWithJsonConversion) { + EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName, + /* enable_privacy_filtering =*/false, + /* convert_to_legacy_json =*/true); + + base::RunLoop wait_for_tracing_start; + threaded_perfetto_service()->CreateProducer( + mojom::kTraceEventDataSourceName, 10u, + wait_for_tracing_start.QuitClosure()); + + wait_for_tracing_start.Run(); + + EXPECT_FALSE(threaded_perfetto_service() + ->GetProducerClientConfig() + .chrome_config() + .privacy_filtering_enabled()); + base::trace_event::TraceConfig base_config(threaded_perfetto_service() + ->GetProducerClientConfig() + .chrome_config() + .trace_config()); + EXPECT_FALSE(base_config.IsArgumentFilterEnabled()); } TEST_F(TracingConsumerTest, PrivacyFilterConfigInJson) { EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName, - /* enable_privacy_filtering =*/false); + /* enable_privacy_filtering =*/true, + /* convert_to_legacy_json =*/true); base::RunLoop wait_for_tracing_start; threaded_perfetto_service()->CreateProducer( @@ -652,6 +692,11 @@ TEST_F(TracingConsumerTest, PrivacyFilterConfigInJson) { ->GetProducerClientConfig() .chrome_config() .privacy_filtering_enabled()); + base::trace_event::TraceConfig base_config(threaded_perfetto_service() + ->GetProducerClientConfig() + .chrome_config() + .trace_config()); + EXPECT_TRUE(base_config.IsArgumentFilterEnabled()); base::RunLoop no_more_data; ExpectPackets("\"trace_processor_stats\":\"__stripped__\"", @@ -672,8 +717,7 @@ class MockConsumerHost : public mojom::TracingSessionClient { explicit MockConsumerHost(PerfettoService* service) : consumer_host_(std::make_unique<ConsumerHost>(service)) {} - void EnableTracing(const perfetto::TraceConfig& config, - mojom::TracingClientPriority priority) { + void EnableTracing(const perfetto::TraceConfig& config) { mojo::PendingRemote<tracing::mojom::TracingSessionClient> tracing_session_client; receiver_.Bind(tracing_session_client.InitWithNewPipeAndPassReceiver()); @@ -683,7 +727,7 @@ class MockConsumerHost : public mojom::TracingSessionClient { consumer_host_->EnableTracing( tracing_session_host_.BindNewPipeAndPassReceiver(), - std::move(tracing_session_client), config, priority); + std::move(tracing_session_client), config); tracing_session_host_.set_disconnect_handler(base::BindOnce( &MockConsumerHost::OnConnectionLost, base::Unretained(this))); } @@ -703,7 +747,7 @@ class MockConsumerHost : public mojom::TracingSessionClient { // mojom::TracingSessionClient implementation: void OnTracingEnabled() override { wait_for_tracing_enabled_.Quit(); } - void OnTracingDisabled() override { wait_for_tracing_disabled_.Quit(); } + void OnTracingDisabled(bool) override { wait_for_tracing_disabled_.Quit(); } void WaitForConnectionLost() { wait_for_connection_lost_.Run(); } @@ -721,36 +765,36 @@ class MockConsumerHost : public mojom::TracingSessionClient { }; TEST_F(TracingConsumerTest, TestConsumerPriority) { - // auto perfetto_service = std::make_unique<PerfettoService>(nullptr); PerfettoService::GetInstance()->SetActiveServicePidsInitialized(); - auto trace_config = GetDefaultTraceConfig(mojom::kTraceEventDataSourceName); + auto trace_config_background = + GetDefaultTraceConfig(mojom::kTraceEventDataSourceName, + perfetto::protos::gen ::ChromeConfig::BACKGROUND); + auto trace_config_user_initiated = GetDefaultTraceConfig( + mojom::kTraceEventDataSourceName, + perfetto::protos::gen ::ChromeConfig::USER_INITIATED); MockConsumerHost background_consumer_1(PerfettoService::GetInstance()); - background_consumer_1.EnableTracing( - trace_config, tracing::mojom::TracingClientPriority::kBackground); + background_consumer_1.EnableTracing(trace_config_background); background_consumer_1.WaitForTracingEnabled(); // Second consumer of the same priority should cause the first one to // be disabled and the second to start. MockConsumerHost background_consumer_2(PerfettoService::GetInstance()); - background_consumer_2.EnableTracing( - trace_config, tracing::mojom::TracingClientPriority::kBackground); + background_consumer_2.EnableTracing(trace_config_background); background_consumer_1.WaitForTracingDisabled(); background_consumer_2.WaitForTracingEnabled(); // Third consumer will have a higher priority, and should kill the second // one. MockConsumerHost user_initiated_consumer(PerfettoService::GetInstance()); - user_initiated_consumer.EnableTracing( - trace_config, tracing::mojom::TracingClientPriority::kUserInitiated); + user_initiated_consumer.EnableTracing(trace_config_user_initiated); background_consumer_2.WaitForTracingDisabled(); user_initiated_consumer.WaitForTracingEnabled(); // Fourth consumer will be another background consumer, and should be // itself killed as the third consumer is still running. MockConsumerHost background_consumer_3(PerfettoService::GetInstance()); - background_consumer_3.EnableTracing( - trace_config, tracing::mojom::TracingClientPriority::kBackground); + background_consumer_3.EnableTracing(trace_config_background); background_consumer_3.WaitForConnectionLost(); // If we close the user initiated consumer, the third background consumer @@ -758,8 +802,7 @@ TEST_F(TracingConsumerTest, TestConsumerPriority) { user_initiated_consumer.DisableTracing(); user_initiated_consumer.WaitForTracingDisabled(); user_initiated_consumer.CloseTracingSession(); - background_consumer_3.EnableTracing( - trace_config, tracing::mojom::TracingClientPriority::kBackground); + background_consumer_3.EnableTracing(trace_config_background); background_consumer_3.WaitForTracingEnabled(); } diff --git a/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc b/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc index c5b00b316c7..c74b5c98a4c 100644 --- a/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc +++ b/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc @@ -10,7 +10,7 @@ #include "base/bind.h" #include "base/run_loop.h" #include "base/strings/strcat.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/thread.h" #include "services/tracing/perfetto/perfetto_service.h" diff --git a/chromium/services/tracing/perfetto/perfetto_service.cc b/chromium/services/tracing/perfetto/perfetto_service.cc index 359164ed2bf..e8a444df7e7 100644 --- a/chromium/services/tracing/perfetto/perfetto_service.cc +++ b/chromium/services/tracing/perfetto/perfetto_service.cc @@ -7,6 +7,7 @@ #include <utility> #include "base/bind.h" +#include "base/metrics/histogram_functions.h" #include "base/no_destructor.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" @@ -89,19 +90,37 @@ void PerfettoService::ConnectToProducerHost( mojo::ScopedSharedBufferHandle shared_memory, uint64_t shared_memory_buffer_page_size_bytes) { if (!shared_memory.is_valid()) { - mojo::ReportBadMessage("Producer connection request without valid SMB"); + // Connection requests should always include an SMB. + mojo::ReportBadMessage("Producer connection request without SMB"); return; } auto new_producer = std::make_unique<ProducerHost>(&perfetto_task_runner_); uint32_t producer_pid = receivers_.current_context(); DCHECK(shared_memory.is_valid()); - if (!new_producer->Initialize( - std::move(producer_client), service_.get(), - base::StrCat({mojom::kPerfettoProducerNamePrefix, - base::NumberToString(producer_pid)}), - std::move(shared_memory), shared_memory_buffer_page_size_bytes)) { - mojo::ReportBadMessage("Producer connection failed"); + ProducerHost::InitializationResult result = new_producer->Initialize( + std::move(producer_client), service_.get(), + base::StrCat({mojom::kPerfettoProducerNamePrefix, + base::NumberToString(producer_pid)}), + std::move(shared_memory), shared_memory_buffer_page_size_bytes); + + base::UmaHistogramEnumeration("Tracing.ProducerHostInitializationResult", + result); + + if (result == ProducerHost::InitializationResult::kSmbNotAdopted) { + // When everything else succeeds, but the SMB was not accepted, the producer + // must be misbehaving. SMBs are not accepted only if they are incorrectly + // sized, but SMB/page sizes are constants in Chromium. + mojo::ReportBadMessage("Producer connection request with invalid SMB"); + return; + } + + if (result != ProducerHost::InitializationResult::kSuccess) { + // In other failure scenarios, the tracing service may have encountered an + // internal error not caused by a misbehaving producer, e.g. we have too + // many producers registered or mapping the SMB failed (crbug/1154344). In + // these cases, we have no choice but to ignore the failure and cancel the + // producer connection by dropping |new_producer|. return; } diff --git a/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h b/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h index bd3ca0b5c6a..d16cb4eb6e5 100644 --- a/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h +++ b/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h @@ -170,15 +170,30 @@ constexpr MessageInfo kChromeFrameReporter = {kChromeFrameReporterIndices, constexpr int kChromeMessagePumpIndices[] = {1, -1}; constexpr MessageInfo kChromeMessagePump = {kChromeMessagePumpIndices, nullptr}; +// Proto Message: ChromeMojoEventInfo +constexpr int kChromeMojoEventInfoIndices[] = {1, -1}; +constexpr MessageInfo kChromeMojoEventInfo = {kChromeMojoEventInfoIndices, + nullptr}; + +// Proto Message: ChromeApplicationStateInfo +constexpr int kChromeApplicationStateInfoIndices[] = {1, -1}; +constexpr MessageInfo kChromeApplicationStateInfo = { + kChromeApplicationStateInfoIndices, nullptr}; + // Proto Message: ChromeRendererSchedulerState constexpr int kChromeRendererSchedulerStateIndices[] = {1, -1}; constexpr MessageInfo kChromeRendererSchedulerState = { kChromeRendererSchedulerStateIndices, nullptr}; +// Proto Message: ChromeWindowHandleEventInfo +constexpr int kChromeWindowHandleEventInfoIndices[] = {1, 2, -1}; +constexpr MessageInfo kChromeWindowHandleEventInfo = { + kChromeWindowHandleEventInfoIndices, nullptr}; + // Proto Message: TrackEvent -constexpr int kTrackEventIndices[] = {1, 2, 3, 5, 6, 9, 10, 11, 12, - 16, 17, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 40, -1}; +constexpr int kTrackEventIndices[] = {1, 2, 3, 5, 6, 9, 10, 11, 12, 16, + 17, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 38, 39, 40, 41, 42, -1}; constexpr MessageInfo const* kTrackEventComplexMessages[] = { nullptr, nullptr, @@ -203,7 +218,12 @@ constexpr MessageInfo const* kTrackEventComplexMessages[] = { &kSourceLocation, nullptr, &kChromeMessagePump, - &kChromeRendererSchedulerState}; + nullptr, + &kChromeMojoEventInfo, + &kChromeApplicationStateInfo, + &kChromeRendererSchedulerState, + &kChromeWindowHandleEventInfo, + nullptr}; constexpr MessageInfo kTrackEvent = {kTrackEventIndices, kTrackEventComplexMessages}; diff --git a/chromium/services/tracing/perfetto/producer_host.cc b/chromium/services/tracing/perfetto/producer_host.cc index 7d7d243213c..44ce454b784 100644 --- a/chromium/services/tracing/perfetto/producer_host.cc +++ b/chromium/services/tracing/perfetto/producer_host.cc @@ -29,7 +29,7 @@ ProducerHost::~ProducerHost() { producer_endpoint_.reset(); } -bool ProducerHost::Initialize( +ProducerHost::InitializationResult ProducerHost::Initialize( mojo::PendingRemote<mojom::ProducerClient> producer_client, perfetto::TracingService* service, const std::string& name, @@ -43,7 +43,7 @@ bool ProducerHost::Initialize( auto shm = std::make_unique<MojoSharedMemory>(std::move(shared_memory)); // We may fail to map the buffer provided by the ProducerClient. if (!shm->start()) { - return false; + return InitializationResult::kSmbMappingFailed; } size_t shm_size = shm->size(); @@ -56,10 +56,15 @@ bool ProducerHost::Initialize( shared_memory_buffer_page_size_bytes, std::move(shm)); // In some cases, the service may deny the producer connection (e.g. if too - // many producers are registered). The service will adopt the shared memory - // buffer provided by the ProducerClient as long as it is correctly sized. - if (!producer_endpoint_ || producer_endpoint_->shared_memory() != shm_raw) { - return false; + // many producers are registered). + if (!producer_endpoint_) { + return InitializationResult::kProducerEndpointConstructionFailed; + } + + // The service will adopt the shared memory buffer provided by the + // ProducerClient as long as it is correctly sized. + if (producer_endpoint_->shared_memory() != shm_raw) { + return InitializationResult::kSmbNotAdopted; } // When we are in-process, we don't use the in-process arbiter perfetto would @@ -81,7 +86,7 @@ bool ProducerHost::Initialize( } } - return true; + return InitializationResult::kSuccess; } void ProducerHost::OnConnect() { diff --git a/chromium/services/tracing/perfetto/producer_host.h b/chromium/services/tracing/perfetto/producer_host.h index b93aafa460a..2579272e7bc 100644 --- a/chromium/services/tracing/perfetto/producer_host.h +++ b/chromium/services/tracing/perfetto/producer_host.h @@ -37,15 +37,26 @@ class ProducerHost : public tracing::mojom::ProducerHost, explicit ProducerHost(PerfettoTaskRunner*); ~ProducerHost() override; + // Keep in sync with tools/metrics/histograms/enums.xml. These values are + // persisted to logs. Entries should not be renumbered and numeric values + // should never be reused. + enum class InitializationResult { + kSuccess = 0, + kSmbMappingFailed = 1, + kSmbNotAdopted = 2, + kProducerEndpointConstructionFailed = 3, + kMaxValue = kProducerEndpointConstructionFailed + }; + // Called by the ProducerService to register the Producer with Perfetto, // connect to the corresponding remote ProducerClient, and setup the provided - // shared memory buffer for tracing data exchange. Returns false if the - // service failed to connect the producer or adopt the provided SMB. - bool Initialize(mojo::PendingRemote<mojom::ProducerClient> producer_client, - perfetto::TracingService* service, - const std::string& name, - mojo::ScopedSharedBufferHandle shared_memory, - uint64_t shared_memory_buffer_page_size_bytes); + // shared memory buffer for tracing data exchange. + InitializationResult Initialize( + mojo::PendingRemote<mojom::ProducerClient> producer_client, + perfetto::TracingService* service, + const std::string& name, + mojo::ScopedSharedBufferHandle shared_memory, + uint64_t shared_memory_buffer_page_size_bytes); // perfetto::Producer implementation. // Gets called by perfetto::TracingService to toggle specific data sources diff --git a/chromium/services/tracing/perfetto/system_perfetto_unittest.cc b/chromium/services/tracing/perfetto/system_perfetto_unittest.cc index 0b6c066c2c2..5d17978173c 100644 --- a/chromium/services/tracing/perfetto/system_perfetto_unittest.cc +++ b/chromium/services/tracing/perfetto/system_perfetto_unittest.cc @@ -16,7 +16,7 @@ #include "base/run_loop.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/trace_event/trace_config.h" diff --git a/chromium/services/tracing/perfetto/test_utils.cc b/chromium/services/tracing/perfetto/test_utils.cc index 074b557dcb2..66fbae2b24c 100644 --- a/chromium/services/tracing/perfetto/test_utils.cc +++ b/chromium/services/tracing/perfetto/test_utils.cc @@ -253,7 +253,7 @@ void MockConsumer::OnConnect() { StartTracing(); } void MockConsumer::OnDisconnect() {} -void MockConsumer::OnTracingDisabled() {} +void MockConsumer::OnTracingDisabled(const std::string& error) {} void MockConsumer::OnTraceData(std::vector<perfetto::TracePacket> packets, bool has_more) { diff --git a/chromium/services/tracing/perfetto/test_utils.h b/chromium/services/tracing/perfetto/test_utils.h index 7963a76a124..21fedd87a5c 100644 --- a/chromium/services/tracing/perfetto/test_utils.h +++ b/chromium/services/tracing/perfetto/test_utils.h @@ -144,7 +144,7 @@ class MockConsumer : public perfetto::Consumer { // perfetto::Consumer implementation void OnConnect() override; void OnDisconnect() override; - void OnTracingDisabled() override; + void OnTracingDisabled(const std::string& error) override; void OnTraceData(std::vector<perfetto::TracePacket> packets, bool has_more) override; diff --git a/chromium/services/tracing/public/cpp/BUILD.gn b/chromium/services/tracing/public/cpp/BUILD.gn index 71407fda609..4b46fa345cb 100644 --- a/chromium/services/tracing/public/cpp/BUILD.gn +++ b/chromium/services/tracing/public/cpp/BUILD.gn @@ -8,13 +8,6 @@ import("//build/config/compiler/compiler.gni") import("//build_overrides/build.gni") import("//services/tracing/public/cpp/stack_sampling/loader_lock_sampling.gni") -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - buildflag_header("buildflags") { header = "buildflags.h" flags = [ "ENABLE_LOADER_LOCK_SAMPLING=$enable_loader_lock_sampling" ] @@ -66,15 +59,6 @@ target(tracing_lib_type, "cpp") { "perfetto/dummy_producer.cc", "perfetto/dummy_producer.h", "perfetto/interning_index.h", - "perfetto/java_heap_profiler/hprof_buffer_android.cc", - "perfetto/java_heap_profiler/hprof_buffer_android.h", - "perfetto/java_heap_profiler/hprof_data_type_android.h", - "perfetto/java_heap_profiler/hprof_instances_android.cc", - "perfetto/java_heap_profiler/hprof_instances_android.h", - "perfetto/java_heap_profiler/hprof_parser_android.cc", - "perfetto/java_heap_profiler/hprof_parser_android.h", - "perfetto/java_heap_profiler/java_heap_profiler_android.cc", - "perfetto/java_heap_profiler/java_heap_profiler_android.h", "perfetto/perfetto_config.cc", "perfetto/perfetto_config.h", "perfetto/perfetto_platform.cc", @@ -106,8 +90,6 @@ target(tracing_lib_type, "cpp") { "perfetto/traced_value_proto_writer.h", "perfetto/track_event_thread_local_event_sink.cc", "perfetto/track_event_thread_local_event_sink.h", - "stack_sampling/reached_code_data_source_android.cc", - "stack_sampling/reached_code_data_source_android.h", "stack_sampling/tracing_sampler_profiler.cc", "stack_sampling/tracing_sampler_profiler.h", "trace_event_agent.cc", @@ -122,6 +104,22 @@ target(tracing_lib_type, "cpp") { "tracing_features.h", ] + if (is_android) { + sources += [ + "perfetto/java_heap_profiler/hprof_buffer_android.cc", + "perfetto/java_heap_profiler/hprof_buffer_android.h", + "perfetto/java_heap_profiler/hprof_data_type_android.h", + "perfetto/java_heap_profiler/hprof_instances_android.cc", + "perfetto/java_heap_profiler/hprof_instances_android.h", + "perfetto/java_heap_profiler/hprof_parser_android.cc", + "perfetto/java_heap_profiler/hprof_parser_android.h", + "perfetto/java_heap_profiler/java_heap_profiler_android.cc", + "perfetto/java_heap_profiler/java_heap_profiler_android.h", + "stack_sampling/reached_code_data_source_android.cc", + "stack_sampling/reached_code_data_source_android.h", + ] + } + if (is_android && current_cpu == "arm64") { sources += [ "stack_sampling/stack_unwinder_arm64_android.cc", @@ -129,7 +127,7 @@ target(tracing_lib_type, "cpp") { ] } - if (enable_loader_lock_sampling) { + if (is_win && enable_loader_lock_sampling) { sources += [ "stack_sampling/loader_lock_sampler_win.cc", "stack_sampling/loader_lock_sampler_win.h", @@ -145,6 +143,7 @@ target(tracing_lib_type, "cpp") { deps += [ ":buildflags", "//build:chromecast_buildflags", + "//build:chromeos_buildflags", "//third_party/perfetto/protos/perfetto/trace/chrome:minimal_complete_lite", ] diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc b/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc index f54590401c5..cf321b19ed6 100644 --- a/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc +++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc @@ -9,10 +9,12 @@ #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" +#include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_config.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "build/chromecast_buildflags.h" +#include "build/chromeos_buildflags.h" #include "services/tracing/public/cpp/perfetto/trace_time.h" #include "services/tracing/public/mojom/perfetto_service.mojom.h" @@ -49,6 +51,17 @@ void AddDataSourceConfigs( perfetto::protos::gen::ChromeConfig::ClientPriority client_priority) { const std::string chrome_config_string = stripped_config.ToString(); + if (stripped_config.IsCategoryGroupEnabled( + base::trace_event::MemoryDumpManager::kTraceCategory)) { + DCHECK(source_names.empty() || + source_names.count( + tracing::mojom::kMemoryInstrumentationDataSourceName)); + AddDataSourceConfig(perfetto_config, + tracing::mojom::kMemoryInstrumentationDataSourceName, + chrome_config_string, privacy_filtering_enabled, + convert_to_legacy_json, client_priority); + } + // Capture actual trace events. if (source_names.empty() || source_names.count(tracing::mojom::kTraceEventDataSourceName) == 1) { @@ -76,7 +89,7 @@ void AddDataSourceConfigs( } #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) if (source_names.empty() || source_names.count(tracing::mojom::kArcTraceDataSourceName) == 1) { AddDataSourceConfig(perfetto_config, diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc b/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc index 4bc5ac15547..889a9e1ea63 100644 --- a/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc +++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc @@ -4,7 +4,7 @@ #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/no_destructor.h" #include "base/run_loop.h" #include "base/sequenced_task_runner.h" diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc b/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc index c731ed29394..38751c834dc 100644 --- a/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc +++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc @@ -42,6 +42,8 @@ constexpr size_t kDefaultSMBPageSizeBytes = 32 * 1024; // TODO(crbug.com/839071): Figure out a good buffer size. constexpr size_t kDefaultSMBSizeBytes = 4 * 1024 * 1024; +constexpr char kErrorTracingFailed[] = "Tracing failed"; + } // namespace // Implements Perfetto's ProducerEndpoint interface on top of the @@ -378,30 +380,10 @@ class ConsumerEndpoint : public perfetto::ConsumerEndpoint, void StartTracing() override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto priority = mojom::TracingClientPriority::kUnknown; - for (const auto& data_source : trace_config_.data_sources()) { - if (!data_source.has_config() || - !data_source.config().has_chrome_config()) { - continue; - } - switch (data_source.config().chrome_config().client_priority()) { - case perfetto::protos::gen::ChromeConfig::BACKGROUND: - priority = - std::max(priority, mojom::TracingClientPriority::kBackground); - break; - case perfetto::protos::gen::ChromeConfig::USER_INITIATED: - priority = - std::max(priority, mojom::TracingClientPriority::kUserInitiated); - break; - default: - case perfetto::protos::gen::ChromeConfig::UNKNOWN: - break; - } - } + tracing_failed_ = false; consumer_host_->EnableTracing( tracing_session_host_.BindNewPipeAndPassReceiver(), - tracing_session_client_.BindNewPipeAndPassRemote(), trace_config_, - priority); + tracing_session_client_.BindNewPipeAndPassRemote(), trace_config_); tracing_session_host_.set_disconnect_handler(base::BindOnce( &ConsumerEndpoint::OnTracingFailed, base::Unretained(this))); tracing_session_client_.set_disconnect_handler(base::BindOnce( @@ -410,7 +392,8 @@ class ConsumerEndpoint : public perfetto::ConsumerEndpoint, void DisableTracing() override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - tracing_session_host_->DisableTracing(); + if (tracing_session_host_) + tracing_session_host_->DisableTracing(); } void Flush(uint32_t timeout_ms, FlushCallback callback) override { @@ -444,7 +427,7 @@ class ConsumerEndpoint : public perfetto::ConsumerEndpoint, data_source.config().chrome_config().convert_to_legacy_json()) { tracing_session_host_->DisableTracingAndEmitJson( /*agent_label_filter=*/"", std::move(producer_handle), - /*privacy_filter_enabled=*/false, + data_source.config().chrome_config().privacy_filtering_enabled(), base::BindOnce(&ConsumerEndpoint::OnReadBuffersComplete, base::Unretained(this))); return; @@ -540,7 +523,7 @@ class ConsumerEndpoint : public perfetto::ConsumerEndpoint, } } - void OnTracingDisabled() override { + void OnTracingDisabled(bool tracing_succeeded) override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // TODO(skyostil): Wire up full data source state. For now Perfetto just // needs to know all data sources have stopped. @@ -551,7 +534,8 @@ class ConsumerEndpoint : public perfetto::ConsumerEndpoint, perfetto::ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED); consumer_->OnObservableEvents(events); } - consumer_->OnTracingDisabled(); + consumer_->OnTracingDisabled( + tracing_succeeded && !tracing_failed_ ? "" : kErrorTracingFailed); } // mojo::DataPipeDrainer::Client implementation: @@ -614,7 +598,7 @@ class ConsumerEndpoint : public perfetto::ConsumerEndpoint, void OnTracingFailed() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // TODO(skyostil): Inform the crew. + tracing_failed_ = true; tracing_session_host_.reset(); tracing_session_client_.reset(); drainer_.reset(); @@ -644,6 +628,7 @@ class ConsumerEndpoint : public perfetto::ConsumerEndpoint, perfetto::TraceConfig trace_config_; std::unique_ptr<TracePacketTokenizer> tokenizer_; + bool tracing_failed_ = false; bool read_buffers_complete_ = false; bool trace_data_complete_ = false; uint32_t observed_events_mask_ = 0; diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc index 9cc62e2bed2..d0c7b193964 100644 --- a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc +++ b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc @@ -12,7 +12,7 @@ #include "base/base64.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/debug/leak_annotations.h" #include "base/json/json_writer.h" @@ -48,7 +48,9 @@ #include "services/tracing/public/mojom/constants.mojom.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory_arbiter.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h" +#include "third_party/perfetto/include/perfetto/protozero/message.h" #include "third_party/perfetto/include/perfetto/tracing/track.h" +#include "third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h" #include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pbzero.h" #include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h" #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h" @@ -117,11 +119,14 @@ static_assert( // Helper class used to ensure no tasks are posted while // TraceEventDataSource::lock_ is held. -class AutoLockWithDeferredTaskPosting { +class SCOPED_LOCKABLE AutoLockWithDeferredTaskPosting { public: explicit AutoLockWithDeferredTaskPosting(base::Lock& lock) + EXCLUSIVE_LOCK_FUNCTION(lock) : autolock_(lock) {} + ~AutoLockWithDeferredTaskPosting() UNLOCK_FUNCTION() = default; + private: // The ordering is important: |defer_task_posting_| must be destroyed // after |autolock_| to ensure the lock is not held when any deferred @@ -157,7 +162,10 @@ TraceEventMetadataSource::~TraceEventMetadataSource() = default; void TraceEventMetadataSource::AddGeneratorFunction( JsonMetadataGeneratorFunction generator) { DCHECK(origin_task_runner_->RunsTasksInCurrentSequence()); - json_generator_functions_.push_back(generator); + { + base::AutoLock lock(lock_); + json_generator_functions_.push_back(generator); + } // An EventBundle is created when nullptr is passed. GenerateJsonMetadataFromGenerator(generator, nullptr); } @@ -165,12 +173,26 @@ void TraceEventMetadataSource::AddGeneratorFunction( void TraceEventMetadataSource::AddGeneratorFunction( MetadataGeneratorFunction generator) { DCHECK(origin_task_runner_->RunsTasksInCurrentSequence()); - generator_functions_.push_back(generator); + { + base::AutoLock lock(lock_); + generator_functions_.push_back(generator); + } GenerateMetadataFromGenerator(generator); } +void TraceEventMetadataSource::AddGeneratorFunction( + PacketGeneratorFunction generator) { + DCHECK(origin_task_runner_->RunsTasksInCurrentSequence()); + { + base::AutoLock lock(lock_); + packet_generator_functions_.push_back(generator); + } + GenerateMetadataPacket(generator); +} + std::unique_ptr<base::DictionaryValue> TraceEventMetadataSource::GenerateTraceConfigMetadataDict() { + AutoLockWithDeferredTaskPosting lock(lock_); if (chrome_config_.empty()) { return nullptr; } @@ -209,6 +231,22 @@ void TraceEventMetadataSource::GenerateMetadataFromGenerator( generator.Run(chrome_metadata, privacy_filtering_enabled_); } +void TraceEventMetadataSource::GenerateMetadataPacket( + const TraceEventMetadataSource::PacketGeneratorFunction& generator) { + DCHECK(origin_task_runner_->RunsTasksInCurrentSequence()); + perfetto::TraceWriter::TracePacketHandle trace_packet; + { + AutoLockWithDeferredTaskPosting lock(lock_); + if (!emit_metadata_at_start_ || !trace_writer_) + return; + trace_packet = trace_writer_->NewTracePacket(); + } + trace_packet->set_timestamp( + TRACE_TIME_TICKS_NOW().since_origin().InNanoseconds()); + trace_packet->set_timestamp_clock_id(kTraceClockId); + generator.Run(trace_packet.get(), privacy_filtering_enabled_); +} + void TraceEventMetadataSource::GenerateJsonMetadataFromGenerator( const TraceEventMetadataSource::JsonMetadataGeneratorFunction& generator, ChromeEventBundle* event_bundle) { @@ -256,7 +294,12 @@ TraceEventMetadataSource::GenerateLegacyMetadataDict() { DCHECK(!privacy_filtering_enabled_); auto merged_metadata = std::make_unique<base::DictionaryValue>(); - for (auto& generator : json_generator_functions_) { + std::vector<JsonMetadataGeneratorFunction> json_generators; + { + base::AutoLock lock(lock_); + json_generators = json_generator_functions_; + } + for (auto& generator : json_generators) { std::unique_ptr<base::DictionaryValue> metadata_dict = generator.Run(); if (!metadata_dict) { continue; @@ -286,16 +329,29 @@ void TraceEventMetadataSource::GenerateMetadata( json_generators, std::unique_ptr< std::vector<TraceEventMetadataSource::MetadataGeneratorFunction>> - proto_generators) { + proto_generators, + std::unique_ptr< + std::vector<TraceEventMetadataSource::PacketGeneratorFunction>> + packet_generators) { DCHECK(origin_task_runner_->RunsTasksInCurrentSequence()); - TracePacketHandle trace_packet; + + perfetto::TraceWriter* trace_writer; bool privacy_filtering_enabled; { AutoLockWithDeferredTaskPosting lock(lock_); - trace_packet = trace_writer_->NewTracePacket(); + trace_writer = trace_writer_.get(); privacy_filtering_enabled = privacy_filtering_enabled_; } + for (auto& generator : *packet_generators) { + TracePacketHandle generator_trace_packet = trace_writer->NewTracePacket(); + generator_trace_packet->set_timestamp( + TRACE_TIME_TICKS_NOW().since_origin().InNanoseconds()); + generator_trace_packet->set_timestamp_clock_id(kTraceClockId); + generator.Run(generator_trace_packet.get(), privacy_filtering_enabled); + } + + TracePacketHandle trace_packet = trace_writer_->NewTracePacket(); trace_packet->set_timestamp( TRACE_TIME_TICKS_NOW().since_origin().InNanoseconds()); trace_packet->set_timestamp_clock_id(kTraceClockId); @@ -304,15 +360,17 @@ void TraceEventMetadataSource::GenerateMetadata( generator.Run(chrome_metadata, privacy_filtering_enabled); } - if (privacy_filtering_enabled) { - return; + if (!privacy_filtering_enabled) { + ChromeEventBundle* event_bundle = trace_packet->set_chrome_events(); + for (auto& generator : *json_generators) { + GenerateJsonMetadataFromGenerator(generator, event_bundle); + } } - ChromeEventBundle* event_bundle = trace_packet->set_chrome_events(); - - for (auto& generator : *json_generators) { - GenerateJsonMetadataFromGenerator(generator, event_bundle); - } + // Force flush the packet since the default flush happens at end of + // trace, and the packet can be discarded then. + trace_packet->Finalize(); + trace_writer->Flush(); } void TraceEventMetadataSource::StartTracing( @@ -322,6 +380,8 @@ void TraceEventMetadataSource::StartTracing( std::make_unique<std::vector<JsonMetadataGeneratorFunction>>(); auto proto_generators = std::make_unique<std::vector<MetadataGeneratorFunction>>(); + auto packet_generators = + std::make_unique<std::vector<PacketGeneratorFunction>>(); { AutoLockWithDeferredTaskPosting lock(lock_); privacy_filtering_enabled_ = @@ -336,6 +396,7 @@ void TraceEventMetadataSource::StartTracing( emit_metadata_at_start_ = true; *json_generators = json_generator_functions_; *proto_generators = generator_functions_; + *packet_generators = packet_generator_functions_; break; } case TraceRecordMode::RECORD_CONTINUOUSLY: @@ -351,7 +412,8 @@ void TraceEventMetadataSource::StartTracing( FROM_HERE, base::BindOnce(&TraceEventMetadataSource::GenerateMetadata, base::Unretained(this), std::move(json_generators), - std::move(proto_generators))); + std::move(proto_generators), + std::move(packet_generators))); } void TraceEventMetadataSource::StopTracing( @@ -369,9 +431,13 @@ void TraceEventMetadataSource::StopTracing( auto proto_generators = std::make_unique<std::vector<MetadataGeneratorFunction>>(); *proto_generators = generator_functions_; + auto packet_generators = + std::make_unique<std::vector<PacketGeneratorFunction>>(); + *packet_generators = packet_generator_functions_; maybe_generate_task = base::BindOnce( &TraceEventMetadataSource::GenerateMetadata, base::Unretained(this), - std::move(json_generators), std::move(proto_generators)); + std::move(json_generators), std::move(proto_generators), + std::move(packet_generators)); } } // Even when not generating metadata, make sure the metadata generate task @@ -1051,6 +1117,24 @@ void TraceEventDataSource::FlushCurrentThread() { } } +namespace { + +struct InternedHistogramName + : public perfetto::TrackEventInternedDataIndex< + InternedHistogramName, + perfetto::protos::pbzero::InternedData::kHistogramNamesFieldNumber, + std::string> { + static void Add(perfetto::protos::pbzero::InternedData* interned_data, + size_t iid, + const std::string& histogram_name) { + auto* msg = interned_data->add_histogram_names(); + msg->set_iid(iid); + msg->set_name(histogram_name); + } +}; + +} // namespace + // static void TraceEventDataSource::OnMetricsSampleCallback( const char* histogram_name, @@ -1066,7 +1150,8 @@ void TraceEventDataSource::OnMetricsSampleCallback( new_sample->set_name_hash(name_hash); new_sample->set_sample(sample); if (!privacy_filtering_enabled) { - new_sample->set_name(histogram_name); + size_t iid = InternedHistogramName::Get(&ctx, histogram_name); + new_sample->set_name_iid(iid); } }); } @@ -1127,21 +1212,39 @@ void TraceEventDataSource::EmitTrackDescriptor() { // mojo message which can result in additional trace events). AutoThreadLocalBoolean thread_is_in_trace_event(GetThreadIsInTraceEventTLS()); - AutoLockWithDeferredTaskPosting lock(lock_); + // It's safe to use this writer outside the lock because EmitTrackDescriptor() + // is either called (a) when startup tracing is set up (from the main thread) + // or (b) on the perfetto sequence. (a) is safe because the writer will not be + // destroyed before startup tracing set up is complete. (b) is safe because + // the writer is only destroyed on the perfetto sequence in this case. + perfetto::TraceWriter* writer; + bool privacy_filtering_enabled; +#if defined(OS_ANDROID) + bool is_system_producer; +#endif // defined(OS_ANDROID) + { + AutoLockWithDeferredTaskPosting lock(lock_); + writer = trace_writer_.get(); + privacy_filtering_enabled = privacy_filtering_enabled_; +#if defined(OS_ANDROID) + is_system_producer = + producer_ == PerfettoTracedProcess::Get()->system_producer(); +#endif // defined(OS_ANDROID) + } - int process_id = TraceLog::GetInstance()->process_id(); - if (process_id == base::kNullProcessId) { - // Do not emit descriptor without process id. + if (!writer) { return; } - if (!trace_writer_) { + int process_id = TraceLog::GetInstance()->process_id(); + if (process_id == base::kNullProcessId) { + // Do not emit descriptor without process id. return; } std::string process_name = TraceLog::GetInstance()->process_name(); - TracePacketHandle trace_packet = trace_writer_->NewTracePacket(); + TracePacketHandle trace_packet = writer->NewTracePacket(); trace_packet->set_sequence_flags( perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED); @@ -1160,7 +1263,7 @@ void TraceEventDataSource::EmitTrackDescriptor() { ProcessDescriptor* process = track_descriptor->set_process(); process->set_pid(process_id); - if (!privacy_filtering_enabled_ && !process_name.empty()) { + if (!privacy_filtering_enabled && !process_name.empty()) { process->set_process_name(process_name); } @@ -1174,8 +1277,7 @@ void TraceEventDataSource::EmitTrackDescriptor() { #if defined(OS_ANDROID) // Host app package name is only recorded if privacy filtering is disabled or // this is a system trace. - if (!privacy_filtering_enabled_ || - producer_ == PerfettoTracedProcess::Get()->system_producer()) { + if (!privacy_filtering_enabled || is_system_producer) { // Host app package name is used to group information from different // processes that "belong" to the same WebView app. // TODO(b/161983088): only write this for WebView since this information is @@ -1191,7 +1293,7 @@ void TraceEventDataSource::EmitTrackDescriptor() { // TODO(eseckler): Set other fields on |chrome_process|. trace_packet = TracePacketHandle(); - trace_writer_->Flush(); + writer->Flush(); } bool TraceEventDataSource::IsPrivacyFilteringEnabled() { diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.h b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.h index 020080f842c..dfbdd6210e9 100644 --- a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.h +++ b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.h @@ -71,12 +71,17 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventMetadataSource perfetto::protos::pbzero::ChromeMetadataPacket*, bool /* privacy_filtering_enabled */)>; + using PacketGeneratorFunction = + base::RepeatingCallback<void(perfetto::protos::pbzero::TracePacket*, + bool /* privacy_filtering_enabled */)>; + // Any callbacks passed here will be called when tracing. Note that if tracing // is enabled while calling this method, the callback may be invoked // directly. void AddGeneratorFunction(JsonMetadataGeneratorFunction generator); // Same as above, but for filling in proto format. void AddGeneratorFunction(MetadataGeneratorFunction generator); + void AddGeneratorFunction(PacketGeneratorFunction generator); // For background tracing, the legacy crash uploader needs // metadata fields to be uploaded as POST args in addition to being // embedded in the trace. TODO(oysteine): Remove when only the @@ -102,26 +107,35 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventMetadataSource void GenerateMetadata( std::unique_ptr<std::vector<JsonMetadataGeneratorFunction>> json_generators, - std::unique_ptr<std::vector<MetadataGeneratorFunction>> proto_generators); + std::unique_ptr<std::vector<MetadataGeneratorFunction>> proto_generators, + std::unique_ptr<std::vector<PacketGeneratorFunction>> packet_generators); void GenerateMetadataFromGenerator( const MetadataGeneratorFunction& generator); void GenerateJsonMetadataFromGenerator( const JsonMetadataGeneratorFunction& generator, perfetto::protos::pbzero::ChromeEventBundle* event_bundle); + void GenerateMetadataPacket( + const TraceEventMetadataSource::PacketGeneratorFunction& generator); std::unique_ptr<base::DictionaryValue> GenerateTraceConfigMetadataDict(); // All members are protected by |lock_|. + // TODO(crbug.com/1138893): Change annotations to GUARDED_BY base::Lock lock_; - std::vector<JsonMetadataGeneratorFunction> json_generator_functions_; - std::vector<MetadataGeneratorFunction> generator_functions_; - - const scoped_refptr<base::SequencedTaskRunner> origin_task_runner_; - - std::unique_ptr<perfetto::TraceWriter> trace_writer_; - bool privacy_filtering_enabled_ = false; - std::string chrome_config_; - std::unique_ptr<base::trace_event::TraceConfig> parsed_chrome_config_; - bool emit_metadata_at_start_ = false; + std::vector<JsonMetadataGeneratorFunction> json_generator_functions_ + GUARDED_BY(lock_); + std::vector<MetadataGeneratorFunction> generator_functions_ GUARDED_BY(lock_); + std::vector<PacketGeneratorFunction> packet_generator_functions_ + GUARDED_BY(lock_); + + const scoped_refptr<base::SequencedTaskRunner> origin_task_runner_ + GUARDED_BY_FIXME(lock_); + + std::unique_ptr<perfetto::TraceWriter> trace_writer_ GUARDED_BY_FIXME(lock_); + bool privacy_filtering_enabled_ GUARDED_BY_FIXME(lock_) = false; + std::string chrome_config_ GUARDED_BY(lock_); + std::unique_ptr<base::trace_event::TraceConfig> parsed_chrome_config_ + GUARDED_BY(lock_); + bool emit_metadata_at_start_ GUARDED_BY(lock_) = false; DISALLOW_COPY_AND_ASSIGN(TraceEventMetadataSource); }; diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc index b3090213e54..e8032e454aa 100644 --- a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc +++ b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc @@ -26,6 +26,7 @@ #include "base/threading/thread_id_name_manager.h" #include "base/threading/thread_restrictions.h" #include "base/time/time.h" +#include "base/trace_event/task_execution_macros.h" #include "base/trace_event/thread_instruction_count.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_log.h" @@ -1018,20 +1019,17 @@ TEST_F(TraceEventDataSourceTest, EventWithConvertableArgs) { TEST_F(TraceEventDataSourceTest, TaskExecutionEvent) { CreateTraceEventDataSource(); - INTERNAL_TRACE_EVENT_ADD( - TRACE_EVENT_PHASE_INSTANT, "toplevel", "ThreadControllerImpl::RunTask", - TRACE_EVENT_SCOPE_THREAD | TRACE_EVENT_FLAG_TYPED_PROTO_ARGS, "src_file", - "my_file", "src_func", "my_func"); - INTERNAL_TRACE_EVENT_ADD( - TRACE_EVENT_PHASE_INSTANT, "toplevel", "ThreadControllerImpl::RunTask", - TRACE_EVENT_SCOPE_THREAD | TRACE_EVENT_FLAG_TYPED_PROTO_ARGS, "src_file", - "my_file", "src_func", "my_func"); + base::PendingTask task; + task.posted_from = + base::Location("my_func", "my_file", 0, /*program_counter=*/&task); + { TRACE_TASK_EXECUTION("ThreadControllerImpl::RunTask1", task); } + { TRACE_TASK_EXECUTION("ThreadControllerImpl::RunTask1", task); } size_t packet_index = ExpectStandardPreamble(); auto* e_packet = producer_client()->GetFinalizedPacket(packet_index++); ExpectTraceEvent(e_packet, /*category_iid=*/1u, /*name_iid=*/1u, - TRACE_EVENT_PHASE_INSTANT, TRACE_EVENT_SCOPE_THREAD); + TRACE_EVENT_PHASE_BEGIN); const auto& annotations = e_packet->track_event().debug_annotations(); EXPECT_EQ(annotations.size(), 0); @@ -1043,9 +1041,9 @@ TEST_F(TraceEventDataSourceTest, TaskExecutionEvent) { EXPECT_EQ(locations[0].function_name(), "my_func"); // Second event should refer to the same interning entries. - auto* e_packet2 = producer_client()->GetFinalizedPacket(packet_index++); + auto* e_packet2 = producer_client()->GetFinalizedPacket(++packet_index); ExpectTraceEvent(e_packet2, /*category_iid=*/1u, /*name_iid=*/1u, - TRACE_EVENT_PHASE_INSTANT, TRACE_EVENT_SCOPE_THREAD); + TRACE_EVENT_PHASE_BEGIN); EXPECT_EQ(e_packet2->track_event().task_execution().posted_from_iid(), 1u); EXPECT_EQ(e_packet2->interned_data().source_locations().size(), 0); @@ -1054,16 +1052,16 @@ TEST_F(TraceEventDataSourceTest, TaskExecutionEvent) { TEST_F(TraceEventDataSourceTest, TaskExecutionEventWithoutFunction) { CreateTraceEventDataSource(); - INTERNAL_TRACE_EVENT_ADD( - TRACE_EVENT_PHASE_INSTANT, "toplevel", "ThreadControllerImpl::RunTask", - TRACE_EVENT_SCOPE_THREAD | TRACE_EVENT_FLAG_TYPED_PROTO_ARGS, "src", - "my_file"); + base::PendingTask task; + task.posted_from = base::Location(/*function_name=*/nullptr, "my_file", 0, + /*program_counter=*/&task); + { TRACE_TASK_EXECUTION("ThreadControllerImpl::RunTask", task); } size_t packet_index = ExpectStandardPreamble(); auto* e_packet = producer_client()->GetFinalizedPacket(packet_index++); ExpectTraceEvent(e_packet, /*category_iid=*/1u, /*name_iid=*/1u, - TRACE_EVENT_PHASE_INSTANT, TRACE_EVENT_SCOPE_THREAD); + TRACE_EVENT_PHASE_BEGIN, TRACE_EVENT_SCOPE_THREAD); const auto& annotations = e_packet->track_event().debug_annotations(); EXPECT_EQ(annotations.size(), 0); @@ -1930,9 +1928,11 @@ TEST_F(TraceEventDataSourceTest, HistogramSampleTraceConfigEmpty) { {{1u, TRACE_DISABLED_BY_DEFAULT("histogram_samples")}}); ExpectEventNames(e_packet, {{1u, "HistogramSample"}}); ASSERT_TRUE(e_packet->track_event().has_chrome_histogram_sample()); - EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_hash(), - base::HashMetricName("Foo.Bar")); EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().sample(), 1u); + ASSERT_TRUE(e_packet->has_interned_data()); + EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_iid(), + e_packet->interned_data().histogram_names()[0].iid()); + EXPECT_EQ(e_packet->interned_data().histogram_names()[0].name(), "Foo.Bar"); } TEST_F(TraceEventDataSourceTest, HistogramSampleTraceConfigNotEmpty) { @@ -1959,9 +1959,11 @@ TEST_F(TraceEventDataSourceTest, HistogramSampleTraceConfigNotEmpty) { ASSERT_TRUE(e_packet->track_event().has_chrome_histogram_sample()); EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_hash(), base::HashMetricName("Foo1.Bar1")); - EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name(), - "Foo1.Bar1"); EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().sample(), 1u); + ASSERT_TRUE(e_packet->has_interned_data()); + EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_iid(), + e_packet->interned_data().histogram_names()[0].iid()); + EXPECT_EQ(e_packet->interned_data().histogram_names()[0].name(), "Foo1.Bar1"); e_packet = producer_client()->GetFinalizedPacket(packet_index++); @@ -1970,9 +1972,11 @@ TEST_F(TraceEventDataSourceTest, HistogramSampleTraceConfigNotEmpty) { ASSERT_TRUE(e_packet->track_event().has_chrome_histogram_sample()); EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_hash(), base::HashMetricName("Foo3.Bar3")); - EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name(), - "Foo3.Bar3"); EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().sample(), 1u); + ASSERT_TRUE(e_packet->has_interned_data()); + EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_iid(), + e_packet->interned_data().histogram_names()[0].iid()); + EXPECT_EQ(e_packet->interned_data().histogram_names()[0].name(), "Foo3.Bar3"); EXPECT_EQ(packet_index, producer_client()->GetFinalizedPacketCount()); } diff --git a/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc b/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc index 38ee903e334..75d5d5218a6 100644 --- a/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc +++ b/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc @@ -67,12 +67,6 @@ constexpr uint64_t kAbsoluteThreadTimeTrackUuidBit = static_cast<uint64_t>(1u) constexpr uint64_t kThreadInstructionCountTrackUuidBit = static_cast<uint64_t>(1u) << 34; -// Names of events that should be converted into a TaskExecution event. -const char* kTaskExecutionEventCategory = "toplevel"; -const char* kTaskExecutionEventNames[3] = {"ThreadControllerImpl::RunTask", - "ThreadPool_RunTask", - "SimpleAlarmTimer::OnTimerFired"}; - void AddConvertableToTraceFormat( base::trace_event::ConvertableToTraceFormat* value, perfetto::protos::pbzero::DebugAnnotation* annotation) { @@ -474,13 +468,6 @@ TrackEvent* TrackEventThreadLocalEventSink::PrepareTrackEvent( const size_t kMaxSize = base::trace_event::TraceArguments::kMaxSize; InterningIndexEntry interned_annotation_names[kMaxSize] = { InterningIndexEntry{}}; - InterningIndexEntry interned_source_location{}; - InterningIndexEntry interned_log_message_body{}; - - const char* src_file = nullptr; - const char* src_func = nullptr; - const char* log_message_body = nullptr; - int line_number = 0; // No need to write the event name for end events (sync or nestable async). // Trace processor will match them without, provided event nesting is correct. @@ -510,49 +497,8 @@ TrackEvent* TrackEventThreadLocalEventSink::PrepareTrackEvent( } } } else { - // TODO(eseckler): Remove special handling of typed events here once we - // support them in TRACE_EVENT macros. - if (flags & TRACE_EVENT_FLAG_TYPED_PROTO_ARGS) { - if (trace_event->arg_size() == 2u) { - DCHECK_EQ(strcmp(category_name, kTaskExecutionEventCategory), 0); - DCHECK(strcmp(trace_event->name(), kTaskExecutionEventNames[0]) == 0 || - strcmp(trace_event->name(), kTaskExecutionEventNames[1]) == 0 || - strcmp(trace_event->name(), kTaskExecutionEventNames[2]) == 0); - // Double argument task execution event (src_file, src_func). - DCHECK_EQ(trace_event->arg_type(0), TRACE_VALUE_TYPE_STRING); - DCHECK_EQ(trace_event->arg_type(1), TRACE_VALUE_TYPE_STRING); - src_file = trace_event->arg_value(0).as_string; - src_func = trace_event->arg_value(1).as_string; - } else { - // arg_size == 1 enforced by the maximum number of parameter == 2. - DCHECK_EQ(trace_event->arg_size(), 1u); - - if (trace_event->arg_type(0) == TRACE_VALUE_TYPE_STRING) { - // Single argument task execution event (src_file). - DCHECK_EQ(strcmp(category_name, kTaskExecutionEventCategory), 0); - DCHECK( - strcmp(trace_event->name(), kTaskExecutionEventNames[0]) == 0 || - strcmp(trace_event->name(), kTaskExecutionEventNames[1]) == 0 || - strcmp(trace_event->name(), kTaskExecutionEventNames[2]) == 0); - src_file = trace_event->arg_value(0).as_string; - } else { - DCHECK_EQ(trace_event->arg_type(0), TRACE_VALUE_TYPE_CONVERTABLE); - DCHECK(strcmp(category_name, "log") == 0); - DCHECK(strcmp(trace_event->name(), "LogMessage") == 0); - const base::trace_event::LogMessage* value = - static_cast<base::trace_event::LogMessage*>( - trace_event->arg_value(0).as_convertable); - src_file = value->file(); - line_number = value->line_number(); - log_message_body = value->message().c_str(); - - interned_log_message_body = - interned_log_message_bodies_.LookupOrAdd(value->message()); - } // else - } // else - interned_source_location = interned_source_locations_.LookupOrAdd( - std::make_tuple(src_file, src_func, line_number)); + NOTREACHED(); } else if (!privacy_filtering_enabled_) { for (size_t i = 0; i < trace_event->arg_size() && trace_event->arg_name(i); ++i) { @@ -626,14 +572,7 @@ TrackEvent* TrackEventThreadLocalEventSink::PrepareTrackEvent( track_event->add_category_iids(interned_category.id); } - if (interned_log_message_body.id) { - auto* log_message = track_event->set_log_message(); - log_message->set_source_location_iid(interned_source_location.id); - log_message->set_body_iid(interned_log_message_body.id); - } else if (interned_source_location.id) { - track_event->set_task_execution()->set_posted_from_iid( - interned_source_location.id); - } else if (!privacy_filtering_enabled_) { + if (!privacy_filtering_enabled_) { WriteDebugAnnotations(trace_event, track_event, interned_annotation_names); } @@ -796,19 +735,7 @@ TrackEvent* TrackEventThreadLocalEventSink::PrepareTrackEvent( std::make_tuple(IndexType::kName, IndexData{trace_event_name}, std::move(interned_name))); } - if (interned_log_message_body.id && !interned_log_message_body.was_emitted) { - pending_interning_updates_.push_back( - std::make_tuple(IndexType::kLogMessage, IndexData{log_message_body}, - std::move(interned_log_message_body))); - } - if (interned_source_location.id) { - if (!interned_source_location.was_emitted) { - pending_interning_updates_.push_back(std::make_tuple( - IndexType::kSourceLocation, - IndexData{std::make_tuple(src_file, src_func, line_number)}, - std::move(interned_source_location))); - } - } else if (!privacy_filtering_enabled_) { + if (!privacy_filtering_enabled_) { for (size_t i = 0; i < trace_event->arg_size() && trace_event->arg_name(i); ++i) { DCHECK(interned_annotation_names[i].id); diff --git a/chromium/services/tracing/public/cpp/stack_sampling/loader_lock_sampler_win_unittest.cc b/chromium/services/tracing/public/cpp/stack_sampling/loader_lock_sampler_win_unittest.cc index 5fd8a91f614..f11034230d1 100644 --- a/chromium/services/tracing/public/cpp/stack_sampling/loader_lock_sampler_win_unittest.cc +++ b/chromium/services/tracing/public/cpp/stack_sampling/loader_lock_sampler_win_unittest.cc @@ -10,7 +10,7 @@ #include "base/scoped_native_library.h" #include "base/strings/string16.h" #include "base/task/thread_pool.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/test/test_timeouts.h" #include "base/test/test_waitable_event.h" diff --git a/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc b/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc index df055a82a56..3af3762382f 100644 --- a/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc +++ b/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc @@ -12,7 +12,7 @@ #include "base/android/reached_code_profiler.h" #include "base/base_switches.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/run_loop.h" #include "base/test/task_environment.h" #include "base/time/time.h" diff --git a/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc b/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc index 1a4fe1e5fbf..4e9c840eeff 100644 --- a/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc +++ b/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc @@ -9,7 +9,7 @@ #include "base/android/library_loader/anchor_functions.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/debug/leak_annotations.h" #include "base/debug/stack_trace.h" #include "base/hash/hash.h" diff --git a/chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc b/chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc index eab6ffc9823..6af92339362 100644 --- a/chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc +++ b/chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc @@ -24,10 +24,10 @@ struct AllowlistEntry { const char* const* arg_name_filter; }; -const char* const kScopedBlockingCallAllowedArgs[] = {"file_name", - "function_name", nullptr}; +const char* const kScopedBlockingCallAllowedArgs[] = { + "file_name", "function_name", "source_location", nullptr}; const char* const kPeekMessageAllowedArgs[] = {"sent_messages_in_queue", - nullptr}; + "chrome_message_pump", nullptr}; const char* const kFallbackFontAllowedArgs[] = {"font_name", "primary_font_name", nullptr}; const char* const kGetFallbackFontsAllowedArgs[] = {"script", nullptr}; @@ -38,7 +38,8 @@ const char* const kMemoryDumpAllowedArgs[] = { const char* const kRendererHostAllowedArgs[] = { "class", "line", "should_background", "has_pending_views", "bytes_allocated", nullptr}; -const char* const kUIAllowedArgs[] = {"dpi", "message_id", nullptr}; +const char* const kUIAllowedArgs[] = { + "dpi", "message_id", "chrome_window_handle_event_info", nullptr}; const char* const kV8GCAllowedArgs[] = {"num_items", "num_tasks", nullptr}; const char* const kTopLevelFlowAllowedArgs[] = {"task_queue_name", nullptr}; const char* const kTopLevelIpcRunTaskAllowedArgs[] = {"ipc_hash", nullptr}; diff --git a/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.cc b/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.cc index 428b71e4da2..f6107943183 100644 --- a/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.cc +++ b/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.cc @@ -18,6 +18,23 @@ bool StructTraits< } out->set_trace_config(std::move(config)); out->set_privacy_filtering_enabled(data.privacy_filtering_enabled()); + out->set_convert_to_legacy_json(data.convert_to_legacy_json()); + switch (data.client_priority()) { + case tracing::mojom::TracingClientPriority::kBackground: + out->set_client_priority(perfetto::protos::gen::ChromeConfig::BACKGROUND); + break; + case tracing::mojom::TracingClientPriority::kUserInitiated: + out->set_client_priority( + perfetto::protos::gen::ChromeConfig::USER_INITIATED); + break; + case tracing::mojom::TracingClientPriority::kUnknown: + out->set_client_priority(perfetto::protos::gen::ChromeConfig::UNKNOWN); + break; + default: + NOTREACHED(); + break; + } + return true; } } // namespace mojo diff --git a/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.h b/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.h index 87729c34656..b800726923b 100644 --- a/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.h +++ b/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.h @@ -27,6 +27,25 @@ class StructTraits<tracing::mojom::ChromeConfigDataView, return src.privacy_filtering_enabled(); } + static bool convert_to_legacy_json(const perfetto::ChromeConfig& src) { + return src.convert_to_legacy_json(); + } + + static tracing::mojom::TracingClientPriority client_priority( + const perfetto::ChromeConfig& src) { + switch (src.client_priority()) { + case perfetto::protos::gen::ChromeConfig::BACKGROUND: + return tracing::mojom::TracingClientPriority::kBackground; + case perfetto::protos::gen::ChromeConfig::USER_INITIATED: + return tracing::mojom::TracingClientPriority::kUserInitiated; + case perfetto::protos::gen::ChromeConfig::UNKNOWN: + return tracing::mojom::TracingClientPriority::kUnknown; + default: + NOTREACHED(); + return tracing::mojom::TracingClientPriority::kUnknown; + } + } + static bool Read(tracing::mojom::ChromeConfigDataView data, perfetto::ChromeConfig* out); }; diff --git a/chromium/services/tracing/public/mojom/perfetto_service.mojom b/chromium/services/tracing/public/mojom/perfetto_service.mojom index 790c636bc47..fe29811546f 100644 --- a/chromium/services/tracing/public/mojom/perfetto_service.mojom +++ b/chromium/services/tracing/public/mojom/perfetto_service.mojom @@ -12,6 +12,7 @@ module tracing.mojom; // particular interest is PosixSystemProducer::ConnectSocket(). const string kPerfettoProducerNamePrefix = "org.chromium-"; const string kTraceEventDataSourceName = "org.chromium.trace_event"; +const string kMemoryInstrumentationDataSourceName = "org.chromium.memory_instrumentation"; const string kMetaDataSourceName = "org.chromium.trace_metadata"; const string kSystemTraceDataSourceName = "org.chromium.trace_system"; const string kArcTraceDataSourceName = "org.chromium.trace_arc"; @@ -85,6 +86,13 @@ struct ChromeConfig { // When enabled the data source is supposed to only emit fields in the output // proto that are guaranteed to not contain any sensitive data. bool privacy_filtering_enabled; + + // Whether the final tracing result will be converted to the legacy JSON + // format. + bool convert_to_legacy_json; + + // Priority of the tracing session. + TracingClientPriority client_priority; }; struct DataSourceConfig { @@ -228,13 +236,13 @@ interface ConsumerHost { // Note: Right now only a single concurrent tracing session is supported, // as there's no support for multiplexing enabled trace events to multiple // consumers. If a new tracing session is attempted while there's an existing - // one in progress, the relative priorities will be used to figure out which - // one to be able to (keep) tracing; if the priorities are the same, the new - // session will take precedence. + // one in progress, the relative priorities (configured through + // TracingClientPriority in the trace config) will be used to figure out + // which one to be able to (keep) tracing; if the priorities are the same, + // the new session will take precedence. EnableTracing(pending_receiver<TracingSessionHost> tracing_session_host, pending_remote<TracingSessionClient> tracing_session_client, - TraceConfig config, - TracingClientPriority priority); + TraceConfig config); }; // Represents the host side of an active tracing session. Closing this @@ -285,5 +293,5 @@ interface TracingSessionClient { // Called when tracing is disabled; initiated either by a call to // TracingSessionHost::DisableTracing or by the service itself if a timeout is // specified in the tracing config. - OnTracingDisabled(); + OnTracingDisabled(bool tracing_succeeded); }; diff --git a/chromium/services/tracing/tracing_service_unittest.cc b/chromium/services/tracing/tracing_service_unittest.cc index 6e5cb97b84b..9c725f42ce3 100644 --- a/chromium/services/tracing/tracing_service_unittest.cc +++ b/chromium/services/tracing/tracing_service_unittest.cc @@ -10,7 +10,7 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/test/test_simple_task_runner.h" @@ -145,8 +145,7 @@ class TestTracingClient : public mojom::TracingSessionClient { consumer_host_->EnableTracing( tracing_session_host_.BindNewPipeAndPassReceiver(), - receiver_.BindNewPipeAndPassRemote(), std::move(perfetto_config), - tracing::mojom::TracingClientPriority::kUserInitiated); + receiver_.BindNewPipeAndPassRemote(), std::move(perfetto_config)); tracing_session_host_->RequestBufferUsage( base::BindOnce([](base::OnceClosure on_response, bool, float, @@ -161,7 +160,7 @@ class TestTracingClient : public mojom::TracingSessionClient { // tracing::mojom::TracingSessionClient implementation: void OnTracingEnabled() override {} - void OnTracingDisabled() override { + void OnTracingDisabled(bool) override { std::move(tracing_disabled_callback_).Run(); } diff --git a/chromium/services/video_capture/BUILD.gn b/chromium/services/video_capture/BUILD.gn index ab42cb1cfb6..6cd31bf31aa 100644 --- a/chromium/services/video_capture/BUILD.gn +++ b/chromium/services/video_capture/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//testing/test.gni") source_set("lib") { @@ -52,9 +53,12 @@ source_set("lib") { "//services/viz/public/cpp/gpu", ] - deps = [ "//media/capture:capture_switches" ] + deps = [ + "//build:chromeos_buildflags", + "//media/capture:capture_switches", + ] - if (is_chromeos) { + if (is_ash) { public_deps += [ "//media/capture/video/chromeos/mojom:cros_camera" ] } } @@ -89,6 +93,7 @@ source_set("tests") { deps = [ ":lib", "//base/test:test_support", + "//build:chromeos_buildflags", "//media/capture:test_support", "//media/capture/mojom:video_capture", "//services/video_capture/public/cpp:mocks", diff --git a/chromium/services/video_capture/DIR_METADATA b/chromium/services/video_capture/DIR_METADATA new file mode 100644 index 00000000000..f49aeaf0153 --- /dev/null +++ b/chromium/services/video_capture/DIR_METADATA @@ -0,0 +1,12 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Blink>GetUserMedia" +} +team_email: "webrtc-dev@chromium.org"
\ No newline at end of file diff --git a/chromium/services/video_capture/OWNERS b/chromium/services/video_capture/OWNERS index 7e7e66b5640..a7bd3877e21 100644 --- a/chromium/services/video_capture/OWNERS +++ b/chromium/services/video_capture/OWNERS @@ -3,6 +3,3 @@ guidou@chromium.org # Original (legacy) owners. chfremer@chromium.org per-file *video*=mcasas@chromium.org - -# COMPONENT: Blink>GetUserMedia -# TEAM: webrtc-dev@chromium.org diff --git a/chromium/services/video_capture/device_factory_media_to_mojo_adapter.cc b/chromium/services/video_capture/device_factory_media_to_mojo_adapter.cc index 0cf87aabcd9..03666620b6a 100644 --- a/chromium/services/video_capture/device_factory_media_to_mojo_adapter.cc +++ b/chromium/services/video_capture/device_factory_media_to_mojo_adapter.cc @@ -11,6 +11,7 @@ #include "base/notreached.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" +#include "build/chromeos_buildflags.h" #include "media/capture/video/fake_video_capture_device.h" #include "media/capture/video/video_capture_device_info.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -79,7 +80,7 @@ DeviceFactoryMediaToMojoAdapter::ActiveDeviceEntry& DeviceFactoryMediaToMojoAdapter::ActiveDeviceEntry::operator=( DeviceFactoryMediaToMojoAdapter::ActiveDeviceEntry&& other) = default; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) DeviceFactoryMediaToMojoAdapter::DeviceFactoryMediaToMojoAdapter( std::unique_ptr<media::VideoCaptureSystem> capture_system, media::MojoMjpegDecodeAcceleratorFactoryCB jpeg_decoder_factory_callback, @@ -94,7 +95,7 @@ DeviceFactoryMediaToMojoAdapter::DeviceFactoryMediaToMojoAdapter( std::unique_ptr<media::VideoCaptureSystem> capture_system) : capture_system_(std::move(capture_system)), has_called_get_device_infos_(false) {} -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) DeviceFactoryMediaToMojoAdapter::~DeviceFactoryMediaToMojoAdapter() = default; @@ -184,14 +185,14 @@ void DeviceFactoryMediaToMojoAdapter::CreateAndAddNewDevice( // Add entry to active_devices to keep track of it ActiveDeviceEntry device_entry; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) device_entry.device = std::make_unique<DeviceMediaToMojoAdapter>( std::move(media_device), jpeg_decoder_factory_callback_, jpeg_decoder_task_runner_); #else device_entry.device = std::make_unique<DeviceMediaToMojoAdapter>(std::move(media_device)); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) device_entry.receiver = std::make_unique<mojo::Receiver<mojom::Device>>( device_entry.device.get(), std::move(device_receiver)); device_entry.receiver->set_disconnect_handler(base::BindOnce( diff --git a/chromium/services/video_capture/device_factory_media_to_mojo_adapter.h b/chromium/services/video_capture/device_factory_media_to_mojo_adapter.h index e66bf251861..785cd74c85d 100644 --- a/chromium/services/video_capture/device_factory_media_to_mojo_adapter.h +++ b/chromium/services/video_capture/device_factory_media_to_mojo_adapter.h @@ -6,6 +6,7 @@ #define SERVICES_VIDEO_CAPTURE_DEVICE_FACTORY_MEDIA_TO_MOJO_ADAPTER_H_ #include <map> +#include "build/chromeos_buildflags.h" #include "media/capture/video/video_capture_device_client.h" #include "media/capture/video/video_capture_system.h" @@ -15,9 +16,9 @@ #include "services/video_capture/device_factory.h" #include "services/video_capture/public/mojom/devices_changed_observer.mojom.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) namespace video_capture { @@ -29,7 +30,7 @@ class DeviceMediaToMojoAdapter; // same media::VideoCaptureDevice at the same time. class DeviceFactoryMediaToMojoAdapter : public DeviceFactory { public: -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) DeviceFactoryMediaToMojoAdapter( std::unique_ptr<media::VideoCaptureSystem> capture_system, media::MojoMjpegDecodeAcceleratorFactoryCB jpeg_decoder_factory_callback, @@ -37,7 +38,7 @@ class DeviceFactoryMediaToMojoAdapter : public DeviceFactory { #else DeviceFactoryMediaToMojoAdapter( std::unique_ptr<media::VideoCaptureSystem> capture_system); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) ~DeviceFactoryMediaToMojoAdapter() override; // DeviceFactory implementation. @@ -86,11 +87,11 @@ class DeviceFactoryMediaToMojoAdapter : public DeviceFactory { const std::unique_ptr<media::VideoCaptureSystem> capture_system_; std::map<std::string, ActiveDeviceEntry> active_devices_by_id_; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) const media::MojoMjpegDecodeAcceleratorFactoryCB jpeg_decoder_factory_callback_; scoped_refptr<base::SequencedTaskRunner> jpeg_decoder_task_runner_; -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) bool has_called_get_device_infos_; base::WeakPtrFactory<DeviceFactoryMediaToMojoAdapter> weak_factory_{this}; diff --git a/chromium/services/video_capture/device_media_to_mojo_adapter.cc b/chromium/services/video_capture/device_media_to_mojo_adapter.cc index 70a933a0297..03d664394be 100644 --- a/chromium/services/video_capture/device_media_to_mojo_adapter.cc +++ b/chromium/services/video_capture/device_media_to_mojo_adapter.cc @@ -7,6 +7,8 @@ #include "base/bind.h" #include "base/check.h" #include "base/command_line.h" +#include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "media/base/bind_to_current_loop.h" #include "media/capture/capture_switches.h" #include "media/capture/video/video_capture_buffer_pool_impl.h" @@ -15,14 +17,14 @@ #include "mojo/public/cpp/bindings/callback_helpers.h" #include "services/video_capture/receiver_mojo_to_media_adapter.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "media/capture/video/chromeos/scoped_video_capture_jpeg_decoder.h" #include "media/capture/video/chromeos/video_capture_jpeg_decoder_impl.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) namespace { -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder( scoped_refptr<base::SequencedTaskRunner> decoder_task_runner, media::MojoMjpegDecodeAcceleratorFactoryCB jpeg_decoder_factory_callback, @@ -34,13 +36,13 @@ std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder( std::move(decode_done_cb), std::move(send_log_message_cb)), decoder_task_runner); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) } // anonymous namespace namespace video_capture { -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) DeviceMediaToMojoAdapter::DeviceMediaToMojoAdapter( std::unique_ptr<media::VideoCaptureDevice> device, media::MojoMjpegDecodeAcceleratorFactoryCB jpeg_decoder_factory_callback, @@ -53,7 +55,7 @@ DeviceMediaToMojoAdapter::DeviceMediaToMojoAdapter( DeviceMediaToMojoAdapter::DeviceMediaToMojoAdapter( std::unique_ptr<media::VideoCaptureDevice> device) : device_(std::move(device)), device_started_(false) {} -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) DeviceMediaToMojoAdapter::~DeviceMediaToMojoAdapter() { DCHECK(thread_checker_.CalledOnValidThread()); @@ -94,7 +96,7 @@ void DeviceMediaToMojoAdapter::Start( scoped_refptr<media::VideoCaptureBufferPool> buffer_pool( new media::VideoCaptureBufferPoolImpl(requested_settings.buffer_type, max_buffer_pool_buffer_count())); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) auto device_client = std::make_unique<media::VideoCaptureDeviceClient>( requested_settings.buffer_type, std::move(media_receiver), buffer_pool, base::BindRepeating( @@ -108,7 +110,7 @@ void DeviceMediaToMojoAdapter::Start( #else auto device_client = std::make_unique<media::VideoCaptureDeviceClient>( requested_settings.buffer_type, std::move(media_receiver), buffer_pool); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) device_->AllocateAndStart(requested_settings, std::move(device_client)); device_started_ = true; @@ -176,7 +178,11 @@ int DeviceMediaToMojoAdapter::max_buffer_pool_buffer_count() { // those frames get dropped. static int kMaxBufferCount = 3; -#if defined(OS_CHROMEOS) +#if defined(OS_MAC) + // On macOS, we allow a few more buffers as it's routinely observed that it + // runs out of three when just displaying 60 FPS media in a video element. + kMaxBufferCount = 10; +#elif BUILDFLAG(IS_ASH) // On Chrome OS with MIPI cameras running on HAL v3, there can be three // concurrent streams of camera pipeline depth ~6. We allow at most 30 buffers // here to take into account the delay caused by the consumer (e.g. display or diff --git a/chromium/services/video_capture/device_media_to_mojo_adapter.h b/chromium/services/video_capture/device_media_to_mojo_adapter.h index b78c403771b..2dbadbb4e12 100644 --- a/chromium/services/video_capture/device_media_to_mojo_adapter.h +++ b/chromium/services/video_capture/device_media_to_mojo_adapter.h @@ -6,6 +6,7 @@ #define SERVICES_VIDEO_CAPTURE_DEVICE_MEDIA_TO_MOJO_ADAPTER_H_ #include "base/threading/thread_checker.h" +#include "build/chromeos_buildflags.h" #include "media/capture/video/video_capture_device.h" #include "media/capture/video/video_capture_device_client.h" #include "media/capture/video/video_capture_device_factory.h" @@ -14,10 +15,10 @@ #include "services/video_capture/public/mojom/device.mojom.h" #include "services/video_capture/public/mojom/video_frame_handler.mojom.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h" #include "media/capture/video/chromeos/video_capture_jpeg_decoder.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) namespace video_capture { @@ -27,7 +28,7 @@ class ReceiverMojoToMediaAdapter; // media::VideoCaptureDevice. class DeviceMediaToMojoAdapter : public mojom::Device { public: -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) DeviceMediaToMojoAdapter( std::unique_ptr<media::VideoCaptureDevice> device, media::MojoMjpegDecodeAcceleratorFactoryCB jpeg_decoder_factory_callback, @@ -35,7 +36,7 @@ class DeviceMediaToMojoAdapter : public mojom::Device { #else DeviceMediaToMojoAdapter( std::unique_ptr<media::VideoCaptureDevice> device); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) ~DeviceMediaToMojoAdapter() override; // mojom::Device implementation. @@ -58,11 +59,11 @@ class DeviceMediaToMojoAdapter : public mojom::Device { private: const std::unique_ptr<media::VideoCaptureDevice> device_; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) const media::MojoMjpegDecodeAcceleratorFactoryCB jpeg_decoder_factory_callback_; scoped_refptr<base::SequencedTaskRunner> jpeg_decoder_task_runner_; -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) std::unique_ptr<ReceiverMojoToMediaAdapter> receiver_; bool device_started_; base::ThreadChecker thread_checker_; diff --git a/chromium/services/video_capture/device_media_to_mojo_adapter_unittest.cc b/chromium/services/video_capture/device_media_to_mojo_adapter_unittest.cc index a4d46915042..ad0a519a9aa 100644 --- a/chromium/services/video_capture/device_media_to_mojo_adapter_unittest.cc +++ b/chromium/services/video_capture/device_media_to_mojo_adapter_unittest.cc @@ -4,9 +4,10 @@ #include "services/video_capture/device_media_to_mojo_adapter.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/run_loop.h" #include "base/test/task_environment.h" +#include "build/chromeos_buildflags.h" #include "media/capture/video/mock_device.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "services/video_capture/public/cpp/mock_video_frame_handler.h" @@ -29,14 +30,14 @@ class DeviceMediaToMojoAdapterTest : public ::testing::Test { video_frame_handler_.InitWithNewPipeAndPassReceiver()); auto mock_device = std::make_unique<media::MockDevice>(); mock_device_ptr_ = mock_device.get(); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) adapter_ = std::make_unique<DeviceMediaToMojoAdapter>( std::move(mock_device), base::DoNothing(), base::ThreadTaskRunnerHandle::Get()); #else adapter_ = std::make_unique<DeviceMediaToMojoAdapter>( std::move(mock_device)); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) } void TearDown() override { diff --git a/chromium/services/video_capture/public/cpp/BUILD.gn b/chromium/services/video_capture/public/cpp/BUILD.gn index 8cead26e449..57529641229 100644 --- a/chromium/services/video_capture/public/cpp/BUILD.gn +++ b/chromium/services/video_capture/public/cpp/BUILD.gn @@ -44,4 +44,6 @@ source_set("mocks") { "//services/video_capture/public/mojom", "//testing/gmock", ] + + deps = [ "//build:chromeos_buildflags" ] } diff --git a/chromium/services/video_capture/public/cpp/mock_video_capture_service.cc b/chromium/services/video_capture/public/cpp/mock_video_capture_service.cc index 2c59db2de92..f2f941b9cc2 100644 --- a/chromium/services/video_capture/public/cpp/mock_video_capture_service.cc +++ b/chromium/services/video_capture/public/cpp/mock_video_capture_service.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "services/video_capture/public/cpp/mock_video_capture_service.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -22,12 +23,12 @@ void MockVideoCaptureService::ConnectToVideoSourceProvider( DoConnectToVideoSourceProvider(std::move(receiver)); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void MockVideoCaptureService::InjectGpuDependencies( mojo::PendingRemote<video_capture::mojom::AcceleratorFactory> accelerator_factory) { DoInjectGpuDependencies(std::move(accelerator_factory)); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) } // namespace video_capture diff --git a/chromium/services/video_capture/public/cpp/mock_video_capture_service.h b/chromium/services/video_capture/public/cpp/mock_video_capture_service.h index 76c5cc1bb9c..8b70f843b91 100644 --- a/chromium/services/video_capture/public/cpp/mock_video_capture_service.h +++ b/chromium/services/video_capture/public/cpp/mock_video_capture_service.h @@ -4,6 +4,7 @@ #ifndef SERVICES_VIDEO_CAPTURE_PUBLIC_CPP_MOCK_VIDEO_CAPTURE_SERVICE_H_ #define SERVICES_VIDEO_CAPTURE_PUBLIC_CPP_MOCK_VIDEO_CAPTURE_SERVICE_H_ +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "services/video_capture/public/mojom/video_capture_service.mojom.h" @@ -25,7 +26,7 @@ class MockVideoCaptureService mojo::PendingReceiver<video_capture::mojom::VideoSourceProvider> receiver) override; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void InjectGpuDependencies( mojo::PendingRemote<video_capture::mojom::AcceleratorFactory> accelerator_factory) override; diff --git a/chromium/services/video_capture/public/mojom/BUILD.gn b/chromium/services/video_capture/public/mojom/BUILD.gn index a31b4253ff3..7bc5add6e13 100644 --- a/chromium/services/video_capture/public/mojom/BUILD.gn +++ b/chromium/services/video_capture/public/mojom/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//mojo/public/tools/bindings/mojom.gni") mojom("mojom") { @@ -26,7 +27,7 @@ mojom("mojom") { "//ui/gfx/geometry/mojom", ] - if (is_chromeos) { + if (is_ash) { deps += [ "//components/chromeos_camera/common", "//media/capture/video/chromeos/mojom:cros_camera", diff --git a/chromium/services/video_capture/push_video_stream_subscription_impl.cc b/chromium/services/video_capture/push_video_stream_subscription_impl.cc index ebdcb01b1cb..7c2757354be 100644 --- a/chromium/services/video_capture/push_video_stream_subscription_impl.cc +++ b/chromium/services/video_capture/push_video_stream_subscription_impl.cc @@ -5,7 +5,7 @@ #include "services/video_capture/push_video_stream_subscription_impl.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "services/video_capture/broadcasting_receiver.h" namespace video_capture { diff --git a/chromium/services/video_capture/video_capture_service_impl.cc b/chromium/services/video_capture/video_capture_service_impl.cc index 27844d6f531..90a149a0f24 100644 --- a/chromium/services/video_capture/video_capture_service_impl.cc +++ b/chromium/services/video_capture/video_capture_service_impl.cc @@ -11,6 +11,7 @@ #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" #include "media/capture/video/create_video_capture_device_factory.h" #include "media/capture/video/fake_video_capture_device_factory.h" @@ -57,7 +58,7 @@ class VideoCaptureServiceImpl::GpuDependenciesContext { return gpu_io_task_runner_; } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void InjectGpuDependencies( mojo::PendingRemote<mojom::AcceleratorFactory> accelerator_factory_info) { DCHECK(gpu_io_task_runner_->RunsTasksInCurrentSequence()); @@ -73,7 +74,7 @@ class VideoCaptureServiceImpl::GpuDependenciesContext { return; accelerator_factory_->CreateJpegDecodeAccelerator(std::move(receiver)); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) private: // Task runner for operating |accelerator_factory_| and @@ -84,9 +85,9 @@ class VideoCaptureServiceImpl::GpuDependenciesContext { // operated on. scoped_refptr<base::SequencedTaskRunner> gpu_io_task_runner_; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) mojo::Remote<mojom::AcceleratorFactory> accelerator_factory_; -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) base::WeakPtrFactory<GpuDependenciesContext> weak_factory_for_gpu_io_thread_{ this}; @@ -102,7 +103,7 @@ VideoCaptureServiceImpl::~VideoCaptureServiceImpl() { factory_receivers_.Clear(); device_factory_.reset(); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) camera_app_device_bridge_.reset(); #endif // defined (OS_CHROMEOS) @@ -112,7 +113,7 @@ VideoCaptureServiceImpl::~VideoCaptureServiceImpl() { } } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void VideoCaptureServiceImpl::InjectGpuDependencies( mojo::PendingRemote<mojom::AcceleratorFactory> accelerator_factory) { LazyInitializeGpuDependenciesContext(); @@ -127,7 +128,7 @@ void VideoCaptureServiceImpl::ConnectToCameraAppDeviceBridge( DCHECK(camera_app_device_bridge_); camera_app_device_bridge_->BindReceiver(std::move(receiver)); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) void VideoCaptureServiceImpl::ConnectToDeviceFactory( mojo::PendingReceiver<mojom::DeviceFactory> receiver) { @@ -168,7 +169,7 @@ void VideoCaptureServiceImpl::LazyInitializeDeviceFactory() { // The task runner passed to CreateFactory is used for things that need to // happen on a "UI thread equivalent", e.g. obtaining screen rotation on // Chrome OS. -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) camera_app_device_bridge_ = std::make_unique<media::CameraAppDeviceBridgeImpl>(); std::unique_ptr<media::VideoCaptureDeviceFactory> media_device_factory = @@ -179,12 +180,12 @@ void VideoCaptureServiceImpl::LazyInitializeDeviceFactory() { #else std::unique_ptr<media::VideoCaptureDeviceFactory> media_device_factory = media::CreateVideoCaptureDeviceFactory(ui_task_runner_); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) auto video_capture_system = std::make_unique<media::VideoCaptureSystemImpl>( std::move(media_device_factory)); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) device_factory_ = std::make_unique<VirtualDeviceEnabledDeviceFactory>( std::make_unique<DeviceFactoryMediaToMojoAdapter>( std::move(video_capture_system), @@ -196,7 +197,7 @@ void VideoCaptureServiceImpl::LazyInitializeDeviceFactory() { device_factory_ = std::make_unique<VirtualDeviceEnabledDeviceFactory>( std::make_unique<DeviceFactoryMediaToMojoAdapter>( std::move(video_capture_system))); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) } void VideoCaptureServiceImpl::LazyInitializeVideoSourceProvider() { diff --git a/chromium/services/video_capture/video_capture_service_impl.h b/chromium/services/video_capture/video_capture_service_impl.h index c7287647455..739497a891b 100644 --- a/chromium/services/video_capture/video_capture_service_impl.h +++ b/chromium/services/video_capture/video_capture_service_impl.h @@ -9,6 +9,7 @@ #include "base/memory/scoped_refptr.h" #include "base/threading/thread.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -16,10 +17,10 @@ #include "services/video_capture/public/mojom/device_factory.mojom.h" #include "services/video_capture/public/mojom/video_capture_service.mojom.h" -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) #include "media/capture/video/chromeos/camera_app_device_bridge_impl.h" #include "media/capture/video/chromeos/mojom/camera_app.mojom.h" -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) namespace video_capture { @@ -34,13 +35,13 @@ class VideoCaptureServiceImpl : public mojom::VideoCaptureService { ~VideoCaptureServiceImpl() override; // mojom::VideoCaptureService implementation. -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void InjectGpuDependencies(mojo::PendingRemote<mojom::AcceleratorFactory> accelerator_factory) override; void ConnectToCameraAppDeviceBridge( mojo::PendingReceiver<cros::mojom::CameraAppDeviceBridge> receiver) override; -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) void ConnectToDeviceFactory( mojo::PendingReceiver<mojom::DeviceFactory> receiver) override; void ConnectToVideoSourceProvider( @@ -63,10 +64,10 @@ class VideoCaptureServiceImpl : public mojom::VideoCaptureService { std::unique_ptr<VideoSourceProviderImpl> video_source_provider_; std::unique_ptr<GpuDependenciesContext> gpu_dependencies_context_; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) // Bridge for Chrome OS camera app and camera devices. std::unique_ptr<media::CameraAppDeviceBridgeImpl> camera_app_device_bridge_; -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; diff --git a/chromium/services/video_capture/video_source_impl.cc b/chromium/services/video_capture/video_source_impl.cc index a19d6ed465a..b572ea1e678 100644 --- a/chromium/services/video_capture/video_source_impl.cc +++ b/chromium/services/video_capture/video_source_impl.cc @@ -5,7 +5,7 @@ #include "services/video_capture/video_source_impl.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "services/video_capture/push_video_stream_subscription_impl.h" namespace video_capture { diff --git a/chromium/services/viz/DIR_METADATA b/chromium/services/viz/DIR_METADATA new file mode 100644 index 00000000000..e72351b34d7 --- /dev/null +++ b/chromium/services/viz/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>Services>Viz" +}
\ No newline at end of file diff --git a/chromium/services/viz/OWNERS b/chromium/services/viz/OWNERS index 0452193cd64..d60220b11e0 100644 --- a/chromium/services/viz/OWNERS +++ b/chromium/services/viz/OWNERS @@ -1,3 +1 @@ file://components/viz/OWNERS - -# COMPONENT: Internals>Services>Viz diff --git a/chromium/services/viz/privileged/mojom/gl/BUILD.gn b/chromium/services/viz/privileged/mojom/gl/BUILD.gn index bfa92f2b682..ef032169bfa 100644 --- a/chromium/services/viz/privileged/mojom/gl/BUILD.gn +++ b/chromium/services/viz/privileged/mojom/gl/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//build/config/sanitizers/sanitizers.gni") import("//mojo/public/tools/bindings/mojom.gni") @@ -20,7 +21,7 @@ mojom("gl") { "//ui/gl/mojom", "//url/mojom:url_mojom_gurl", ] - if (is_chromeos) { + if (is_ash) { public_deps += [ "//components/arc/mojom:media", "//components/chromeos_camera/common", diff --git a/chromium/services/viz/privileged/mojom/gl/gpu_host.mojom b/chromium/services/viz/privileged/mojom/gl/gpu_host.mojom index 9d40a960ab3..2a495c036e8 100644 --- a/chromium/services/viz/privileged/mojom/gl/gpu_host.mojom +++ b/chromium/services/viz/privileged/mojom/gl/gpu_host.mojom @@ -6,9 +6,9 @@ module viz.mojom; import "gpu/ipc/common/gpu_feature_info.mojom"; import "gpu/ipc/common/gpu_info.mojom"; -import "gpu/ipc/common/gpu_extra_info.mojom"; import "gpu/ipc/common/surface_handle.mojom"; import "services/viz/privileged/mojom/gl/context_lost_reason.mojom"; +import "ui/gfx/mojom/gpu_extra_info.mojom"; import "url/mojom/url.mojom"; // Communication channel from the gpu process to the gpu host. This interface @@ -21,7 +21,7 @@ interface GpuHost { gpu.mojom.GpuFeatureInfo gpu_feature_info, gpu.mojom.GpuInfo? gpu_info_for_hardware_gpu, gpu.mojom.GpuFeatureInfo? gpu_feature_info_for_hardware_gpu, - gpu.mojom.GpuExtraInfo gpu_extra_info); + gfx.mojom.GpuExtraInfo gpu_extra_info); DidFailInitialize(); DidCreateContextSuccessfully(); diff --git a/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom b/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom index 5d6701aaca3..2afcc3947c0 100644 --- a/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom +++ b/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom @@ -124,6 +124,9 @@ interface GpuService { // Tells GPU that host has seen a monitor being unplugged. DisplayRemoved(); + // Tells GPU that host has seen the display metrics changed. + DisplayMetricsChanged(); + // Tells GPU that all GPU channels are to be destroyed. DestroyAllChannels(); diff --git a/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.cc index 61657009295..031dba29631 100644 --- a/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.cc +++ b/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.cc @@ -20,13 +20,14 @@ bool StructTraits<viz::mojom::DelegatedInkMetadataDataView, base::TimeTicks timestamp; gfx::RectF presentation_area; SkColor color; + base::TimeTicks frame_time; if (!data.ReadPoint(&point) || !data.ReadTimestamp(×tamp) || !data.ReadPresentationArea(&presentation_area) || - !data.ReadColor(&color)) { + !data.ReadColor(&color) || !data.ReadFrameTime(&frame_time)) { return false; } *out = std::make_unique<viz::DelegatedInkMetadata>( - point, data.diameter(), color, timestamp, presentation_area); + point, data.diameter(), color, timestamp, presentation_area, frame_time); return true; } diff --git a/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.h index bb452750ee3..2a9a243ab26 100644 --- a/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.h +++ b/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.h @@ -5,6 +5,8 @@ #ifndef SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_DELEGATED_INK_METADATA_MOJOM_TRAITS_H_ #define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_DELEGATED_INK_METADATA_MOJOM_TRAITS_H_ +#include <memory> + #include "components/viz/common/delegated_ink_metadata.h" #include "mojo/public/cpp/base/time_mojom_traits.h" #include "services/viz/public/mojom/compositing/delegated_ink_metadata.mojom-shared.h" @@ -24,7 +26,7 @@ struct StructTraits<viz::mojom::DelegatedInkMetadataDataView, input->reset(); } - static gfx::PointF point( + static const gfx::PointF& point( const std::unique_ptr<viz::DelegatedInkMetadata>& input) { return input->point(); } @@ -44,11 +46,16 @@ struct StructTraits<viz::mojom::DelegatedInkMetadataDataView, return input->timestamp(); } - static gfx::RectF presentation_area( + static const gfx::RectF& presentation_area( const std::unique_ptr<viz::DelegatedInkMetadata>& input) { return input->presentation_area(); } + static base::TimeTicks frame_time( + const std::unique_ptr<viz::DelegatedInkMetadata>& input) { + return input->frame_time(); + } + static bool Read(viz::mojom::DelegatedInkMetadataDataView data, std::unique_ptr<viz::DelegatedInkMetadata>* out); }; diff --git a/chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc b/chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc index ec6e51283ad..a740cc70661 100644 --- a/chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc +++ b/chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc @@ -217,8 +217,9 @@ class VizSerializationPerfTest : public testing::Test { pass_in->CreateAndAppendSharedQuadState(); shared_state1_in->SetAll( arbitrary_matrix1, arbitrary_rect1, arbitrary_rect1, - arbitrary_rrectf1, arbitrary_rect2, arbitrary_bool1, arbitrary_bool1, - arbitrary_float1, arbitrary_blend_mode1, arbitrary_context_id1); + gfx::MaskFilterInfo(arbitrary_rrectf1), arbitrary_rect2, + arbitrary_bool1, arbitrary_bool1, arbitrary_float1, + arbitrary_blend_mode1, arbitrary_context_id1); auto* texture_in = pass_in->CreateAndAppendDrawQuad<TextureDrawQuad>(); texture_in->SetAll( @@ -259,8 +260,9 @@ class VizSerializationPerfTest : public testing::Test { pass_in->CreateAndAppendSharedQuadState(); shared_state2_in->SetAll( arbitrary_matrix2, arbitrary_rect2, arbitrary_rect2, - arbitrary_rrectf2, arbitrary_rect3, arbitrary_bool1, arbitrary_bool1, - arbitrary_float2, arbitrary_blend_mode2, arbitrary_context_id2); + gfx::MaskFilterInfo(arbitrary_rrectf2), arbitrary_rect3, + arbitrary_bool1, arbitrary_bool1, arbitrary_float2, + arbitrary_blend_mode2, arbitrary_context_id2); for (uint32_t j = 0; j < 6; ++j) { auto* tile_in = pass_in->CreateAndAppendDrawQuad<TileDrawQuad>(); tile_in->SetAll( @@ -276,8 +278,9 @@ class VizSerializationPerfTest : public testing::Test { pass_in->CreateAndAppendSharedQuadState(); shared_state3_in->SetAll( arbitrary_matrix1, arbitrary_rect3, arbitrary_rect3, - arbitrary_rrectf3, arbitrary_rect1, arbitrary_bool1, arbitrary_bool1, - arbitrary_float3, arbitrary_blend_mode3, arbitrary_context_id3); + gfx::MaskFilterInfo(arbitrary_rrectf3), arbitrary_rect1, + arbitrary_bool1, arbitrary_bool1, arbitrary_float3, + arbitrary_blend_mode3, arbitrary_context_id3); for (uint32_t j = 0; j < 5; ++j) { auto* solidcolor_in = pass_in->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); diff --git a/chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc b/chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc index 90e3b1123a1..d5c0f419379 100644 --- a/chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc +++ b/chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc @@ -58,11 +58,11 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkString.h" #include "ui/gfx/geometry/mojom/geometry_mojom_traits.h" +#include "ui/gfx/hdr_metadata.h" #include "ui/gfx/mojom/buffer_types_mojom_traits.h" #include "ui/gfx/mojom/color_space_mojom_traits.h" #include "ui/gfx/mojom/selection_bound_mojom_traits.h" #include "ui/gfx/mojom/transform_mojom_traits.h" -#include "ui/gl/hdr_metadata.h" #include "ui/latency/mojom/latency_info_mojom_traits.h" namespace viz { @@ -416,7 +416,8 @@ TEST_F(StructTraitsTest, SharedQuadState) { 13.f, 14.f, 15.f, 16.f); const gfx::Rect layer_rect(1234, 5678); const gfx::Rect visible_layer_rect(12, 34, 56, 78); - const gfx::RRectF rounded_corner_bounds(gfx::RectF(1.f, 2.f, 30.f, 40.f), 5); + const gfx::MaskFilterInfo mask_filter_info( + gfx::RRectF(gfx::RectF(1.f, 2.f, 30.f, 40.f), 5)); const gfx::Rect clip_rect(123, 456, 789, 101112); const bool is_clipped = true; bool are_contents_opaque = true; @@ -426,9 +427,8 @@ TEST_F(StructTraitsTest, SharedQuadState) { bool is_fast_rounded_corner = true; SharedQuadState input_sqs; input_sqs.SetAll(quad_to_target_transform, layer_rect, visible_layer_rect, - rounded_corner_bounds, clip_rect, is_clipped, - are_contents_opaque, opacity, blend_mode, - sorting_context_id); + mask_filter_info, clip_rect, is_clipped, are_contents_opaque, + opacity, blend_mode, sorting_context_id); input_sqs.is_fast_rounded_corner = is_fast_rounded_corner; SharedQuadState output_sqs; mojo::test::SerializeAndDeserialize<mojom::SharedQuadState>(&input_sqs, @@ -436,7 +436,8 @@ TEST_F(StructTraitsTest, SharedQuadState) { EXPECT_EQ(quad_to_target_transform, output_sqs.quad_to_target_transform); EXPECT_EQ(layer_rect, output_sqs.quad_layer_rect); EXPECT_EQ(visible_layer_rect, output_sqs.visible_quad_layer_rect); - EXPECT_EQ(rounded_corner_bounds, output_sqs.rounded_corner_bounds); + EXPECT_EQ(mask_filter_info.rounded_corner_bounds(), + output_sqs.mask_filter_info.rounded_corner_bounds()); EXPECT_EQ(clip_rect, output_sqs.clip_rect); EXPECT_EQ(is_clipped, output_sqs.is_clipped); EXPECT_EQ(opacity, output_sqs.opacity); @@ -459,8 +460,8 @@ TEST_F(StructTraitsTest, CompositorFrame) { 15.f, 16.f); const gfx::Rect sqs_layer_rect(1234, 5678); const gfx::Rect sqs_visible_layer_rect(12, 34, 56, 78); - const gfx::RRectF sqs_rounded_corner_bounds(gfx::RectF(3.f, 4.f, 50.f, 15.f), - 3); + const gfx::MaskFilterInfo sqs_mask_filter_info( + gfx::RRectF(gfx::RectF(3.f, 4.f, 50.f, 15.f), 3)); const gfx::Rect sqs_clip_rect(123, 456, 789, 101112); const bool sqs_is_clipped = true; bool sqs_are_contents_opaque = false; @@ -469,7 +470,7 @@ TEST_F(StructTraitsTest, CompositorFrame) { const int sqs_sorting_context_id = 1337; SharedQuadState* sqs = render_pass->CreateAndAppendSharedQuadState(); sqs->SetAll(sqs_quad_to_target_transform, sqs_layer_rect, - sqs_visible_layer_rect, sqs_rounded_corner_bounds, sqs_clip_rect, + sqs_visible_layer_rect, sqs_mask_filter_info, sqs_clip_rect, sqs_is_clipped, sqs_are_contents_opaque, sqs_opacity, sqs_blend_mode, sqs_sorting_context_id); @@ -544,7 +545,7 @@ TEST_F(StructTraitsTest, CompositorFrame) { EXPECT_EQ(sqs_quad_to_target_transform, out_sqs->quad_to_target_transform); EXPECT_EQ(sqs_layer_rect, out_sqs->quad_layer_rect); EXPECT_EQ(sqs_visible_layer_rect, out_sqs->visible_quad_layer_rect); - EXPECT_EQ(sqs_rounded_corner_bounds, out_sqs->rounded_corner_bounds); + EXPECT_EQ(sqs_mask_filter_info, out_sqs->mask_filter_info); EXPECT_EQ(sqs_clip_rect, out_sqs->clip_rect); EXPECT_EQ(sqs_is_clipped, out_sqs->is_clipped); EXPECT_EQ(sqs_are_contents_opaque, out_sqs->are_contents_opaque); @@ -723,7 +724,7 @@ TEST_F(StructTraitsTest, RenderPass) { gfx::Transform(16.1f, 15.3f, 14.3f, 13.7f, 12.2f, 11.4f, 10.4f, 9.8f, 8.1f, 7.3f, 6.3f, 5.7f, 4.8f, 3.4f, 2.4f, 1.2f), gfx::Rect(1, 2), gfx::Rect(1337, 5679, 9101112, 131415), - gfx::RRectF(gfx::RectF(5.f, 6.f, 70.f, 89.f), 10.f), + gfx::MaskFilterInfo(gfx::RRectF(gfx::RectF(5.f, 6.f, 70.f, 89.f), 10.f)), gfx::Rect(1357, 2468, 121314, 1337), true, true, 2, SkBlendMode::kSrcOver, 1); @@ -732,7 +733,7 @@ TEST_F(StructTraitsTest, RenderPass) { gfx::Transform(1.1f, 2.3f, 3.3f, 4.7f, 5.2f, 6.4f, 7.4f, 8.8f, 9.1f, 10.3f, 11.3f, 12.7f, 13.8f, 14.4f, 15.4f, 16.2f), gfx::Rect(1337, 1234), gfx::Rect(1234, 5678, 9101112, 13141516), - gfx::RRectF(gfx::RectF(23.f, 45.f, 60.f, 70.f), 8.f), + gfx::MaskFilterInfo(gfx::RRectF(gfx::RectF(23.f, 45.f, 60.f, 70.f), 8.f)), gfx::Rect(1357, 2468, 121314, 1337), true, true, 2, SkBlendMode::kSrcOver, 1); @@ -792,8 +793,7 @@ TEST_F(StructTraitsTest, RenderPass) { EXPECT_EQ(shared_state_1->quad_layer_rect, out_sqs1->quad_layer_rect); EXPECT_EQ(shared_state_1->visible_quad_layer_rect, out_sqs1->visible_quad_layer_rect); - EXPECT_EQ(shared_state_1->rounded_corner_bounds, - out_sqs1->rounded_corner_bounds); + EXPECT_EQ(shared_state_1->mask_filter_info, out_sqs1->mask_filter_info); EXPECT_EQ(shared_state_1->clip_rect, out_sqs1->clip_rect); EXPECT_EQ(shared_state_1->is_clipped, out_sqs1->is_clipped); EXPECT_EQ(shared_state_1->opacity, out_sqs1->opacity); @@ -806,8 +806,7 @@ TEST_F(StructTraitsTest, RenderPass) { EXPECT_EQ(shared_state_2->quad_layer_rect, out_sqs2->quad_layer_rect); EXPECT_EQ(shared_state_2->visible_quad_layer_rect, out_sqs2->visible_quad_layer_rect); - EXPECT_EQ(shared_state_2->rounded_corner_bounds, - out_sqs2->rounded_corner_bounds); + EXPECT_EQ(shared_state_2->mask_filter_info, out_sqs2->mask_filter_info); EXPECT_EQ(shared_state_2->clip_rect, out_sqs2->clip_rect); EXPECT_EQ(shared_state_2->is_clipped, out_sqs2->is_clipped); EXPECT_EQ(shared_state_2->opacity, out_sqs2->opacity); @@ -1134,7 +1133,7 @@ TEST_F(StructTraitsTest, YUVDrawQuad) { const uint32_t bits_per_channel = 13; const gfx::ProtectedVideoType protected_video_type = gfx::ProtectedVideoType::kSoftwareProtected; - gl::HDRMetadata hdr_metadata = gl::HDRMetadata(); + gfx::HDRMetadata hdr_metadata = gfx::HDRMetadata(); hdr_metadata.max_content_light_level = 1000; hdr_metadata.max_frame_average_light_level = 100; diff --git a/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h index c0d5efee8cd..dd697f3cf4e 100644 --- a/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h +++ b/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h @@ -25,9 +25,9 @@ #include "services/viz/public/cpp/compositing/surface_range_mojom_traits.h" #include "services/viz/public/mojom/compositing/quads.mojom-shared.h" #include "ui/gfx/geometry/mojom/geometry_mojom_traits.h" +#include "ui/gfx/hdr_metadata.h" #include "ui/gfx/ipc/color/gfx_param_traits.h" -#include "ui/gl/hdr_metadata.h" -#include "ui/gl/mojom/hdr_metadata_mojom_traits.h" +#include "ui/gfx/mojom/hdr_metadata_mojom_traits.h" namespace mojo { @@ -545,7 +545,7 @@ struct StructTraits<viz::mojom::YUVVideoQuadStateDataView, viz::DrawQuad> { viz::YUVVideoDrawQuad::MaterialCast(&input); return quad->protected_video_type; } - static const gl::HDRMetadata& hdr_metadata(const viz::DrawQuad& input) { + static const gfx::HDRMetadata& hdr_metadata(const viz::DrawQuad& input) { const viz::YUVVideoDrawQuad* quad = viz::YUVVideoDrawQuad::MaterialCast(&input); return quad->hdr_metadata; diff --git a/chromium/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h index 8301911110e..5bbe76ad677 100644 --- a/chromium/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h +++ b/chromium/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h @@ -7,6 +7,7 @@ #include "components/viz/common/quads/shared_quad_state.h" #include "services/viz/public/mojom/compositing/shared_quad_state.mojom-shared.h" +#include "ui/gfx/mojom/mask_filter_info_mojom_traits.h" #include "ui/gfx/mojom/rrect_f_mojom_traits.h" namespace mojo { @@ -35,9 +36,9 @@ struct StructTraits<viz::mojom::SharedQuadStateDataView, OptSharedQuadState> { return input.sqs->visible_quad_layer_rect; } - static const gfx::RRectF& rounded_corner_bounds( + static const gfx::MaskFilterInfo& mask_filter_info( const OptSharedQuadState& input) { - return input.sqs->rounded_corner_bounds; + return input.sqs->mask_filter_info; } static const gfx::Rect& clip_rect(const OptSharedQuadState& input) { @@ -93,9 +94,9 @@ struct StructTraits<viz::mojom::SharedQuadStateDataView, viz::SharedQuadState> { return sqs.visible_quad_layer_rect; } - static const gfx::RRectF& rounded_corner_bounds( + static const gfx::MaskFilterInfo& mask_filter_info( const viz::SharedQuadState& sqs) { - return sqs.rounded_corner_bounds; + return sqs.mask_filter_info; } static const gfx::Rect& clip_rect(const viz::SharedQuadState& sqs) { @@ -137,7 +138,7 @@ struct StructTraits<viz::mojom::SharedQuadStateDataView, viz::SharedQuadState> { if (!data.ReadQuadToTargetTransform(&out->quad_to_target_transform) || !data.ReadQuadLayerRect(&out->quad_layer_rect) || !data.ReadVisibleQuadLayerRect(&out->visible_quad_layer_rect) || - !data.ReadRoundedCornerBounds(&out->rounded_corner_bounds) || + !data.ReadMaskFilterInfo(&out->mask_filter_info) || !data.ReadClipRect(&out->clip_rect)) { return false; } diff --git a/chromium/services/viz/public/cpp/gpu/BUILD.gn b/chromium/services/viz/public/cpp/gpu/BUILD.gn index e72a33c5128..7a95c61fb1b 100644 --- a/chromium/services/viz/public/cpp/gpu/BUILD.gn +++ b/chromium/services/viz/public/cpp/gpu/BUILD.gn @@ -30,6 +30,7 @@ source_set("gpu") { deps = [ "//base", + "//build:chromeos_buildflags", "//gpu", "//gpu/command_buffer/client", "//gpu/command_buffer/client:gles2_cmd_helper", @@ -56,6 +57,7 @@ source_set("tests") { deps = [ "//base", "//base/test:test_support", + "//build:chromeos_buildflags", "//mojo/core/embedder", "//mojo/public/cpp/system", "//services/service_manager/public/cpp", diff --git a/chromium/services/viz/public/cpp/gpu/DIR_METADATA b/chromium/services/viz/public/cpp/gpu/DIR_METADATA new file mode 100644 index 00000000000..8e87cca679a --- /dev/null +++ b/chromium/services/viz/public/cpp/gpu/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Internals>GPU>Internals" +}
\ No newline at end of file diff --git a/chromium/services/viz/public/cpp/gpu/OWNERS b/chromium/services/viz/public/cpp/gpu/OWNERS index 50daca70bdc..1db50ad6a5a 100644 --- a/chromium/services/viz/public/cpp/gpu/OWNERS +++ b/chromium/services/viz/public/cpp/gpu/OWNERS @@ -1,3 +1 @@ file://gpu/OWNERS - -# COMPONENT: Internals>GPU>Internals diff --git a/chromium/services/viz/public/cpp/gpu/gpu.cc b/chromium/services/viz/public/cpp/gpu/gpu.cc index 50049f52785..155d689654b 100644 --- a/chromium/services/viz/public/cpp/gpu/gpu.cc +++ b/chromium/services/viz/public/cpp/gpu/gpu.cc @@ -15,6 +15,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/service_manager/public/cpp/connector.h" #include "services/viz/public/cpp/gpu/client_gpu_memory_buffer_manager.h" @@ -56,14 +57,14 @@ class Gpu::GpuPtrIO { } } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void CreateJpegDecodeAccelerator( mojo::PendingReceiver<chromeos_camera::mojom::MjpegDecodeAccelerator> receiver) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); gpu_remote_->CreateJpegDecodeAccelerator(std::move(receiver)); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) void CreateVideoEncodeAcceleratorProvider( mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProvider> @@ -286,7 +287,7 @@ std::unique_ptr<Gpu> Gpu::Create( new Gpu(std::move(remote), std::move(io_task_runner))); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void Gpu::CreateJpegDecodeAccelerator( mojo::PendingReceiver<chromeos_camera::mojom::MjpegDecodeAccelerator> jda_receiver) { @@ -296,7 +297,7 @@ void Gpu::CreateJpegDecodeAccelerator( base::BindOnce(&GpuPtrIO::CreateJpegDecodeAccelerator, base::Unretained(gpu_.get()), std::move(jda_receiver))); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) void Gpu::CreateVideoEncodeAcceleratorProvider( mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProvider> diff --git a/chromium/services/viz/public/cpp/gpu/gpu.h b/chromium/services/viz/public/cpp/gpu/gpu.h index 958571afca4..efd51d56221 100644 --- a/chromium/services/viz/public/cpp/gpu/gpu.h +++ b/chromium/services/viz/public/cpp/gpu/gpu.h @@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" +#include "build/chromeos_buildflags.h" #include "components/viz/common/gpu/context_provider.h" #include "gpu/ipc/client/gpu_channel_host.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -42,11 +43,11 @@ class Gpu : public gpu::GpuChannelEstablishFactory { return gpu_memory_buffer_manager_.get(); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void CreateJpegDecodeAccelerator( mojo::PendingReceiver<chromeos_camera::mojom::MjpegDecodeAccelerator> jda_receiver); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) void CreateVideoEncodeAcceleratorProvider( mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProvider> vea_provider_receiver); diff --git a/chromium/services/viz/public/cpp/gpu/gpu_unittest.cc b/chromium/services/viz/public/cpp/gpu/gpu_unittest.cc index 2bda44e5eb7..b9a3f9b0487 100644 --- a/chromium/services/viz/public/cpp/gpu/gpu_unittest.cc +++ b/chromium/services/viz/public/cpp/gpu/gpu_unittest.cc @@ -14,6 +14,7 @@ #include "base/synchronization/waitable_event.h" #include "base/test/task_environment.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "gpu/config/gpu_feature_info.h" #include "gpu/config/gpu_info.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -63,11 +64,11 @@ class TestGpuImpl : public mojom::Gpu { gpu::GpuFeatureInfo()); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) void CreateJpegDecodeAccelerator( mojo::PendingReceiver<chromeos_camera::mojom::MjpegDecodeAccelerator> jda_receiver) override {} -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_ASH) void CreateVideoEncodeAcceleratorProvider( mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProvider> diff --git a/chromium/services/viz/public/mojom/BUILD.gn b/chromium/services/viz/public/mojom/BUILD.gn index 32c01030d69..2e78c5b1b9b 100644 --- a/chromium/services/viz/public/mojom/BUILD.gn +++ b/chromium/services/viz/public/mojom/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//mojo/public/tools/bindings/mojom.gni") mojom("mojom") { @@ -55,7 +56,7 @@ mojom("mojom") { "//ui/latency/mojom", ] - if (is_chromeos) { + if (is_ash) { public_deps += [ "//components/chromeos_camera/common" ] } diff --git a/chromium/services/viz/public/mojom/compositing/compositor_frame_sink.mojom b/chromium/services/viz/public/mojom/compositing/compositor_frame_sink.mojom index accfb748d2d..b8c26e8db83 100644 --- a/chromium/services/viz/public/mojom/compositing/compositor_frame_sink.mojom +++ b/chromium/services/viz/public/mojom/compositing/compositor_frame_sink.mojom @@ -53,6 +53,11 @@ interface CompositorFrameSink { // For successful swaps, the implementation must call // DidReceiveCompositorFrameAck() asynchronously when the frame has been // processed in order to unthrottle the next frame. + // + // TODO(crbug.com/1141980): Investigate whether it's possible to alter the + // CompositorFrame structure to be less likely to exceed soft message size + // limits and remove [UnlimitedSize] here. + [UnlimitedSize] SubmitCompositorFrame(LocalSurfaceId local_surface_id, CompositorFrame frame, HitTestRegionList? hit_test_region_list, diff --git a/chromium/services/viz/public/mojom/compositing/delegated_ink_metadata.mojom b/chromium/services/viz/public/mojom/compositing/delegated_ink_metadata.mojom index 89843b27ddb..99ff67ea10d 100644 --- a/chromium/services/viz/public/mojom/compositing/delegated_ink_metadata.mojom +++ b/chromium/services/viz/public/mojom/compositing/delegated_ink_metadata.mojom @@ -15,4 +15,5 @@ struct DelegatedInkMetadata { skia.mojom.SkColor color; mojo_base.mojom.TimeTicks timestamp; gfx.mojom.RectF presentation_area; + mojo_base.mojom.TimeTicks frame_time; }; diff --git a/chromium/services/viz/public/mojom/compositing/quads.mojom b/chromium/services/viz/public/mojom/compositing/quads.mojom index 7305c4d03d5..2789afa0a46 100644 --- a/chromium/services/viz/public/mojom/compositing/quads.mojom +++ b/chromium/services/viz/public/mojom/compositing/quads.mojom @@ -10,8 +10,8 @@ import "services/viz/public/mojom/compositing/shared_quad_state.mojom"; import "services/viz/public/mojom/compositing/surface_range.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; import "ui/gfx/mojom/color_space.mojom"; +import "ui/gfx/mojom/hdr_metadata.mojom"; import "ui/gfx/mojom/transform.mojom"; -import "ui/gl/mojom/hdr_metadata.mojom"; enum ProtectedVideoState { kClear, @@ -115,7 +115,7 @@ struct YUVVideoQuadState { uint32 bits_per_channel; gfx.mojom.ColorSpace video_color_space; ProtectedVideoState protected_video_type; - gl.mojom.HDRMetadata hdr_metadata; + gfx.mojom.HDRMetadata hdr_metadata; }; struct VideoHoleQuadState { diff --git a/chromium/services/viz/public/mojom/compositing/shared_quad_state.mojom b/chromium/services/viz/public/mojom/compositing/shared_quad_state.mojom index 214f508b306..98ba3010a35 100644 --- a/chromium/services/viz/public/mojom/compositing/shared_quad_state.mojom +++ b/chromium/services/viz/public/mojom/compositing/shared_quad_state.mojom @@ -7,6 +7,7 @@ module viz.mojom; import "ui/gfx/geometry/mojom/geometry.mojom"; import "ui/gfx/mojom/rrect_f.mojom"; import "ui/gfx/mojom/transform.mojom"; +import "ui/gfx/mojom/mask_filter_info.mojom"; // See viz::SharedQuadState. struct SharedQuadState { @@ -20,9 +21,10 @@ struct SharedQuadState { // of the quad rects. gfx.mojom.Rect visible_quad_layer_rect; - // This rect lives in the target content space. It defines the corner radius - // to clip the quads with. - gfx.mojom.RRectF rounded_corner_bounds; + // This rect lives in the target content space. It defines the mask filter + // info applied to the quad, and also defines rounded corner rects to clip the + // quads with. + gfx.mojom.MaskFilterInfo mask_filter_info; // This rect lives in the target content space. gfx.mojom.Rect clip_rect; |