diff --git a/DEPS b/DEPS index c840c25..cf95f5a2 100644 --- a/DEPS +++ b/DEPS
@@ -138,7 +138,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '82310316135997d5a0c3d9750b72dbc184c18829', + 'skia_revision': 'fe18de506097d9cfa5f2a2a057e1dd134a96c116', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -154,7 +154,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '8ac0bd6cc3e5aaabb904ffe01639ecea4b7b5fde', + 'swiftshader_revision': 'c2c829bc9a633302d6a6b19e635a1ab6e7ae5915', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -189,7 +189,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': 'c949ab0757a2514cd3a37b3e1e8390fd662a025b', + 'freetype_revision': '711b593e4b589fbd726a4962ad492fc4e416355d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling HarfBuzz # and whatever else without interference from each other. @@ -201,7 +201,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '991302572440fa546ef523789fa821943184b4bf', + 'catapult_revision': 'abea78f985f4f3156889f26ba5e34131ed457437', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -273,7 +273,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'fa7228a1fa63163a6f27b9b0a9036d1be27c6dd6', + 'dawn_revision': '120f5d906283d44c5259987f650bc9c8e5b50d08', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -1187,7 +1187,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'b4697aa45589d116d9db40a21de69d1365dd7e1c', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c63be46c502089deed3fc93217425e4b6ea2f517', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1396,7 +1396,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@104f3fc6931f2aeb29ad8445345d513b0259dfb8', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b793b75db94826ef7a42406d267d720d59c22354', 'condition': 'checkout_src_internal', },
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc index cdc0904..df182d8 100644 --- a/ash/accelerators/accelerator_controller_impl.cc +++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -918,7 +918,6 @@ // prefs iteself. Shell* shell = Shell::Get(); shell->accessibility_controller()->SetFullscreenMagnifierEnabled(enabled); - shell->magnification_controller()->SetEnabled(enabled); } void SetHighContrastEnabled(bool enabled) {
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index dee5465..e2dc7c7 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -22,6 +22,7 @@ #include "ash/magnifier/magnification_controller.h" #include "ash/media/media_controller_impl.h" #include "ash/public/cpp/ash_features.h" +#include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/test/shell_test_api.h" @@ -52,6 +53,8 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/user_action_tester.h" #include "base/test/scoped_feature_list.h" +#include "components/prefs/pref_change_registrar.h" +#include "components/prefs/pref_service.h" #include "media/base/media_switches.h" #include "services/media_session/public/cpp/test/test_media_controller.h" #include "services/media_session/public/mojom/media_session.mojom.h" @@ -1823,6 +1826,8 @@ namespace { +constexpr char kUserEmail[] = "user@magnifier"; + class MagnifiersAcceleratorsTester : public AcceleratorControllerTest { public: MagnifiersAcceleratorsTester() = default; @@ -1836,13 +1841,55 @@ return Shell::Get()->magnification_controller(); } + PrefService* user_pref_service() { + return Shell::Get()->session_controller()->GetUserPrefServiceForUser( + AccountId::FromUserEmail(kUserEmail)); + } + + void SetUp() override { + AcceleratorControllerTest::SetUp(); + + // Create user session and simulate its login. + SimulateUserLogin(kUserEmail); + } + private: DISALLOW_COPY_AND_ASSIGN(MagnifiersAcceleratorsTester); }; } // namespace +// TODO (afakhry): Remove this class after refactoring MagnificationManager. +// Mocked chrome/browser/chromeos/accessibility/magnification_manager.cc +class FakeMagnificationManager { + public: + FakeMagnificationManager() = default; + + void SetPrefs(PrefService* prefs) { + pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>(); + pref_change_registrar_->Init(prefs); + pref_change_registrar_->Add( + prefs::kAccessibilityScreenMagnifierEnabled, + base::BindRepeating(&FakeMagnificationManager::UpdateMagnifierFromPrefs, + base::Unretained(this))); + prefs_ = prefs; + } + + void UpdateMagnifierFromPrefs() { + Shell::Get()->magnification_controller()->SetEnabled( + prefs_->GetBoolean(prefs::kAccessibilityScreenMagnifierEnabled)); + } + + private: + std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_; + PrefService* prefs_; + + DISALLOW_COPY_AND_ASSIGN(FakeMagnificationManager); +}; + TEST_F(MagnifiersAcceleratorsTester, TestToggleFullscreenMagnifier) { + FakeMagnificationManager manager; + manager.SetPrefs(user_pref_service()); EXPECT_FALSE(docked_magnifier_controller()->GetEnabled()); EXPECT_FALSE(fullscreen_magnifier_controller()->IsEnabled()); EXPECT_FALSE(IsConfirmationDialogOpen());
diff --git a/ash/multi_device_setup/multi_device_notification_presenter.cc b/ash/multi_device_setup/multi_device_notification_presenter.cc index 4e7f2dd1..46edd07 100644 --- a/ash/multi_device_setup/multi_device_notification_presenter.cc +++ b/ash/multi_device_setup/multi_device_notification_presenter.cc
@@ -56,18 +56,6 @@ NOTREACHED(); } -MultiDeviceNotificationPresenter::OpenUiDelegate::~OpenUiDelegate() = default; - -void MultiDeviceNotificationPresenter::OpenUiDelegate:: - OpenMultiDeviceSetupUi() { - Shell::Get()->system_tray_model()->client()->ShowMultiDeviceSetup(); -} - -void MultiDeviceNotificationPresenter::OpenUiDelegate:: - OpenConnectedDevicesSettings() { - Shell::Get()->system_tray_model()->client()->ShowConnectedDevicesSettings(); -} - // static MultiDeviceNotificationPresenter::NotificationType MultiDeviceNotificationPresenter::GetMetricValueForNotification( @@ -91,7 +79,6 @@ : message_center_(message_center), connector_(connector), binding_(this), - open_ui_delegate_(std::make_unique<OpenUiDelegate>()), weak_ptr_factory_(this) { DCHECK(message_center_); DCHECK(connector_); @@ -191,14 +178,17 @@ kNotificationTypeMax); switch (notification_status_) { case Status::kNewUserNotificationVisible: - open_ui_delegate_->OpenMultiDeviceSetupUi(); + Shell::Get()->system_tray_model()->client()->ShowMultiDeviceSetup(); break; case Status::kExistingUserHostSwitchedNotificationVisible: // Clicks on the 'host switched' and 'Chromebook added' notifications have // the same effect, i.e. opening the Settings subpage. FALLTHROUGH; case Status::kExistingUserNewChromebookNotificationVisible: - open_ui_delegate_->OpenConnectedDevicesSettings(); + Shell::Get() + ->system_tray_model() + ->client() + ->ShowConnectedDevicesSettings(); break; case Status::kNoNotificationVisible: NOTREACHED();
diff --git a/ash/multi_device_setup/multi_device_notification_presenter.h b/ash/multi_device_setup/multi_device_notification_presenter.h index 4d9571f..77bc760 100644 --- a/ash/multi_device_setup/multi_device_notification_presenter.h +++ b/ash/multi_device_setup/multi_device_notification_presenter.h
@@ -84,16 +84,6 @@ // MultiDevice setup notification ID. static const char kNotificationId[]; - // These methods are delegated to a nested class to make them easier to stub - // in unit tests. This way they can all be stubbed simultaneously by building - // a test delegate class deriving from OpenUiDelegate. - class OpenUiDelegate { - public: - virtual ~OpenUiDelegate(); - virtual void OpenMultiDeviceSetupUi(); - virtual void OpenConnectedDevicesSettings(); - }; - // Represents each possible MultiDevice setup notification that the setup flow // can show with a "none" option for the general state with no notification // present. @@ -141,7 +131,6 @@ mojo::Binding<chromeos::multidevice_setup::mojom::AccountStatusChangeDelegate> binding_; - std::unique_ptr<OpenUiDelegate> open_ui_delegate_; base::WeakPtrFactory<MultiDeviceNotificationPresenter> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(MultiDeviceNotificationPresenter);
diff --git a/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc b/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc index 2cd617a..b212a44 100644 --- a/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc +++ b/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc
@@ -8,10 +8,10 @@ #include <memory> #include <utility> +#include "ash/public/cpp/test/test_system_tray_client.h" #include "ash/session/test_session_controller_client.h" #include "ash/strings/grit/ash_strings.h" #include "ash/test/ash_test_base.h" -#include "ash/test/ash_test_helper.h" #include "base/bind.h" #include "base/logging.h" #include "base/memory/ptr_util.h" @@ -94,43 +94,12 @@ class MultiDeviceNotificationPresenterTest : public NoSessionAshTestBase { public: - class TestOpenUiDelegate - : public MultiDeviceNotificationPresenter::OpenUiDelegate { - public: - TestOpenUiDelegate() = default; - ~TestOpenUiDelegate() override = default; - - int open_multi_device_setup_ui_count() const { - return open_multi_device_setup_ui_count_; - } - - int open_connected_devices_settings_count() const { - return open_connected_devices_settings_count_; - } - - // MultiDeviceNotificationPresenter::OpenUiDelegate: - void OpenMultiDeviceSetupUi() override { - ++open_multi_device_setup_ui_count_; - } - - void OpenConnectedDevicesSettings() override { - ++open_connected_devices_settings_count_; - } - - private: - int open_multi_device_setup_ui_count_ = 0; - int open_connected_devices_settings_count_ = 0; - }; - - protected: MultiDeviceNotificationPresenterTest() = default; void SetUp() override { NoSessionAshTestBase::SetUp(); - std::unique_ptr<TestOpenUiDelegate> test_open_ui_delegate = - std::make_unique<TestOpenUiDelegate>(); - test_open_ui_delegate_ = test_open_ui_delegate.get(); + test_system_tray_client_ = GetSystemTrayClient(); service_manager::mojom::ConnectorRequest request; connector_ = service_manager::Connector::Create(&request); @@ -150,8 +119,6 @@ notification_presenter_ = std::make_unique<MultiDeviceNotificationPresenter>( &test_message_center_, connector_.get()); - notification_presenter_->open_ui_delegate_ = - std::move(test_open_ui_delegate); } void TearDown() override { @@ -271,7 +238,7 @@ } base::HistogramTester histogram_tester_; - TestOpenUiDelegate* test_open_ui_delegate_; + TestSystemTrayClient* test_system_tray_client_; TestMessageCenter test_message_center_; std::unique_ptr<service_manager::Connector> connector_; std::unique_ptr<chromeos::multidevice_setup::FakeMultiDeviceSetup> @@ -354,7 +321,7 @@ notification_presenter_->RemoveMultiDeviceSetupNotification(); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_multi_device_setup_ui_count(), 0); + EXPECT_EQ(test_system_tray_client_->show_multi_device_setup_count(), 0); AssertPotentialHostBucketCount("MultiDeviceSetup_NotificationClicked", 0); AssertPotentialHostBucketCount("MultiDeviceSetup_NotificationShown", 1); } @@ -369,7 +336,7 @@ ClickNotification(); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_multi_device_setup_ui_count(), 1); + EXPECT_EQ(test_system_tray_client_->show_multi_device_setup_count(), 1); AssertPotentialHostBucketCount("MultiDeviceSetup_NotificationClicked", 1); AssertPotentialHostBucketCount("MultiDeviceSetup_NotificationShown", 1); } @@ -384,7 +351,7 @@ DismissNotification(true /* by_user */); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_multi_device_setup_ui_count(), 0); + EXPECT_EQ(test_system_tray_client_->show_multi_device_setup_count(), 0); AssertPotentialHostBucketCount("MultiDeviceSetup_NotificationDismissed", 1); ShowNewUserNotification(); @@ -393,7 +360,7 @@ DismissNotification(false /* by_user */); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_multi_device_setup_ui_count(), 0); + EXPECT_EQ(test_system_tray_client_->show_multi_device_setup_count(), 0); AssertPotentialHostBucketCount("MultiDeviceSetup_NotificationDismissed", 1); } @@ -406,7 +373,7 @@ TriggerNoLongerNewUserEvent(); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_multi_device_setup_ui_count(), 0); + EXPECT_EQ(test_system_tray_client_->show_multi_device_setup_count(), 0); AssertPotentialHostBucketCount("MultiDeviceSetup_NotificationClicked", 0); AssertPotentialHostBucketCount("MultiDeviceSetup_NotificationShown", 1); } @@ -421,7 +388,8 @@ notification_presenter_->RemoveMultiDeviceSetupNotification(); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_connected_devices_settings_count(), 0); + EXPECT_EQ(test_system_tray_client_->show_connected_devices_settings_count(), + 0); AssertHostSwitchedBucketCount("MultiDeviceSetup_NotificationClicked", 0); AssertHostSwitchedBucketCount("MultiDeviceSetup_NotificationShown", 1); } @@ -436,7 +404,8 @@ ClickNotification(); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_connected_devices_settings_count(), 1); + EXPECT_EQ(test_system_tray_client_->show_connected_devices_settings_count(), + 1); AssertHostSwitchedBucketCount("MultiDeviceSetup_NotificationClicked", 1); AssertHostSwitchedBucketCount("MultiDeviceSetup_NotificationShown", 1); } @@ -451,7 +420,7 @@ DismissNotification(true /* by_user */); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_multi_device_setup_ui_count(), 0); + EXPECT_EQ(test_system_tray_client_->show_multi_device_setup_count(), 0); AssertHostSwitchedBucketCount("MultiDeviceSetup_NotificationDismissed", 1); ShowExistingUserHostSwitchedNotification(); @@ -460,7 +429,7 @@ DismissNotification(false /* by_user */); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_multi_device_setup_ui_count(), 0); + EXPECT_EQ(test_system_tray_client_->show_multi_device_setup_count(), 0); AssertHostSwitchedBucketCount("MultiDeviceSetup_NotificationDismissed", 1); } @@ -475,7 +444,8 @@ notification_presenter_->RemoveMultiDeviceSetupNotification(); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_connected_devices_settings_count(), 0); + EXPECT_EQ(test_system_tray_client_->show_connected_devices_settings_count(), + 0); AssertNewChromebookBucketCount("MultiDeviceSetup_NotificationClicked", 0); AssertNewChromebookBucketCount("MultiDeviceSetup_NotificationShown", 1); } @@ -490,7 +460,8 @@ ClickNotification(); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_connected_devices_settings_count(), 1); + EXPECT_EQ(test_system_tray_client_->show_connected_devices_settings_count(), + 1); AssertNewChromebookBucketCount("MultiDeviceSetup_NotificationClicked", 1); AssertNewChromebookBucketCount("MultiDeviceSetup_NotificationShown", 1); } @@ -506,7 +477,7 @@ DismissNotification(true /* by_user */); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_multi_device_setup_ui_count(), 0); + EXPECT_EQ(test_system_tray_client_->show_multi_device_setup_count(), 0); AssertNewChromebookBucketCount("MultiDeviceSetup_NotificationDismissed", 1); ShowExistingUserNewChromebookNotification(); @@ -515,7 +486,7 @@ DismissNotification(false /* by_user */); VerifyNoNotificationIsVisible(); - EXPECT_EQ(test_open_ui_delegate_->open_multi_device_setup_ui_count(), 0); + EXPECT_EQ(test_system_tray_client_->show_multi_device_setup_count(), 0); AssertNewChromebookBucketCount("MultiDeviceSetup_NotificationDismissed", 1); }
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index ecf5389..cd58ff410 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -297,6 +297,8 @@ "test/test_keyboard_controller_observer.h", "test/test_new_window_delegate.cc", "test/test_new_window_delegate.h", + "test/test_system_tray_client.cc", + "test/test_system_tray_client.h", ] deps = [
diff --git a/ash/public/cpp/system_tray_client.h b/ash/public/cpp/system_tray_client.h index 9d2bda3..81692e1 100644 --- a/ash/public/cpp/system_tray_client.h +++ b/ash/public/cpp/system_tray_client.h
@@ -12,8 +12,6 @@ namespace ash { -class SystemTrayClient; - // Handles method calls delegated back to chrome from ash. class ASH_PUBLIC_EXPORT SystemTrayClient { public:
diff --git a/ash/public/cpp/test/test_system_tray_client.cc b/ash/public/cpp/test/test_system_tray_client.cc new file mode 100644 index 0000000..e6d941d --- /dev/null +++ b/ash/public/cpp/test/test_system_tray_client.cc
@@ -0,0 +1,78 @@ +// Copyright 2019 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 "ash/public/cpp/test/test_system_tray_client.h" + +namespace ash { + +TestSystemTrayClient::TestSystemTrayClient() = default; + +TestSystemTrayClient::~TestSystemTrayClient() = default; + +void TestSystemTrayClient::ShowSettings() {} + +void TestSystemTrayClient::ShowBluetoothSettings() { + show_bluetooth_settings_count_++; +} + +void TestSystemTrayClient::ShowBluetoothPairingDialog( + const std::string& address, + const base::string16& name_for_display, + bool paired, + bool connected) {} + +void TestSystemTrayClient::ShowDateSettings() {} + +void TestSystemTrayClient::ShowSetTimeDialog() {} + +void TestSystemTrayClient::ShowDisplaySettings() {} + +void TestSystemTrayClient::ShowPowerSettings() {} + +void TestSystemTrayClient::ShowChromeSlow() {} + +void TestSystemTrayClient::ShowIMESettings() {} + +void TestSystemTrayClient::ShowConnectedDevicesSettings() { + show_connected_devices_settings_count_++; +} + +void TestSystemTrayClient::ShowAboutChromeOS() {} + +void TestSystemTrayClient::ShowHelp() {} + +void TestSystemTrayClient::ShowAccessibilityHelp() {} + +void TestSystemTrayClient::ShowAccessibilitySettings() {} + +void TestSystemTrayClient::ShowPaletteHelp() {} + +void TestSystemTrayClient::ShowPaletteSettings() {} + +void TestSystemTrayClient::ShowPublicAccountInfo() {} + +void TestSystemTrayClient::ShowEnterpriseInfo() {} + +void TestSystemTrayClient::ShowNetworkConfigure(const std::string& network_id) { +} + +void TestSystemTrayClient::ShowNetworkCreate(const std::string& type) {} + +void TestSystemTrayClient::ShowThirdPartyVpnCreate( + const std::string& extension_id) {} + +void TestSystemTrayClient::ShowArcVpnCreate(const std::string& app_id) {} + +void TestSystemTrayClient::ShowNetworkSettings(const std::string& network_id) {} + +void TestSystemTrayClient::ShowMultiDeviceSetup() { + show_multi_device_setup_count_++; +} + +void TestSystemTrayClient::RequestRestartForUpdate() {} + +void TestSystemTrayClient::SetLocaleAndExit( + const std::string& locale_iso_code) {} + +} // namespace ash
diff --git a/ash/public/cpp/test/test_system_tray_client.h b/ash/public/cpp/test/test_system_tray_client.h new file mode 100644 index 0000000..6c1b9e2 --- /dev/null +++ b/ash/public/cpp/test/test_system_tray_client.h
@@ -0,0 +1,71 @@ +// Copyright 2019 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 ASH_PUBLIC_CPP_TEST_TEST_SYSTEM_TRAY_CLIENT_H_ +#define ASH_PUBLIC_CPP_TEST_TEST_SYSTEM_TRAY_CLIENT_H_ + +#include "ash/public/cpp/ash_public_export.h" +#include "ash/public/cpp/system_tray_client.h" +#include "base/macros.h" + +namespace ash { + +// A SystemTrayClient that does nothing. Used by AshTestBase. +class ASH_PUBLIC_EXPORT TestSystemTrayClient : public SystemTrayClient { + public: + TestSystemTrayClient(); + ~TestSystemTrayClient() override; + + // SystemTrayClient: + void ShowSettings() override; + void ShowBluetoothSettings() override; + void ShowBluetoothPairingDialog(const std::string& address, + const base::string16& name_for_display, + bool paired, + bool connected) override; + void ShowDateSettings() override; + void ShowSetTimeDialog() override; + void ShowDisplaySettings() override; + void ShowPowerSettings() override; + void ShowChromeSlow() override; + void ShowIMESettings() override; + void ShowConnectedDevicesSettings() override; + void ShowAboutChromeOS() override; + void ShowHelp() override; + void ShowAccessibilityHelp() override; + void ShowAccessibilitySettings() override; + void ShowPaletteHelp() override; + void ShowPaletteSettings() override; + void ShowPublicAccountInfo() override; + void ShowEnterpriseInfo() override; + void ShowNetworkConfigure(const std::string& network_id) override; + void ShowNetworkCreate(const std::string& type) override; + void ShowThirdPartyVpnCreate(const std::string& extension_id) override; + void ShowArcVpnCreate(const std::string& app_id) override; + void ShowNetworkSettings(const std::string& network_id) override; + void ShowMultiDeviceSetup() override; + void RequestRestartForUpdate() override; + void SetLocaleAndExit(const std::string& locale_iso_code) override; + + int show_bluetooth_settings_count() const { + return show_bluetooth_settings_count_; + } + int show_multi_device_setup_count() const { + return show_multi_device_setup_count_; + } + int show_connected_devices_settings_count() const { + return show_connected_devices_settings_count_; + } + + private: + int show_bluetooth_settings_count_ = 0; + int show_multi_device_setup_count_ = 0; + int show_connected_devices_settings_count_ = 0; + + DISALLOW_COPY_AND_ASSIGN(TestSystemTrayClient); +}; + +} // namespace ash + +#endif // ASH_PUBLIC_CPP_TEST_TEST_SYSTEM_TRAY_CLIENT_H_
diff --git a/ash/system/bluetooth/bluetooth_notification_controller.cc b/ash/system/bluetooth/bluetooth_notification_controller.cc index f753723..d9160b2 100644 --- a/ash/system/bluetooth/bluetooth_notification_controller.cc +++ b/ash/system/bluetooth/bluetooth_notification_controller.cc
@@ -137,36 +137,25 @@ class BluetoothNotificationController::BluetoothPairedNotificationDelegate : public message_center::NotificationDelegate { public: - explicit BluetoothPairedNotificationDelegate(OpenUiDelegate* open_delegate) - : open_delegate_(open_delegate) {} + BluetoothPairedNotificationDelegate() = default; protected: ~BluetoothPairedNotificationDelegate() override = default; + // message_center::NotificationDelegate: void Click(const base::Optional<int>& button_index, - const base::Optional<base::string16>& reply) override; + const base::Optional<base::string16>& reply) override { + if (TrayPopupUtils::CanOpenWebUISettings()) + Shell::Get()->system_tray_model()->client()->ShowBluetoothSettings(); + } private: - OpenUiDelegate* open_delegate_; DISALLOW_COPY_AND_ASSIGN(BluetoothPairedNotificationDelegate); }; -void BluetoothNotificationController::BluetoothPairedNotificationDelegate:: - Click(const base::Optional<int>& button_index, - const base::Optional<base::string16>& reply) { - if (TrayPopupUtils::CanOpenWebUISettings()) - open_delegate_->OpenBluetoothSettings(); -} - -void BluetoothNotificationController::OpenUiDelegate::OpenBluetoothSettings() { - Shell::Get()->system_tray_model()->client()->ShowBluetoothSettings(); -} - BluetoothNotificationController::BluetoothNotificationController( message_center::MessageCenter* message_center) - : open_delegate_(std::make_unique<OpenUiDelegate>()), - message_center_(message_center), - weak_ptr_factory_(this) { + : message_center_(message_center), weak_ptr_factory_(this) { BluetoothAdapterFactory::GetAdapter( base::BindOnce(&BluetoothNotificationController::OnGetAdapter, weak_ptr_factory_.GetWeakPtr())); @@ -365,8 +354,7 @@ message_center::NotifierId(message_center::NotifierType::SYSTEM_COMPONENT, kNotifierBluetooth), message_center::RichNotificationData(), - base::MakeRefCounted<BluetoothPairedNotificationDelegate>( - open_delegate_.get()), + base::MakeRefCounted<BluetoothPairedNotificationDelegate>(), kNotificationBluetoothIcon, message_center::SystemNotificationWarningLevel::NORMAL); message_center_->AddNotification(std::move(notification));
diff --git a/ash/system/bluetooth/bluetooth_notification_controller.h b/ash/system/bluetooth/bluetooth_notification_controller.h index 9a1aac9f..81accf4d 100644 --- a/ash/system/bluetooth/bluetooth_notification_controller.h +++ b/ash/system/bluetooth/bluetooth_notification_controller.h
@@ -62,14 +62,6 @@ friend class BluetoothNotificationControllerTest; class BluetoothPairedNotificationDelegate; - // Wraps calls to settings code which are mocked out for tests. - class OpenUiDelegate { - public: - OpenUiDelegate() = default; - virtual ~OpenUiDelegate() = default; - virtual void OpenBluetoothSettings(); - }; - static const char kBluetoothDeviceDiscoverableNotificationId[]; // Identifier for the pairing notification; the Bluetooth code ensures we // only receive one pairing request at a time, so a single id is sufficient @@ -98,8 +90,6 @@ // Clears any shown pairing notification now that the device has been paired. void NotifyPairedDevice(device::BluetoothDevice* device); - std::unique_ptr<OpenUiDelegate> open_delegate_; - message_center::MessageCenter* const message_center_; // Reference to the underlying BluetoothAdapter object, holding this reference
diff --git a/ash/system/bluetooth/bluetooth_notification_controller_unittest.cc b/ash/system/bluetooth/bluetooth_notification_controller_unittest.cc index 180c7f2..5f83047 100644 --- a/ash/system/bluetooth/bluetooth_notification_controller_unittest.cc +++ b/ash/system/bluetooth/bluetooth_notification_controller_unittest.cc
@@ -7,11 +7,11 @@ #include <memory> #include <utility> +#include "ash/public/cpp/test/test_system_tray_client.h" #include "ash/session/test_session_controller_client.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/tray/tray_popup_utils.h" #include "ash/test/ash_test_base.h" -#include "ash/test/ash_test_helper.h" #include "base/containers/flat_map.h" #include "base/logging.h" #include "base/memory/ptr_util.h" @@ -47,27 +47,6 @@ class BluetoothNotificationControllerTest : public AshTestBase { public: - class TestOpenUiDelegate - : public BluetoothNotificationController::OpenUiDelegate { - public: - TestOpenUiDelegate() = default; - ~TestOpenUiDelegate() override = default; - - size_t open_bluetooth_settings_ui_count() const { - return open_bluetooth_settings_ui_count_; - } - - void OpenBluetoothSettings() override { - ++open_bluetooth_settings_ui_count_; - } - - private: - size_t open_bluetooth_settings_ui_count_ = 0u; - - DISALLOW_COPY_AND_ASSIGN(TestOpenUiDelegate); - }; - - protected: BluetoothNotificationControllerTest() = default; void SetUp() override { @@ -75,9 +54,7 @@ notification_controller_ = std::make_unique<BluetoothNotificationController>( &test_message_center_); - auto open_delegate = std::make_unique<TestOpenUiDelegate>(); - open_ui_delegate_ = open_delegate.get(); - notification_controller_->open_delegate_ = std::move(open_delegate); + system_tray_client_ = GetSystemTrayClient(); bluetooth_device_ = std::make_unique<testing::NiceMock<device::MockBluetoothDevice>>( nullptr /* adapter */, 0 /* bluetooth_class */, "name", "address", @@ -126,7 +103,7 @@ TestMessageCenter test_message_center_; std::unique_ptr<BluetoothNotificationController> notification_controller_; - TestOpenUiDelegate* open_ui_delegate_; + TestSystemTrayClient* system_tray_client_; std::unique_ptr<device::MockBluetoothDevice> bluetooth_device_; DISALLOW_COPY_AND_ASSIGN(BluetoothNotificationControllerTest); @@ -146,7 +123,7 @@ VerifyPairedNotificationIsVisible(bluetooth_device_.get()); // Check the notification controller tried to open the UI. - EXPECT_EQ(1u, open_ui_delegate_->open_bluetooth_settings_ui_count()); + EXPECT_EQ(1, system_tray_client_->show_bluetooth_settings_count()); } TEST_F(BluetoothNotificationControllerTest, @@ -160,7 +137,7 @@ VerifyPairedNotificationIsNotVisible(); // The settings UI should not open when closing the notification. - EXPECT_EQ(0u, open_ui_delegate_->open_bluetooth_settings_ui_count()); + EXPECT_EQ(0, system_tray_client_->show_bluetooth_settings_count()); } TEST_F(BluetoothNotificationControllerTest, @@ -173,7 +150,7 @@ DismissPairedNotification(false /* by_user */); VerifyPairedNotificationIsNotVisible(); - EXPECT_EQ(0u, open_ui_delegate_->open_bluetooth_settings_ui_count()); + EXPECT_EQ(0, system_tray_client_->show_bluetooth_settings_count()); } } // namespace ash
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc index 5e3b9b7..d606c44 100644 --- a/ash/test/ash_test_base.cc +++ b/ash/test/ash_test_base.cc
@@ -361,6 +361,10 @@ return ash_test_helper_->test_session_controller_client(); } +TestSystemTrayClient* AshTestBase::GetSystemTrayClient() { + return ash_test_helper_->system_tray_client(); +} + AppListTestHelper* AshTestBase::GetAppListTestHelper() { return ash_test_helper_->app_list_test_helper(); }
diff --git a/ash/test/ash_test_base.h b/ash/test/ash_test_base.h index da1a195a1..1a9a676 100644 --- a/ash/test/ash_test_base.h +++ b/ash/test/ash_test_base.h
@@ -67,6 +67,7 @@ class AshTestHelper; class Shelf; class TestScreenshotDelegate; +class TestSystemTrayClient; class UnifiedSystemTray; class WorkAreaInsets; @@ -194,6 +195,8 @@ TestSessionControllerClient* GetSessionControllerClient(); + TestSystemTrayClient* GetSystemTrayClient(); + AppListTestHelper* GetAppListTestHelper(); // Emulates an ash session that have |session_count| user sessions running.
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc index c8c0c10..64ca13e 100644 --- a/ash/test/ash_test_helper.cc +++ b/ash/test/ash_test_helper.cc
@@ -19,10 +19,12 @@ #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/test/test_keyboard_controller_observer.h" #include "ash/public/cpp/test/test_new_window_delegate.h" +#include "ash/public/cpp/test/test_system_tray_client.h" #include "ash/session/test_pref_service_provider.h" #include "ash/session/test_session_controller_client.h" #include "ash/shell.h" #include "ash/shell_init_params.h" +#include "ash/system/model/system_tray_model.h" #include "ash/system/screen_layout_observer.h" #include "ash/test/ash_test_views_delegate.h" #include "ash/test_shell_delegate.h" @@ -151,6 +153,9 @@ shell->session_controller(), prefs_provider_.get())); session_controller_client_->InitializeAndSetClient(); + system_tray_client_ = std::make_unique<TestSystemTrayClient>(); + shell->system_tray_model()->SetClient(system_tray_client_.get()); + if (start_session) session_controller_client_->CreatePredefinedUserSessions(1);
diff --git a/ash/test/ash_test_helper.h b/ash/test/ash_test_helper.h index be17ffa..aac29cd 100644 --- a/ash/test/ash_test_helper.h +++ b/ash/test/ash_test_helper.h
@@ -47,6 +47,7 @@ class TestNewWindowDelegate; class TestPrefServiceProvider; class TestShellDelegate; +class TestSystemTrayClient; // A helper class that does common initialization required for Ash. Creates a // root window and an ash::Shell instance with a test delegate. @@ -88,6 +89,9 @@ std::unique_ptr<TestSessionControllerClient> session_controller_client) { session_controller_client_ = std::move(session_controller_client); } + TestSystemTrayClient* system_tray_client() { + return system_tray_client_.get(); + } TestPrefServiceProvider* prefs_provider() { return prefs_provider_.get(); } AppListTestHelper* app_list_test_helper() { @@ -118,6 +122,7 @@ bool power_policy_controller_initialized_ = false; std::unique_ptr<TestSessionControllerClient> session_controller_client_; + std::unique_ptr<TestSystemTrayClient> system_tray_client_; std::unique_ptr<TestPrefServiceProvider> prefs_provider_; std::unique_ptr<ui::TestContextFactories> context_factories_;
diff --git a/base/command_line.cc b/base/command_line.cc index 3f13db20..1451251 100644 --- a/base/command_line.cc +++ b/base/command_line.cc
@@ -286,7 +286,7 @@ bool CommandLine::HasSwitch(const StringPiece& switch_string) const { DCHECK_EQ(ToLowerASCII(switch_string), switch_string); - return ContainsKey(switches_, switch_string); + return Contains(switches_, switch_string); } bool CommandLine::HasSwitch(const char switch_constant[]) const {
diff --git a/base/cpu_unittest.cc b/base/cpu_unittest.cc index 8a68ea0..b6403af 100644 --- a/base/cpu_unittest.cc +++ b/base/cpu_unittest.cc
@@ -129,6 +129,6 @@ // For https://crbug.com/249713 TEST(CPU, BrandAndVendorContainsNoNUL) { base::CPU cpu; - EXPECT_FALSE(base::ContainsValue(cpu.cpu_brand(), '\0')); - EXPECT_FALSE(base::ContainsValue(cpu.vendor_name(), '\0')); + EXPECT_FALSE(base::Contains(cpu.cpu_brand(), '\0')); + EXPECT_FALSE(base::Contains(cpu.vendor_name(), '\0')); }
diff --git a/base/debug/activity_analyzer.cc b/base/debug/activity_analyzer.cc index 1bd60262..d84dd0e 100644 --- a/base/debug/activity_analyzer.cc +++ b/base/debug/activity_analyzer.cc
@@ -354,7 +354,7 @@ // Add this analyzer to the map of known ones, indexed by a unique // thread // identifier. - DCHECK(!base::ContainsKey(analyzers_, analyzer->GetThreadKey())); + DCHECK(!base::Contains(analyzers_, analyzer->GetThreadKey())); analyzer->allocator_reference_ = ref; analyzers_[analyzer->GetThreadKey()] = std::move(analyzer); } break; @@ -364,7 +364,7 @@ int64_t process_id; int64_t create_stamp; ActivityUserData::GetOwningProcessId(base, &process_id, &create_stamp); - DCHECK(!base::ContainsKey(process_data_, process_id)); + DCHECK(!base::Contains(process_data_, process_id)); // Create a snapshot of the data. This can fail if the data is somehow // corrupted or the process shutdown and the memory being released.
diff --git a/base/debug/activity_analyzer_unittest.cc b/base/debug/activity_analyzer_unittest.cc index 15b08f9..4fdc2d27 100644 --- a/base/debug/activity_analyzer_unittest.cc +++ b/base/debug/activity_analyzer_unittest.cc
@@ -294,22 +294,22 @@ const ActivityUserData::Snapshot& user_data = analyzer_snapshot.user_data_stack.at(1); EXPECT_EQ(8U, user_data.size()); - ASSERT_TRUE(ContainsKey(user_data, "raw2")); + ASSERT_TRUE(Contains(user_data, "raw2")); EXPECT_EQ("foo2", user_data.at("raw2").Get().as_string()); - ASSERT_TRUE(ContainsKey(user_data, "string2")); + ASSERT_TRUE(Contains(user_data, "string2")); EXPECT_EQ("bar2", user_data.at("string2").GetString().as_string()); - ASSERT_TRUE(ContainsKey(user_data, "char2")); + ASSERT_TRUE(Contains(user_data, "char2")); EXPECT_EQ('2', user_data.at("char2").GetChar()); - ASSERT_TRUE(ContainsKey(user_data, "int2")); + ASSERT_TRUE(Contains(user_data, "int2")); EXPECT_EQ(-2222, user_data.at("int2").GetInt()); - ASSERT_TRUE(ContainsKey(user_data, "uint2")); + ASSERT_TRUE(Contains(user_data, "uint2")); EXPECT_EQ(2222U, user_data.at("uint2").GetUint()); - ASSERT_TRUE(ContainsKey(user_data, "bool2")); + ASSERT_TRUE(Contains(user_data, "bool2")); EXPECT_FALSE(user_data.at("bool2").GetBool()); - ASSERT_TRUE(ContainsKey(user_data, "ref2")); + ASSERT_TRUE(Contains(user_data, "ref2")); EXPECT_EQ(string2a, user_data.at("ref2").GetReference().data()); EXPECT_EQ(sizeof(string2a), user_data.at("ref2").GetReference().size()); - ASSERT_TRUE(ContainsKey(user_data, "sref2")); + ASSERT_TRUE(Contains(user_data, "sref2")); EXPECT_EQ(string2b, user_data.at("sref2").GetStringReference().data()); EXPECT_EQ(strlen(string2b), user_data.at("sref2").GetStringReference().size()); @@ -372,22 +372,22 @@ DCHECK_EQ(pid, first_pid); const ActivityUserData::Snapshot& snapshot = global_analyzer.GetProcessDataSnapshot(pid); - ASSERT_TRUE(ContainsKey(snapshot, "raw")); + ASSERT_TRUE(Contains(snapshot, "raw")); EXPECT_EQ("foo", snapshot.at("raw").Get().as_string()); - ASSERT_TRUE(ContainsKey(snapshot, "string")); + ASSERT_TRUE(Contains(snapshot, "string")); EXPECT_EQ("bar", snapshot.at("string").GetString().as_string()); - ASSERT_TRUE(ContainsKey(snapshot, "char")); + ASSERT_TRUE(Contains(snapshot, "char")); EXPECT_EQ('9', snapshot.at("char").GetChar()); - ASSERT_TRUE(ContainsKey(snapshot, "int")); + ASSERT_TRUE(Contains(snapshot, "int")); EXPECT_EQ(-9999, snapshot.at("int").GetInt()); - ASSERT_TRUE(ContainsKey(snapshot, "uint")); + ASSERT_TRUE(Contains(snapshot, "uint")); EXPECT_EQ(9999U, snapshot.at("uint").GetUint()); - ASSERT_TRUE(ContainsKey(snapshot, "bool")); + ASSERT_TRUE(Contains(snapshot, "bool")); EXPECT_TRUE(snapshot.at("bool").GetBool()); - ASSERT_TRUE(ContainsKey(snapshot, "ref")); + ASSERT_TRUE(Contains(snapshot, "ref")); EXPECT_EQ(string1, snapshot.at("ref").GetReference().data()); EXPECT_EQ(sizeof(string1), snapshot.at("ref").GetReference().size()); - ASSERT_TRUE(ContainsKey(snapshot, "sref")); + ASSERT_TRUE(Contains(snapshot, "sref")); EXPECT_EQ(string2, snapshot.at("sref").GetStringReference().data()); EXPECT_EQ(strlen(string2), snapshot.at("sref").GetStringReference().size()); }
diff --git a/base/debug/activity_tracker.cc b/base/debug/activity_tracker.cc index f5ee9c48..fbf49c7 100644 --- a/base/debug/activity_tracker.cc +++ b/base/debug/activity_tracker.cc
@@ -1427,7 +1427,7 @@ DCHECK_NE(0, pid); base::AutoLock lock(global_tracker_lock_); - if (base::ContainsKey(known_processes_, pid)) { + if (base::Contains(known_processes_, pid)) { // TODO(bcwhite): Measure this in UMA. NOTREACHED() << "Process #" << process_id << " was previously recorded as \"launched\""
diff --git a/base/debug/debugger_posix.cc b/base/debug/debugger_posix.cc index 674a78b..45bf1da 100644 --- a/base/debug/debugger_posix.cc +++ b/base/debug/debugger_posix.cc
@@ -19,7 +19,6 @@ #include "base/clang_coverage_buildflags.h" #include "base/stl_util.h" -#include "base/test/clang_coverage.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "build/build_config.h" @@ -52,6 +51,10 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" +#if BUILDFLAG(CLANG_COVERAGE) +#include "base/test/clang_coverage.h" +#endif + #if defined(USE_SYMBOLIZE) #include "base/third_party/symbolize/symbolize.h" #endif
diff --git a/base/debug/debugger_win.cc b/base/debug/debugger_win.cc index 53dfcd2..fd10b4b 100644 --- a/base/debug/debugger_win.cc +++ b/base/debug/debugger_win.cc
@@ -8,7 +8,10 @@ #include <windows.h> #include "base/clang_coverage_buildflags.h" + +#if BUILDFLAG(CLANG_COVERAGE) #include "base/test/clang_coverage.h" +#endif namespace base { namespace debug {
diff --git a/base/feature_list.cc b/base/feature_list.cc index a92ec44..56aa03c 100644 --- a/base/feature_list.cc +++ b/base/feature_list.cc
@@ -150,7 +150,7 @@ OverrideState override_state, FieldTrial* field_trial) { DCHECK(field_trial); - DCHECK(!ContainsKey(overrides_, feature_name) || + DCHECK(!Contains(overrides_, feature_name) || !overrides_.find(feature_name)->second.field_trial) << "Feature " << feature_name << " has conflicting field trial overrides: "
diff --git a/base/files/file_path_watcher_linux.cc b/base/files/file_path_watcher_linux.cc index 0ff8924..266d66b 100644 --- a/base/files/file_path_watcher_linux.cc +++ b/base/files/file_path_watcher_linux.cc
@@ -496,7 +496,7 @@ } } - if (ContainsKey(recursive_paths_by_watch_, fired_watch)) { + if (Contains(recursive_paths_by_watch_, fired_watch)) { if (!did_update) UpdateRecursiveWatches(fired_watch, is_dir); callback_.Run(target_, false /* error */); @@ -607,7 +607,7 @@ // Check to see if this is a forced update or if some component of |target_| // has changed. For these cases, redo the watches for |target_| and below. - if (!ContainsKey(recursive_paths_by_watch_, fired_watch) && + if (!Contains(recursive_paths_by_watch_, fired_watch) && fired_watch != watches_.back().watch) { UpdateRecursiveWatchesForPath(target_); return; @@ -617,10 +617,9 @@ if (!is_dir) return; - const FilePath& changed_dir = - ContainsKey(recursive_paths_by_watch_, fired_watch) ? - recursive_paths_by_watch_[fired_watch] : - target_; + const FilePath& changed_dir = Contains(recursive_paths_by_watch_, fired_watch) + ? recursive_paths_by_watch_[fired_watch] + : target_; auto start_it = recursive_watches_by_path_.lower_bound(changed_dir); auto end_it = start_it; @@ -652,7 +651,7 @@ current = enumerator.Next()) { DCHECK(enumerator.GetInfo().IsDirectory()); - if (!ContainsKey(recursive_watches_by_path_, current)) { + if (!Contains(recursive_watches_by_path_, current)) { // Add new watches. InotifyReader::Watch watch = g_inotify_reader.Get().AddWatch(current, this); @@ -686,8 +685,8 @@ if (watch == InotifyReader::kInvalidWatch) return; - DCHECK(!ContainsKey(recursive_paths_by_watch_, watch)); - DCHECK(!ContainsKey(recursive_watches_by_path_, path)); + DCHECK(!Contains(recursive_paths_by_watch_, watch)); + DCHECK(!Contains(recursive_watches_by_path_, path)); recursive_paths_by_watch_[watch] = path; recursive_watches_by_path_[path] = watch; }
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc index c05a09b..11bf492 100644 --- a/base/files/file_util_posix.cc +++ b/base/files/file_util_posix.cc
@@ -114,7 +114,7 @@ } if ((stat_info.st_mode & S_IWGRP) && - !ContainsKey(group_gids, stat_info.st_gid)) { + !Contains(group_gids, stat_info.st_gid)) { DLOG(ERROR) << "Path " << path.value() << " is writable by an unprivileged group."; return false;
diff --git a/base/ios/crb_protocol_observers.mm b/base/ios/crb_protocol_observers.mm index 1a3b9f73..86a081e 100644 --- a/base/ios/crb_protocol_observers.mm +++ b/base/ios/crb_protocol_observers.mm
@@ -104,7 +104,7 @@ DCHECK(observer); DCHECK([observer conformsToProtocol:self.protocol]); - if (base::ContainsValue(_observers, observer)) + if (base::Contains(_observers, observer)) return; _observers.push_back(observer);
diff --git a/base/mac/objc_release_properties_unittest.mm b/base/mac/objc_release_properties_unittest.mm index 5f15650..4b51e42 100644 --- a/base/mac/objc_release_properties_unittest.mm +++ b/base/mac/objc_release_properties_unittest.mm
@@ -217,7 +217,7 @@ @selector(baseCvcDynamic), @selector(derivedCvcDynamic), @selector(protoCvcDynamic), }; - if (!base::ContainsValue(dynamicMethods, sel)) { + if (!base::Contains(dynamicMethods, sel)) { return NO; } id (*imp)() = []() -> id { return nil; };
diff --git a/base/memory/shared_memory_mapping.cc b/base/memory/shared_memory_mapping.cc index 2be25700..8426fa8 100644 --- a/base/memory/shared_memory_mapping.cc +++ b/base/memory/shared_memory_mapping.cc
@@ -33,7 +33,7 @@ SharedMemoryMapping::SharedMemoryMapping() = default; -SharedMemoryMapping::SharedMemoryMapping(SharedMemoryMapping&& mapping) +SharedMemoryMapping::SharedMemoryMapping(SharedMemoryMapping&& mapping) noexcept : memory_(mapping.memory_), size_(mapping.size_), mapped_size_(mapping.mapped_size_), @@ -42,7 +42,7 @@ } SharedMemoryMapping& SharedMemoryMapping::operator=( - SharedMemoryMapping&& mapping) { + SharedMemoryMapping&& mapping) noexcept { Unmap(); memory_ = mapping.memory_; size_ = mapping.size_; @@ -90,9 +90,9 @@ ReadOnlySharedMemoryMapping::ReadOnlySharedMemoryMapping() = default; ReadOnlySharedMemoryMapping::ReadOnlySharedMemoryMapping( - ReadOnlySharedMemoryMapping&&) = default; + ReadOnlySharedMemoryMapping&&) noexcept = default; ReadOnlySharedMemoryMapping& ReadOnlySharedMemoryMapping::operator=( - ReadOnlySharedMemoryMapping&&) = default; + ReadOnlySharedMemoryMapping&&) noexcept = default; ReadOnlySharedMemoryMapping::ReadOnlySharedMemoryMapping( void* address, size_t size, @@ -102,9 +102,9 @@ WritableSharedMemoryMapping::WritableSharedMemoryMapping() = default; WritableSharedMemoryMapping::WritableSharedMemoryMapping( - WritableSharedMemoryMapping&&) = default; + WritableSharedMemoryMapping&&) noexcept = default; WritableSharedMemoryMapping& WritableSharedMemoryMapping::operator=( - WritableSharedMemoryMapping&&) = default; + WritableSharedMemoryMapping&&) noexcept = default; WritableSharedMemoryMapping::WritableSharedMemoryMapping( void* address, size_t size,
diff --git a/base/memory/shared_memory_mapping.h b/base/memory/shared_memory_mapping.h index d9569af..2b8858e 100644 --- a/base/memory/shared_memory_mapping.h +++ b/base/memory/shared_memory_mapping.h
@@ -32,8 +32,8 @@ SharedMemoryMapping(); // Move operations are allowed. - SharedMemoryMapping(SharedMemoryMapping&& mapping); - SharedMemoryMapping& operator=(SharedMemoryMapping&& mapping); + SharedMemoryMapping(SharedMemoryMapping&& mapping) noexcept; + SharedMemoryMapping& operator=(SharedMemoryMapping&& mapping) noexcept; // Unmaps the region if the mapping is valid. virtual ~SharedMemoryMapping(); @@ -93,8 +93,9 @@ ReadOnlySharedMemoryMapping(); // Move operations are allowed. - ReadOnlySharedMemoryMapping(ReadOnlySharedMemoryMapping&&); - ReadOnlySharedMemoryMapping& operator=(ReadOnlySharedMemoryMapping&&); + ReadOnlySharedMemoryMapping(ReadOnlySharedMemoryMapping&&) noexcept; + ReadOnlySharedMemoryMapping& operator=( + ReadOnlySharedMemoryMapping&&) noexcept; // Returns the base address of the mapping. This is read-only memory. This is // page-aligned. This is nullptr for invalid instances. @@ -171,8 +172,9 @@ WritableSharedMemoryMapping(); // Move operations are allowed. - WritableSharedMemoryMapping(WritableSharedMemoryMapping&&); - WritableSharedMemoryMapping& operator=(WritableSharedMemoryMapping&&); + WritableSharedMemoryMapping(WritableSharedMemoryMapping&&) noexcept; + WritableSharedMemoryMapping& operator=( + WritableSharedMemoryMapping&&) noexcept; // Returns the base address of the mapping. This is writable memory. This is // page-aligned. This is nullptr for invalid instances.
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc index 94e663f..9236f44 100644 --- a/base/metrics/field_trial.cc +++ b/base/metrics/field_trial.cc
@@ -733,7 +733,7 @@ const std::string trial_name = entry.trial_name.as_string(); const std::string group_name = entry.group_name.as_string(); - if (ContainsKey(ignored_trial_names, trial_name)) { + if (Contains(ignored_trial_names, trial_name)) { // This is to warn that the field trial forced through command-line // input is unforcable. // Use --enable-logging or --enable-logging=stderr to see this warning.
diff --git a/base/metrics/field_trial_param_associator.cc b/base/metrics/field_trial_param_associator.cc index af76eaf..6360b8c 100644 --- a/base/metrics/field_trial_param_associator.cc +++ b/base/metrics/field_trial_param_associator.cc
@@ -26,7 +26,7 @@ AutoLock scoped_lock(lock_); const FieldTrialKey key(trial_name, group_name); - if (ContainsKey(field_trial_params_, key)) + if (Contains(field_trial_params_, key)) return false; field_trial_params_[key] = params; @@ -57,7 +57,7 @@ AutoLock scoped_lock(lock_); const FieldTrialKey key(trial_name, group_name); - if (!ContainsKey(field_trial_params_, key)) + if (!Contains(field_trial_params_, key)) return false; *params = field_trial_params_[key];
diff --git a/base/metrics/histogram_snapshot_manager_unittest.cc b/base/metrics/histogram_snapshot_manager_unittest.cc index 1e2c599..2fbf182 100644 --- a/base/metrics/histogram_snapshot_manager_unittest.cc +++ b/base/metrics/histogram_snapshot_manager_unittest.cc
@@ -25,8 +25,7 @@ const HistogramSamples& snapshot) override { recorded_delta_histogram_names_.push_back(histogram.histogram_name()); // Use CHECK instead of ASSERT to get full stack-trace and thus origin. - CHECK(!ContainsKey(recorded_delta_histogram_sum_, - histogram.histogram_name())); + CHECK(!Contains(recorded_delta_histogram_sum_, histogram.histogram_name())); // Keep pointer to snapshot for testing. This really isn't ideal but the // snapshot-manager keeps the snapshot alive until it's "forgotten". recorded_delta_histogram_sum_[histogram.histogram_name()] = snapshot.sum(); @@ -42,7 +41,7 @@ } int64_t GetRecordedDeltaHistogramSum(const std::string& name) { - EXPECT_TRUE(ContainsKey(recorded_delta_histogram_sum_, name)); + EXPECT_TRUE(Contains(recorded_delta_histogram_sum_, name)); return recorded_delta_histogram_sum_[name]; }
diff --git a/base/metrics/persistent_sample_map.cc b/base/metrics/persistent_sample_map.cc index e07b716..ba73128b 100644 --- a/base/metrics/persistent_sample_map.cc +++ b/base/metrics/persistent_sample_map.cc
@@ -276,7 +276,7 @@ DCHECK_EQ(id(), record->id); // Check if the record's value is already known. - if (!ContainsKey(sample_counts_, record->value)) { + if (!Contains(sample_counts_, record->value)) { // No: Add it to map of known values. sample_counts_[record->value] = &record->count; } else {
diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h index 5036ffc..6388ba4 100644 --- a/base/observer_list_threadsafe.h +++ b/base/observer_list_threadsafe.h
@@ -107,7 +107,7 @@ AutoLock auto_lock(lock_); // Add |observer| to the list of observers. - DCHECK(!ContainsKey(observers_, observer)); + DCHECK(!Contains(observers_, observer)); const scoped_refptr<SequencedTaskRunner> task_runner = SequencedTaskRunnerHandle::Get(); observers_[observer] = task_runner;
diff --git a/base/process/process_fuchsia.cc b/base/process/process_fuchsia.cc index 8ecf9d61..f260575 100644 --- a/base/process/process_fuchsia.cc +++ b/base/process/process_fuchsia.cc
@@ -13,7 +13,10 @@ #include "base/fuchsia/default_job.h" #include "base/fuchsia/fuchsia_logging.h" #include "base/strings/stringprintf.h" + +#if BUILDFLAG(CLANG_COVERAGE) #include "base/test/clang_coverage.h" +#endif namespace base {
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc index 38ee542..9636d44 100644 --- a/base/process/process_posix.cc +++ b/base/process/process_posix.cc
@@ -16,7 +16,6 @@ #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "base/process/kill.h" -#include "base/test/clang_coverage.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" @@ -24,6 +23,10 @@ #include <sys/event.h> #endif +#if BUILDFLAG(CLANG_COVERAGE) +#include "base/test/clang_coverage.h" +#endif + namespace { #if !defined(OS_NACL_NONSFI)
diff --git a/base/process/process_win.cc b/base/process/process_win.cc index ae97a92..dd065b6 100644 --- a/base/process/process_win.cc +++ b/base/process/process_win.cc
@@ -9,11 +9,14 @@ #include "base/logging.h" #include "base/numerics/safe_conversions.h" #include "base/process/kill.h" -#include "base/test/clang_coverage.h" #include "base/threading/thread_restrictions.h" #include <windows.h> +#if BUILDFLAG(CLANG_COVERAGE) +#include "base/test/clang_coverage.h" +#endif + namespace { DWORD kBasicProcessAccess =
diff --git a/base/sampling_heap_profiler/sampling_heap_profiler.cc b/base/sampling_heap_profiler/sampling_heap_profiler.cc index f8736ef..676beca 100644 --- a/base/sampling_heap_profiler/sampling_heap_profiler.cc +++ b/base/sampling_heap_profiler/sampling_heap_profiler.cc
@@ -17,7 +17,6 @@ #include "base/no_destructor.h" #include "base/partition_alloc_buildflags.h" #include "base/sampling_heap_profiler/lock_free_address_hash_set.h" -#include "base/threading/thread_id_name_manager.h" #include "base/threading/thread_local_storage.h" #include "base/trace_event/heap_profiler_allocation_context_tracker.h" #include "build/build_config.h" @@ -94,7 +93,10 @@ SamplingHeapProfiler::Sample::~Sample() = default; SamplingHeapProfiler::SamplingHeapProfiler() = default; -SamplingHeapProfiler::~SamplingHeapProfiler() = default; +SamplingHeapProfiler::~SamplingHeapProfiler() { + if (record_thread_names_) + base::ThreadIdNameManager::GetInstance()->RemoveObserver(this); +} uint32_t SamplingHeapProfiler::Start() { #if defined(OS_ANDROID) && BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && \ @@ -124,10 +126,13 @@ } void SamplingHeapProfiler::SetRecordThreadNames(bool value) { + if (record_thread_names_ == value) + return; record_thread_names_ = value; if (value) { - base::ThreadIdNameManager::GetInstance()->InstallSetNameCallback( - base::BindRepeating(IgnoreResult(&UpdateAndGetThreadName))); + base::ThreadIdNameManager::GetInstance()->AddObserver(this); + } else { + base::ThreadIdNameManager::GetInstance()->RemoveObserver(this); } } @@ -284,4 +289,8 @@ return instance.get(); } +void SamplingHeapProfiler::OnThreadNameChanged(const char* name) { + UpdateAndGetThreadName(name); +} + } // namespace base
diff --git a/base/sampling_heap_profiler/sampling_heap_profiler.h b/base/sampling_heap_profiler/sampling_heap_profiler.h index 398bf0e9..a1dca2ec 100644 --- a/base/sampling_heap_profiler/sampling_heap_profiler.h +++ b/base/sampling_heap_profiler/sampling_heap_profiler.h
@@ -14,6 +14,7 @@ #include "base/macros.h" #include "base/sampling_heap_profiler/poisson_allocation_sampler.h" #include "base/synchronization/lock.h" +#include "base/threading/thread_id_name_manager.h" namespace base { @@ -25,7 +26,8 @@ // record samples. // The recorded samples can then be retrieved using GetSamples method. class BASE_EXPORT SamplingHeapProfiler - : private PoissonAllocationSampler::SamplesObserver { + : private PoissonAllocationSampler::SamplesObserver, + public base::ThreadIdNameManager::Observer { public: class BASE_EXPORT Sample { public: @@ -95,6 +97,9 @@ static void Init(); static SamplingHeapProfiler* Get(); + // ThreadIdNameManager::Observer implementation: + void OnThreadNameChanged(const char* name) override; + private: SamplingHeapProfiler(); ~SamplingHeapProfiler() override;
diff --git a/base/scoped_generic_unittest.cc b/base/scoped_generic_unittest.cc index f75adf0..73291a8 100644 --- a/base/scoped_generic_unittest.cc +++ b/base/scoped_generic_unittest.cc
@@ -215,18 +215,18 @@ std::unordered_set<int> freed; TrackedIntTraits traits(&freed, &owners); -#define ASSERT_OWNED(value, owner) \ - ASSERT_TRUE(base::ContainsKey(owners, value)); \ - ASSERT_EQ(&owner, owners[value]); \ - ASSERT_FALSE(base::ContainsKey(freed, value)) +#define ASSERT_OWNED(value, owner) \ + ASSERT_TRUE(base::Contains(owners, value)); \ + ASSERT_EQ(&owner, owners[value]); \ + ASSERT_FALSE(base::Contains(freed, value)) -#define ASSERT_UNOWNED(value) \ - ASSERT_FALSE(base::ContainsKey(owners, value)); \ - ASSERT_FALSE(base::ContainsKey(freed, value)) +#define ASSERT_UNOWNED(value) \ + ASSERT_FALSE(base::Contains(owners, value)); \ + ASSERT_FALSE(base::Contains(freed, value)) -#define ASSERT_FREED(value) \ - ASSERT_FALSE(base::ContainsKey(owners, value)); \ - ASSERT_TRUE(base::ContainsKey(freed, value)) +#define ASSERT_FREED(value) \ + ASSERT_FALSE(base::Contains(owners, value)); \ + ASSERT_TRUE(base::Contains(freed, value)) // Constructor. {
diff --git a/base/scoped_observer.h b/base/scoped_observer.h index 7f1d6fba..ecad6c0 100644 --- a/base/scoped_observer.h +++ b/base/scoped_observer.h
@@ -47,7 +47,7 @@ } bool IsObserving(Source* source) const { - return base::ContainsValue(sources_, source); + return base::Contains(sources_, source); } bool IsObservingSources() const { return !sources_.empty(); }
diff --git a/base/stl_util.h b/base/stl_util.h index 3a4dd7f..18d44616b 100644 --- a/base/stl_util.h +++ b/base/stl_util.h
@@ -221,6 +221,8 @@ // Test to see if a set or map contains a particular key. // Returns true if the key is in the collection. +// TODO(crbug.com/970209): Replace usages of ContainsKey() with Contains() and +// remove this method. template <typename Collection, typename Key> bool ContainsKey(const Collection& collection, const Key& key) { return Contains(collection, key); @@ -228,6 +230,8 @@ // Test to see if a collection like a vector contains a particular value. // Returns true if the value is in the collection. +// TODO(crbug.com/970209): Replace usages of ContainsValue() with Contains() and +// remove this method. template <typename Collection, typename Value> bool ContainsValue(const Collection& collection, const Value& value) { return Contains(collection, value);
diff --git a/base/task/thread_pool/worker_thread_stack.cc b/base/task/thread_pool/worker_thread_stack.cc index f6f2610..40eadde 100644 --- a/base/task/thread_pool/worker_thread_stack.cc +++ b/base/task/thread_pool/worker_thread_stack.cc
@@ -41,7 +41,7 @@ } bool WorkerThreadStack::Contains(const WorkerThread* worker) const { - return ContainsValue(stack_, worker); + return base::Contains(stack_, worker); } void WorkerThreadStack::Remove(const WorkerThread* worker) {
diff --git a/base/test/clang_coverage.h b/base/test/clang_coverage.h index 44337f1f..ed2e3d7 100644 --- a/base/test/clang_coverage.h +++ b/base/test/clang_coverage.h
@@ -5,6 +5,12 @@ #ifndef BASE_TEST_CLANG_COVERAGE_H_ #define BASE_TEST_CLANG_COVERAGE_H_ +#include "base/clang_coverage_buildflags.h" + +#if !BUILDFLAG(CLANG_COVERAGE) +#error "Clang coverage can only be used if CLANG_COVERAGE macro is defined" +#endif + namespace base { // Write out the accumulated code coverage profile to the configured file. @@ -13,7 +19,6 @@ // (or triggering a debug crash), where the automatic at-exit writer will not // be invoked. // This call is thread-safe, and will write profiling data at-most-once. -// Call-sites invoke this API only if the CLANG_COVERAGE macro is defined. void WriteClangCoverageProfile(); } // namespace base
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc index 56b197c..b3951485 100644 --- a/base/test/launcher/test_launcher.cc +++ b/base/test/launcher/test_launcher.cc
@@ -1242,7 +1242,7 @@ std::vector<TestInfo> tests_to_run; for (const TestInfo& test_info : tests_) { // If any test has a matching disabled test, fail and log for audit. - if (base::ContainsKey(disabled_tests, test_info.GetFullName())) { + if (base::Contains(disabled_tests, test_info.GetFullName())) { LOG(ERROR) << test_info.GetFullName() << " duplicated by a DISABLED_ test"; result = false;
diff --git a/base/test/launcher/unit_test_launcher.cc b/base/test/launcher/unit_test_launcher.cc index cfd517b3..bcac932 100644 --- a/base/test/launcher/unit_test_launcher.cc +++ b/base/test/launcher/unit_test_launcher.cc
@@ -282,7 +282,7 @@ std::vector<TestResult> final_results; for (const auto& i : test_names) { - if (ContainsKey(results_map, i)) { + if (Contains(results_map, i)) { TestResult test_result = results_map[i]; if (test_result.status == TestResult::TEST_CRASH) { if (was_timeout) {
diff --git a/base/test/scoped_feature_list.cc b/base/test/scoped_feature_list.cc index 01a5e75..0cc910c 100644 --- a/base/test/scoped_feature_list.cc +++ b/base/test/scoped_feature_list.cc
@@ -68,8 +68,8 @@ for (StringPiece feature : features_list) { StringPiece feature_name = GetFeatureName(feature); - if (ContainsValue(merged_features->enabled_feature_list, feature_name) || - ContainsValue(merged_features->disabled_feature_list, feature_name)) + if (Contains(merged_features->enabled_feature_list, feature_name) || + Contains(merged_features->disabled_feature_list, feature_name)) continue; if (override_state == FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE) {
diff --git a/base/threading/thread_id_name_manager.cc b/base/threading/thread_id_name_manager.cc index a0ced2c5..ba2f9b4 100644 --- a/base/threading/thread_id_name_manager.cc +++ b/base/threading/thread_id_name_manager.cc
@@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/memory/singleton.h" #include "base/no_destructor.h" +#include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/threading/thread_local.h" #include "base/trace_event/heap_profiler_allocation_context_tracker.h" @@ -26,6 +27,8 @@ } } +ThreadIdNameManager::Observer::~Observer() = default; + ThreadIdNameManager::ThreadIdNameManager() : main_process_name_(nullptr), main_process_id_(kInvalidThreadId) { g_default_name = new std::string(kDefaultName); @@ -53,9 +56,16 @@ name_to_interned_name_[kDefaultName]; } -void ThreadIdNameManager::InstallSetNameCallback(SetNameCallback callback) { +void ThreadIdNameManager::AddObserver(Observer* obs) { AutoLock locked(lock_); - set_name_callback_ = std::move(callback); + DCHECK(!base::Contains(observers_, obs)); + observers_.push_back(obs); +} + +void ThreadIdNameManager::RemoveObserver(Observer* obs) { + AutoLock locked(lock_); + DCHECK(base::Contains(observers_, obs)); + base::Erase(observers_, obs); } void ThreadIdNameManager::SetName(const std::string& name) { @@ -74,9 +84,8 @@ auto id_to_handle_iter = thread_id_to_handle_.find(id); GetThreadNameTLS().Set(const_cast<char*>(leaked_str->c_str())); - if (set_name_callback_) { - set_name_callback_.Run(leaked_str->c_str()); - } + for (Observer* obs : observers_) + obs->OnThreadNameChanged(leaked_str->c_str()); // The main thread of a process will not be created as a Thread object which // means there is no PlatformThreadHandler registered.
diff --git a/base/threading/thread_id_name_manager.h b/base/threading/thread_id_name_manager.h index f17dc1a4..e413da5 100644 --- a/base/threading/thread_id_name_manager.h +++ b/base/threading/thread_id_name_manager.h
@@ -7,10 +7,12 @@ #include <map> #include <string> +#include <vector> #include "base/base_export.h" #include "base/callback.h" #include "base/macros.h" +#include "base/observer_list.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" @@ -25,14 +27,24 @@ static const char* GetDefaultInternedString(); + class BASE_EXPORT Observer { + public: + virtual ~Observer(); + + // Called on the thread whose name is changing, immediately after the name + // is set. |name| is a pointer to a C string that is guaranteed to remain + // valid for the duration of the process. + // + // NOTE: Will be called while ThreadIdNameManager's lock is held, so don't + // call back into it. + virtual void OnThreadNameChanged(const char* name) = 0; + }; + // Register the mapping between a thread |id| and |handle|. void RegisterThread(PlatformThreadHandle::Handle handle, PlatformThreadId id); - // The callback is called on the thread, immediately after the name is set. - // |name| is a pointer to a C string that is guaranteed to remain valid for - // the duration of the process. - using SetNameCallback = base::RepeatingCallback<void(const char* name)>; - void InstallSetNameCallback(SetNameCallback callback); + void AddObserver(Observer*); + void RemoveObserver(Observer*); // Set the name for the current thread. void SetName(const std::string& name); @@ -70,7 +82,9 @@ std::string* main_process_name_; PlatformThreadId main_process_id_; - SetNameCallback set_name_callback_; + // There's no point using a base::ObserverList behind a lock, so we just use + // an std::vector instead. + std::vector<Observer*> observers_; DISALLOW_COPY_AND_ASSIGN(ThreadIdNameManager); };
diff --git a/base/threading/thread_local_storage_perftest.cc b/base/threading/thread_local_storage_perftest.cc index 786a091..198775c 100644 --- a/base/threading/thread_local_storage_perftest.cc +++ b/base/threading/thread_local_storage_perftest.cc
@@ -15,9 +15,17 @@ #include "base/threading/simple_thread.h" #include "base/threading/thread_local_storage.h" #include "base/time/time.h" +#include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" +#if defined(OS_WIN) +#include <windows.h> +#include "base/win/windows_types.h" +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) +#include <pthread.h> +#endif + namespace base { namespace internal { @@ -134,9 +142,59 @@ auto read = [&]() { return reinterpret_cast<intptr_t>(tls.Get()); }; auto write = [&](intptr_t value) { tls.Set(reinterpret_cast<void*>(value)); }; - Benchmark("ThreadLocalStorage", read, write, 1000000, 1); - Benchmark("ThreadLocalStorage 4 threads", read, write, 1000000, 4); + Benchmark("ThreadLocalStorage", read, write, 10000000, 1); + Benchmark("ThreadLocalStorage 4 threads", read, write, 10000000, 4); } +#if defined(OS_WIN) + +void WINAPI destroy(void*) {} + +TEST_F(ThreadLocalStoragePerfTest, PlatformFls) { + DWORD key = FlsAlloc(destroy); + ASSERT_NE(PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES, key); + + auto read = [&]() { return reinterpret_cast<intptr_t>(FlsGetValue(key)); }; + auto write = [&](intptr_t value) { + FlsSetValue(key, reinterpret_cast<void*>(value)); + }; + + Benchmark("PlatformFls", read, write, 10000000, 1); + Benchmark("PlatformFls 4 threads", read, write, 10000000, 4); +} + +TEST_F(ThreadLocalStoragePerfTest, PlatformTls) { + DWORD key = TlsAlloc(); + ASSERT_NE(PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES, key); + + auto read = [&]() { return reinterpret_cast<intptr_t>(TlsGetValue(key)); }; + auto write = [&](intptr_t value) { + TlsSetValue(key, reinterpret_cast<void*>(value)); + }; + + Benchmark("PlatformTls", read, write, 10000000, 1); + Benchmark("PlatformTls 4 threads", read, write, 10000000, 4); +} + +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + +TEST_F(ThreadLocalStoragePerfTest, PlatformTls) { + pthread_key_t key; + ASSERT_FALSE(pthread_key_create(&key, [](void*) {})); + ASSERT_NE(PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES, key); + + auto read = [&]() { + return reinterpret_cast<intptr_t>(pthread_getspecific(key)); + }; + auto write = [&](intptr_t value) { + pthread_setspecific(key, reinterpret_cast<void*>(value)); + }; + + Benchmark("PlatformTls", read, write, 10000000, 1); + Benchmark("PlatformTls 4 threads", read, write, 10000000, 4); +} + +#endif + } // namespace internal } // namespace base \ No newline at end of file
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index 44ee37c..fe765a0 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -782,7 +782,7 @@ bool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const { AutoLock lock(observers_lock_); - return ContainsValue(enabled_state_observers_, listener); + return Contains(enabled_state_observers_, listener); } void TraceLog::AddAsyncEnabledStateObserver( @@ -800,7 +800,7 @@ bool TraceLog::HasAsyncEnabledStateObserver( AsyncEnabledStateObserver* listener) const { AutoLock lock(observers_lock_); - return ContainsKey(async_observers_, listener); + return Contains(async_observers_, listener); } TraceLogStatus TraceLog::GetStatus() const { @@ -1212,7 +1212,7 @@ std::vector<StringPiece> existing_names = base::SplitStringPiece( existing_name->second, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - if (!ContainsValue(existing_names, new_name)) { + if (!Contains(existing_names, new_name)) { if (!existing_names.empty()) existing_name->second.push_back(','); existing_name->second.append(new_name);
diff --git a/base/values.cc b/base/values.cc index 03acb86..7d042cd 100644 --- a/base/values.cc +++ b/base/values.cc
@@ -1706,7 +1706,7 @@ bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { DCHECK(in_value); - if (ContainsValue(list_, *in_value)) + if (Contains(list_, *in_value)) return false; list_.push_back(std::move(*in_value));
diff --git a/base/win/win_util_unittest.cc b/base/win/win_util_unittest.cc index 5999fb9..1178199e 100644 --- a/base/win/win_util_unittest.cc +++ b/base/win/win_util_unittest.cc
@@ -73,7 +73,7 @@ ASSERT_NE(static_cast<HMODULE>(NULL), new_dll.get()); ASSERT_TRUE(GetLoadedModulesSnapshot(::GetCurrentProcess(), &snapshot)); ASSERT_GT(snapshot.size(), original_snapshot_size); - ASSERT_TRUE(ContainsValue(snapshot, new_dll.get())); + ASSERT_TRUE(Contains(snapshot, new_dll.get())); } TEST(BaseWinUtilTest, TestUint32ToInvalidHandle) {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index f9b22ea..52913649 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8911371438377102624 \ No newline at end of file +8911315473209928720 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 4e41237b..0745611d 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8911375035762188400 \ No newline at end of file +8911318344250807168 \ No newline at end of file
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index 19b7422..850fbc4 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -320,14 +320,13 @@ auto backing = std::make_unique<HudSoftwareBacking>(); backing->layer_tree_frame_sink = layer_tree_frame_sink; backing->shared_bitmap_id = viz::SharedBitmap::GenerateId(); - base::MappedReadOnlyRegion mapped_region = + base::MappedReadOnlyRegion shm = viz::bitmap_allocation::AllocateSharedBitmap(pool_resource.size(), pool_resource.format()); - backing->shared_mapping = std::move(mapped_region.mapping); + backing->shared_mapping = std::move(shm.mapping); - layer_tree_frame_sink->DidAllocateSharedBitmap( - viz::bitmap_allocation::ToMojoHandle(std::move(mapped_region.region)), - backing->shared_bitmap_id); + layer_tree_frame_sink->DidAllocateSharedBitmap(std::move(shm.region), + backing->shared_bitmap_id); pool_resource.set_software_backing(std::move(backing)); }
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc index a51f6789..3f82daf 100644 --- a/cc/layers/texture_layer_impl.cc +++ b/cc/layers/texture_layer_impl.cc
@@ -110,8 +110,7 @@ LayerTreeFrameSink* sink = layer_tree_impl()->layer_tree_frame_sink(); for (const auto& pair : to_register_bitmaps_) { - sink->DidAllocateSharedBitmap(viz::bitmap_allocation::ToMojoHandle( - pair.second->shared_region().Duplicate()), + sink->DidAllocateSharedBitmap(pair.second->shared_region().Duplicate(), pair.first); } // All |to_register_bitmaps_| have been registered above, so we can move them
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.cc b/cc/mojo_embedder/async_layer_tree_frame_sink.cc index 4459afb..f34b638 100644 --- a/cc/mojo_embedder/async_layer_tree_frame_sink.cc +++ b/cc/mojo_embedder/async_layer_tree_frame_sink.cc
@@ -293,10 +293,10 @@ } void AsyncLayerTreeFrameSink::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, + base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) { DCHECK(compositor_frame_sink_ptr_); - compositor_frame_sink_ptr_->DidAllocateSharedBitmap(std::move(buffer), id); + compositor_frame_sink_ptr_->DidAllocateSharedBitmap(std::move(region), id); } void AsyncLayerTreeFrameSink::DidDeleteSharedBitmap(
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.h b/cc/mojo_embedder/async_layer_tree_frame_sink.h index 5ed49023..95d4c6d 100644 --- a/cc/mojo_embedder/async_layer_tree_frame_sink.h +++ b/cc/mojo_embedder/async_layer_tree_frame_sink.h
@@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "cc/mojo_embedder/mojo_embedder_export.h" @@ -123,7 +124,7 @@ bool hit_test_data_changed, bool show_hit_test_borders) override; void DidNotProduceFrame(const viz::BeginFrameAck& ack) override; - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) override; void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override; void ForceAllocateNewId() override;
diff --git a/cc/raster/bitmap_raster_buffer_provider.cc b/cc/raster/bitmap_raster_buffer_provider.cc index 754ff69..db62527 100644 --- a/cc/raster/bitmap_raster_buffer_provider.cc +++ b/cc/raster/bitmap_raster_buffer_provider.cc
@@ -108,12 +108,11 @@ auto backing = std::make_unique<BitmapSoftwareBacking>(); backing->frame_sink = frame_sink_; backing->shared_bitmap_id = viz::SharedBitmap::GenerateId(); - base::MappedReadOnlyRegion mapped_region = + base::MappedReadOnlyRegion shm = viz::bitmap_allocation::AllocateSharedBitmap(size, viz::RGBA_8888); - backing->mapping = std::move(mapped_region.mapping); - frame_sink_->DidAllocateSharedBitmap( - viz::bitmap_allocation::ToMojoHandle(std::move(mapped_region.region)), - backing->shared_bitmap_id); + backing->mapping = std::move(shm.mapping); + frame_sink_->DidAllocateSharedBitmap(std::move(shm.region), + backing->shared_bitmap_id); resource.set_software_backing(std::move(backing)); }
diff --git a/cc/test/fake_layer_tree_frame_sink.cc b/cc/test/fake_layer_tree_frame_sink.cc index 0d2a0b50..740b56e 100644 --- a/cc/test/fake_layer_tree_frame_sink.cc +++ b/cc/test/fake_layer_tree_frame_sink.cc
@@ -85,7 +85,7 @@ } void FakeLayerTreeFrameSink::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, + base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) { DCHECK(!base::Contains(shared_bitmaps_, id)); shared_bitmaps_.push_back(id);
diff --git a/cc/test/fake_layer_tree_frame_sink.h b/cc/test/fake_layer_tree_frame_sink.h index 50ca127..5eb1129 100644 --- a/cc/test/fake_layer_tree_frame_sink.h +++ b/cc/test/fake_layer_tree_frame_sink.h
@@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "cc/trees/layer_tree_frame_sink.h" @@ -104,7 +105,7 @@ bool hit_test_data_changed, bool show_hit_test_borders) override; void DidNotProduceFrame(const viz::BeginFrameAck& ack) override; - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) override; void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override;
diff --git a/cc/test/test_layer_tree_frame_sink.cc b/cc/test/test_layer_tree_frame_sink.cc index e6b51c5b..da1736f 100644 --- a/cc/test/test_layer_tree_frame_sink.cc +++ b/cc/test/test_layer_tree_frame_sink.cc
@@ -204,10 +204,10 @@ } void TestLayerTreeFrameSink::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, + base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) { - bool ok = shared_bitmap_manager_->ChildAllocatedSharedBitmap( - viz::bitmap_allocation::FromMojoHandle(std::move(buffer)).Map(), id); + bool ok = + shared_bitmap_manager_->ChildAllocatedSharedBitmap(region.Map(), id); DCHECK(ok); owned_bitmaps_.insert(id); }
diff --git a/cc/test/test_layer_tree_frame_sink.h b/cc/test/test_layer_tree_frame_sink.h index 72a89e7..fe43725 100644 --- a/cc/test/test_layer_tree_frame_sink.h +++ b/cc/test/test_layer_tree_frame_sink.h
@@ -94,7 +94,7 @@ bool hit_test_data_changed, bool show_hit_test_borders) override; void DidNotProduceFrame(const viz::BeginFrameAck& ack) override; - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion buffer, const viz::SharedBitmapId& id) override; void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override;
diff --git a/cc/trees/layer_tree_frame_sink.h b/cc/trees/layer_tree_frame_sink.h index 76634a7..7a0444c6 100644 --- a/cc/trees/layer_tree_frame_sink.h +++ b/cc/trees/layer_tree_frame_sink.h
@@ -8,6 +8,7 @@ #include <deque> #include <memory> +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" @@ -127,7 +128,7 @@ virtual void DidNotProduceFrame(const viz::BeginFrameAck& ack) = 0; // viz::SharedBitmapReporter implementation. - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) override = 0; void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override = 0;
diff --git a/cc/trees/layer_tree_frame_sink_unittest.cc b/cc/trees/layer_tree_frame_sink_unittest.cc index 58334b8..5eabeb0 100644 --- a/cc/trees/layer_tree_frame_sink_unittest.cc +++ b/cc/trees/layer_tree_frame_sink_unittest.cc
@@ -4,6 +4,7 @@ #include "cc/trees/layer_tree_frame_sink.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/single_thread_task_runner.h" #include "base/test/test_simple_task_runner.h" #include "cc/test/fake_layer_tree_frame_sink_client.h" @@ -34,7 +35,7 @@ client_->DidReceiveCompositorFrameAck(); } void DidNotProduceFrame(const viz::BeginFrameAck& ack) override {} - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) override {} void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override {} };
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index b372ed9..302f2e6 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -5361,7 +5361,7 @@ GLenum texture_target = GL_TEXTURE_2D; // For software compositing, shared memory will be allocated and the // UIResource will be copied into it. - base::MappedReadOnlyRegion mapped_region; + base::MappedReadOnlyRegion shm; viz::SharedBitmapId shared_bitmap_id; bool overlay_candidate = false; @@ -5379,8 +5379,7 @@ BufferFormat(format), caps); } } else { - mapped_region = - viz::bitmap_allocation::AllocateSharedBitmap(upload_size, format); + shm = viz::bitmap_allocation::AllocateSharedBitmap(upload_size, format); shared_bitmap_id = viz::SharedBitmap::GenerateId(); } @@ -5405,7 +5404,7 @@ SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size)); sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect( - dst_info, mapped_region.mapping.memory(), dst_info.minRowBytes()); + dst_info, shm.mapping.memory(), dst_info.minRowBytes()); surface->getCanvas()->writePixels( src_info, const_cast<uint8_t*>(bitmap.GetPixels()), src_info.minRowBytes(), 0, 0); @@ -5441,7 +5440,7 @@ SkImageInfo dst_info = SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size)); scaled_surface = SkSurface::MakeRasterDirect( - dst_info, mapped_region.mapping.memory(), dst_info.minRowBytes()); + dst_info, shm.mapping.memory(), dst_info.minRowBytes()); } SkCanvas* scaled_canvas = scaled_surface->getCanvas(); scaled_canvas->scale(canvas_scale_x, canvas_scale_y); @@ -5484,9 +5483,8 @@ overlay_candidate); transferable.format = format; } else { - layer_tree_frame_sink_->DidAllocateSharedBitmap( - viz::bitmap_allocation::ToMojoHandle(std::move(mapped_region.region)), - shared_bitmap_id); + layer_tree_frame_sink_->DidAllocateSharedBitmap(std::move(shm.region), + shared_bitmap_id); transferable = viz::TransferableResource::MakeSoftware(shared_bitmap_id, upload_size, format); } @@ -5504,7 +5502,7 @@ data.opaque = bitmap.GetOpaque(); data.format = format; data.shared_bitmap_id = shared_bitmap_id; - data.shared_mapping = std::move(mapped_region.mapping); + data.shared_mapping = std::move(shm.mapping); data.mailbox = mailbox; data.resource_id_for_export = id; ui_resource_map_[uid] = std::move(data);
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMetricsRecorder.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMetricsRecorder.java index f725ec1e..6edd12d 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMetricsRecorder.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMetricsRecorder.java
@@ -22,6 +22,8 @@ "KeyboardAccessory.AccessorySheetSuggestionsSelected"; private static final String UMA_KEYBOARD_ACCESSORY_SHEET_TYPE_SUFFIX_PASSWORDS = "Passwords"; private static final String UMA_KEYBOARD_ACCESSORY_SHEET_TYPE_SUFFIX_ADDRESSES = "Addresses"; + private static final String UMA_KEYBOARD_ACCESSORY_SHEET_TYPE_SUFFIX_TOUCH_TO_FILL = + "TouchToFill"; /** * The Recorder itself should be stateless and have no need for an instance. @@ -42,6 +44,8 @@ return baseHistogram + "." + UMA_KEYBOARD_ACCESSORY_SHEET_TYPE_SUFFIX_PASSWORDS; case AccessoryTabType.ADDRESSES: return baseHistogram + "." + UMA_KEYBOARD_ACCESSORY_SHEET_TYPE_SUFFIX_ADDRESSES; + case AccessoryTabType.TOUCH_TO_FILL: + return baseHistogram + "." + UMA_KEYBOARD_ACCESSORY_SHEET_TYPE_SUFFIX_TOUCH_TO_FILL; } assert false : "Undefined histogram for tab type " + tabType + " !"; return ""; @@ -106,6 +110,10 @@ // TODO(crbug.com/965494): Consider splitting and/or separate recording. suggestionRecordingType = AccessorySuggestionType.ADDRESS_INFO; break; + case AccessoryTabType.TOUCH_TO_FILL: + suggestionRecordingType = AccessorySuggestionType.TOUCH_TO_FILL_INFO; + break; + case AccessoryTabType.ALL: throw new InvalidParameterException("Unable to handle tabType: " + tabType); }
diff --git a/chrome/android/java/res/layout/edit_url_suggestion_layout.xml b/chrome/android/java/res/layout/edit_url_suggestion_layout.xml index bb5ea00..f23b9f4 100644 --- a/chrome/android/java/res/layout/edit_url_suggestion_layout.xml +++ b/chrome/android/java/res/layout/edit_url_suggestion_layout.xml
@@ -41,14 +41,31 @@ </LinearLayout> + <Space + android:id="@+id/edit_url_space" + android:layout_width="@dimen/omnibox_suggestion_start_offset_without_icon" + android:layout_height="match_parent" + android:layout_alignParentStart="true" /> + + <ImageView + android:id="@+id/edit_url_favicon" + android:layout_width="@dimen/omnibox_suggestion_favicon_size" + android:layout_height="@dimen/omnibox_suggestion_favicon_size" + android:layout_centerVertical="true" + android:layout_marginStart="@dimen/omnibox_suggestion_24dp_icon_margin_start" + android:layout_marginEnd="@dimen/omnibox_suggestion_24dp_icon_margin_end" + android:layout_toEndOf="@id/edit_url_space" + android:importantForAccessibility="no" + android:visibility="gone" + android:scaleType="centerInside" /> + <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentStart="true" android:layout_centerVertical="true" android:layout_toStartOf="@id/edit_url_suggestion_icons" - android:orientation="vertical" - android:layout_marginStart="@dimen/omnibox_suggestion_start_offset_without_icon"> + android:layout_toEndOf="@id/edit_url_favicon" + android:orientation="vertical"> <TextView android:id="@+id/title_text_view"
diff --git a/chrome/android/java/res/layout/omnibox_answer_suggestion.xml b/chrome/android/java/res/layout/omnibox_answer_suggestion.xml index 72d5bb7..cbd6c39 100644 --- a/chrome/android/java/res/layout/omnibox_answer_suggestion.xml +++ b/chrome/android/java/res/layout/omnibox_answer_suggestion.xml
@@ -27,8 +27,8 @@ android:id="@+id/omnibox_answer_icon" android:layout_centerVertical="true" android:layout_height="36dp" - android:layout_marginEnd="10dp" - android:layout_marginStart="@dimen/omnibox_suggestion_icon_margin_start" + android:layout_marginEnd="@dimen/omnibox_suggestion_36dp_icon_margin_end" + android:layout_marginStart="@dimen/omnibox_suggestion_36dp_icon_margin_start" android:layout_width="36dp" android:scaleType="fitCenter" />
diff --git a/chrome/android/java/res/layout/omnibox_entity_suggestion.xml b/chrome/android/java/res/layout/omnibox_entity_suggestion.xml index 2f76cf0..98c817f 100644 --- a/chrome/android/java/res/layout/omnibox_entity_suggestion.xml +++ b/chrome/android/java/res/layout/omnibox_entity_suggestion.xml
@@ -25,9 +25,9 @@ android:layout_width="@dimen/omnibox_suggestion_entity_icon_size" android:layout_height="@dimen/omnibox_suggestion_entity_icon_size" android:layout_centerVertical="true" - android:layout_marginEnd="8dp" - android:layout_marginStart="@dimen/omnibox_suggestion_icon_margin_start" - android:contentDescription="@null" /> + android:layout_marginEnd="@dimen/omnibox_suggestion_36dp_icon_margin_end" + android:layout_marginStart="@dimen/omnibox_suggestion_36dp_icon_margin_start" + android:contentDescription="@null"/> <TextView android:id="@+id/omnibox_entity_subject_text"
diff --git a/chrome/android/java/res/values-sw600dp/dimens.xml b/chrome/android/java/res/values-sw600dp/dimens.xml index dbdb8a9..aa9a859 100644 --- a/chrome/android/java/res/values-sw600dp/dimens.xml +++ b/chrome/android/java/res/values-sw600dp/dimens.xml
@@ -34,7 +34,10 @@ <dimen name="omnibox_suggestion_start_offset_without_icon">@dimen/location_bar_icon_width</dimen> <dimen name="omnibox_suggestion_start_offset_with_icon">@dimen/omnibox_suggestion_start_offset_without_icon</dimen> - <dimen name="omnibox_suggestion_icon_margin_start">0dp</dimen> + <dimen name="omnibox_suggestion_36dp_icon_margin_start">0dp</dimen> + <dimen name="omnibox_suggestion_36dp_icon_margin_end">8dp</dimen> + <dimen name="omnibox_suggestion_24dp_icon_margin_start">8dp</dimen> + <dimen name="omnibox_suggestion_24dp_icon_margin_end">8dp</dimen> <!-- NTP dimensions --> <dimen name="ntp_search_box_transition_length">60dp</dimen>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index 6892ee4..0ef4e15 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -301,7 +301,10 @@ <dimen name="omnibox_suggestion_start_offset_without_icon">18dp</dimen> <dimen name="omnibox_suggestion_start_offset_with_icon">56dp</dimen> - <dimen name="omnibox_suggestion_icon_margin_start">10dp</dimen> + <dimen name="omnibox_suggestion_36dp_icon_margin_start">10dp</dimen> + <dimen name="omnibox_suggestion_36dp_icon_margin_end">10dp</dimen> + <dimen name="omnibox_suggestion_24dp_icon_margin_start">16dp</dimen> + <dimen name="omnibox_suggestion_24dp_icon_margin_end">16dp</dimen> <dimen name="omnibox_suggestion_favicon_size">24dp</dimen> <dimen name="omnibox_suggestion_entity_icon_size">36dp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java index f3c289e..a3d8820 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -159,7 +159,7 @@ mBasicSuggestionProcessor = new BasicSuggestionProcessor(mContext, this, textProvider); mAnswerSuggestionProcessor = new AnswerSuggestionProcessor(mContext, this, textProvider); mEditUrlProcessor = new EditUrlSuggestionProcessor( - delegate, (suggestion) -> onSelection(suggestion, 0)); + mContext, this, delegate, (suggestion) -> onSelection(suggestion, 0)); mEntitySuggestionProcessor = new EntitySuggestionProcessor(mContext, this); } @@ -430,6 +430,7 @@ void setAutocompleteProfile(Profile profile) { mAutocomplete.setProfile(profile); mBasicSuggestionProcessor.setProfile(profile); + mEditUrlProcessor.setProfile(profile); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java index 7b80b12..ded877e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.omnibox.suggestions.editurl; import android.content.Context; +import android.graphics.Bitmap; import android.support.annotation.IntDef; import android.text.TextUtils; import android.view.LayoutInflater; @@ -16,12 +17,16 @@ import org.chromium.base.metrics.CachedMetrics.EnumeratedHistogramSample; import org.chromium.chrome.R; import org.chromium.chrome.browser.ActivityTabProvider; +import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.favicon.LargeIconBridge; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.UrlBar; import org.chromium.chrome.browser.omnibox.UrlBar.OmniboxAction; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionProcessor; +import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionHost; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.share.ShareMenuActionHandler; import org.chromium.chrome.browser.tab.Tab; import org.chromium.ui.base.Clipboard; @@ -115,14 +120,32 @@ /** Whether this processor should ignore all subsequent suggestion. */ private boolean mIgnoreSuggestions; + /** Whether suggestion site favicons are enabled. */ + private boolean mEnableSuggestionFavicons; + + /** Edge size (in pixels) of the favicon. Used to request best matching favicon from cache. */ + private final int mDesiredFaviconWidthPx; + + /** Supplies Profile information. */ + private Profile mCurrentUserProfile; + + /** Supplies site favicons. */ + private LargeIconBridge mLargeIconBridge; + + /** Supplies additional control over suggestion model. */ + private final SuggestionHost mSuggestionHost; + /** * @param locationBarDelegate A means of modifying the location bar. * @param selectionHandler A mechanism for handling selection of the edit URL suggestion item. */ - public EditUrlSuggestionProcessor( + public EditUrlSuggestionProcessor(Context context, SuggestionHost suggestionHost, LocationBarDelegate locationBarDelegate, SuggestionSelectionHandler selectionHandler) { mLocationBarDelegate = locationBarDelegate; mSelectionHandler = selectionHandler; + mDesiredFaviconWidthPx = context.getResources().getDimensionPixelSize( + R.dimen.omnibox_suggestion_favicon_size); + mSuggestionHost = suggestionHost; } /** @@ -185,13 +208,42 @@ model.set(EditUrlSuggestionProperties.TEXT_CLICK_LISTENER, this); model.set(EditUrlSuggestionProperties.BUTTON_CLICK_LISTENER, this); + // Lazily create LargeIconBridge in case Profile is reported ahead on Native initialized. + if (mEnableSuggestionFavicons && mLargeIconBridge == null && mCurrentUserProfile != null) { + mLargeIconBridge = new LargeIconBridge(mCurrentUserProfile); + } + + if (mLargeIconBridge != null) { + mLargeIconBridge.getLargeIconForUrl(mLastProcessedSuggestion.getUrl(), + mDesiredFaviconWidthPx, + (Bitmap icon, int fallbackColor, boolean isFallbackColorDefault, + int iconType) -> { + if (!mSuggestionHost.isActiveModel(model)) return; + model.set(EditUrlSuggestionProperties.SITE_FAVICON, icon); + mSuggestionHost.notifyPropertyModelsChanged(); + }); + } + if (mOriginalTitle == null) mOriginalTitle = mTabProvider.get().getTitle(); model.set(EditUrlSuggestionProperties.TITLE_TEXT, mOriginalTitle); model.set(EditUrlSuggestionProperties.URL_TEXT, mLastProcessedSuggestion.getUrl()); } @Override - public void onNativeInitialized() {} + public void onNativeInitialized() { + mEnableSuggestionFavicons = + ChromeFeatureList.isEnabled(ChromeFeatureList.OMNIBOX_SHOW_SUGGESTION_FAVICONS); + } + + /** + * Updates the profile used for extracting website favicons. + * @param profile The profile to be used. + */ + public void setProfile(Profile profile) { + if (mCurrentUserProfile == profile) return; + mCurrentUserProfile = profile; + mLargeIconBridge = null; + } /** * @param provider A means of accessing the activity's tab.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProperties.java index b4cfc6b..68cbd20 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProperties.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProperties.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.omnibox.suggestions.editurl; +import android.graphics.Bitmap; import android.view.View; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; @@ -29,8 +30,11 @@ public static final WritableObjectPropertyKey<View.OnClickListener> TEXT_CLICK_LISTENER = new WritableObjectPropertyKey<>(); - private static final PropertyKey[] ALL_UNIQUE_KEYS = - new PropertyKey[] {TITLE_TEXT, URL_TEXT, BUTTON_CLICK_LISTENER, TEXT_CLICK_LISTENER}; + public static final WritableObjectPropertyKey<Bitmap> SITE_FAVICON = + new WritableObjectPropertyKey<>(); + + private static final PropertyKey[] ALL_UNIQUE_KEYS = new PropertyKey[] { + TITLE_TEXT, URL_TEXT, BUTTON_CLICK_LISTENER, TEXT_CLICK_LISTENER, SITE_FAVICON}; public static final PropertyKey[] ALL_KEYS = PropertyModel.concatKeys(ALL_UNIQUE_KEYS, SuggestionCommonProperties.ALL_KEYS);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java index 04faee3..77a1830 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java
@@ -4,10 +4,14 @@ package org.chromium.chrome.browser.omnibox.suggestions.editurl; +import android.graphics.Bitmap; +import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.TextView; import org.chromium.chrome.R; +import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; @@ -32,7 +36,27 @@ model.get(EditUrlSuggestionProperties.BUTTON_CLICK_LISTENER)); } else if (EditUrlSuggestionProperties.TEXT_CLICK_LISTENER == propertyKey) { view.setOnClickListener(model.get(EditUrlSuggestionProperties.TEXT_CLICK_LISTENER)); + } else if (SuggestionCommonProperties.SHOW_SUGGESTION_ICONS == propertyKey) { + boolean showIcons = model.get(SuggestionCommonProperties.SHOW_SUGGESTION_ICONS); + view.findViewById(R.id.edit_url_space) + .setVisibility(showIcons ? View.GONE : View.VISIBLE); + view.findViewById(R.id.edit_url_favicon) + .setVisibility(showIcons ? View.VISIBLE : View.GONE); + updateSiteFavicon(view.findViewById(R.id.edit_url_favicon), model); + } else if (EditUrlSuggestionProperties.SITE_FAVICON == propertyKey) { + updateSiteFavicon(view.findViewById(R.id.edit_url_favicon), model); } // TODO(mdjones): Support SuggestionCommonProperties.* } + + private static void updateSiteFavicon(ImageView view, PropertyModel model) { + if (!model.get(SuggestionCommonProperties.SHOW_SUGGESTION_ICONS)) return; + + Bitmap bitmap = model.get(EditUrlSuggestionProperties.SITE_FAVICON); + if (bitmap != null) { + view.setImageBitmap(bitmap); + } else { + view.setImageResource(R.drawable.ic_globe_24dp); + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java index 860b12a4..425c2946b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java
@@ -252,10 +252,7 @@ int destinationGroupId = destinationTab.getRootId(); List<Tab> tabsToMerge = getRelatedTabList(sourceTabId); - int sourceTabIndexInTabModel = - TabModelUtils.getTabIndexById(getTabModel(), sourceTab.getId()); int destinationIndexInTabModel = getTabModelDestinationIndex(destinationTab); - boolean isMovingBackward = sourceTabIndexInTabModel < destinationIndexInTabModel; if (!needToUpdateTabModel(tabsToMerge, destinationIndexInTabModel)) { for (int i = 0; i < tabsToMerge.size(); i++) { @@ -271,13 +268,31 @@ tabsToMerge.get(tabsToMerge.size() - 1), group.getLastShownTabId()); } } else { - for (int i = 0; i < tabsToMerge.size(); i++) { - Tab tab = tabsToMerge.get(i); - tab.setRootId(destinationGroupId); - getTabModel().moveTab(tab.getId(), - isMovingBackward ? destinationIndexInTabModel - : destinationIndexInTabModel++); - } + mergeListOfTabsToGroup(tabsToMerge, destinationTab); + } + } + + /** + * This method appends a list of {@link Tab}s to the destination group that contains the + * {@code} destinationTab. The {@link TabModel} ordering of the tabs in the given list is not + * preserved. After calling this method, the {@link TabModel} ordering of these tabs would + * become the ordering of {@code tabs}. + * + * @param tabs List of {@link Tab}s to be appended. + * @param destinationTab The destination {@link Tab} to be append to. + */ + public void mergeListOfTabsToGroup(List<Tab> tabs, Tab destinationTab) { + int destinationGroupId = destinationTab.getRootId(); + int destinationIndexInTabModel = getTabModelDestinationIndex(destinationTab); + + for (int i = 0; i < tabs.size(); i++) { + Tab tab = tabs.get(i); + int index = TabModelUtils.getTabIndexById(getTabModel(), tab.getId()); + boolean isMergingBackward = index < destinationIndexInTabModel; + + tab.setRootId(destinationGroupId); + getTabModel().moveTab(tab.getId(), + isMergingBackward ? destinationIndexInTabModel : destinationIndexInTabModel++); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionTest.java index 92e14b0..b71fd9e 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionTest.java
@@ -7,6 +7,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.Context; +import android.content.res.Resources; import android.support.test.filters.SmallTest; import android.view.View; @@ -39,6 +41,12 @@ private PropertyModel mModel; @Mock + Context mContext; + + @Mock + Resources mResources; + + @Mock private ActivityTabProvider mTabProvider; @Mock @@ -66,6 +74,7 @@ public void setUp() { MockitoAnnotations.initMocks(this); + when(mContext.getResources()).thenReturn(mResources); when(mTab.getUrl()).thenReturn(TEST_URL); when(mTab.getTitle()).thenReturn(TEST_TITLE); when(mTab.isNativePage()).thenReturn(false); @@ -81,7 +90,8 @@ mModel = new PropertyModel.Builder(EditUrlSuggestionProperties.ALL_KEYS).build(); - mProcessor = new EditUrlSuggestionProcessor(mLocationBarDelegate, mSelectionHandler); + mProcessor = new EditUrlSuggestionProcessor( + mContext, null, mLocationBarDelegate, mSelectionHandler); mProcessor.setActivityTabProvider(mTabProvider); when(mEditButton.getId()).thenReturn(R.id.url_edit_icon);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilterUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilterUnitTest.java index 631f40e..14e0819 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilterUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilterUnitTest.java
@@ -64,6 +64,8 @@ private static final int POSITION5 = 4; private static final int POSITION6 = 5; + private static final int NEW_TAB_ID = 159; + @Mock TabModel mTabModel; @@ -174,6 +176,13 @@ doReturn(0).when(mTabModel).index(); } + private Tab addTabToTabModel() { + Tab tab = prepareTab(NEW_TAB_ID, NEW_TAB_ID); + mTabModel.addTab(tab, -1, TabLaunchType.FROM_CHROME_UI); + mTabModelObserverCaptor.getValue().didAddTab(tab, TabLaunchType.FROM_CHROME_UI); + return tab; + } + @Before public void setUp() { RecordUserAction.setDisabledForTests(true); @@ -315,6 +324,53 @@ } @Test + public void mergeListOfTabsToGroup_All_Backward() { + List<Tab> expectedTabModel = + new ArrayList<>(Arrays.asList(mTab2, mTab3, mTab5, mTab6, mTab1, mTab4)); + List<Tab> tabsToMerge = new ArrayList<>(Arrays.asList(mTab1, mTab4)); + + mTabGroupModelFilter.mergeListOfTabsToGroup(tabsToMerge, mTab5); + + verify(mTabModel).moveTab(mTab1.getId(), POSITION6 + 1); + verify(mTabModel).moveTab(mTab4.getId(), POSITION6 + 1); + verify(mTabGroupModelFilterObserver).didMergeTabToGroup(mTab1, mTab5.getId()); + verify(mTabGroupModelFilterObserver).didMergeTabToGroup(mTab4, mTab5.getId()); + assertArrayEquals(mTabs.toArray(), expectedTabModel.toArray()); + } + + @Test + public void mergeListOfTabsToGroup_All_Forward() { + Tab newTab = addTabToTabModel(); + List<Tab> tabsToMerge = new ArrayList<>(Arrays.asList(mTab4, newTab)); + List<Tab> expectedTabModel = + new ArrayList<>(Arrays.asList(mTab1, mTab4, newTab, mTab2, mTab3, mTab5, mTab6)); + + mTabGroupModelFilter.mergeListOfTabsToGroup(tabsToMerge, mTab1); + + verify(mTabModel).moveTab(mTab4.getId(), POSITION1 + 1); + verify(mTabModel).moveTab(newTab.getId(), POSITION1 + 2); + verify(mTabGroupModelFilterObserver).didMergeTabToGroup(mTab4, mTab1.getId()); + verify(mTabGroupModelFilterObserver).didMergeTabToGroup(newTab, mTab1.getId()); + assertArrayEquals(mTabs.toArray(), expectedTabModel.toArray()); + } + + @Test + public void mergeListOfTabsToGroup_Any_direction() { + Tab newTab = addTabToTabModel(); + List<Tab> tabsToMerge = new ArrayList<>(Arrays.asList(mTab1, newTab)); + List<Tab> expectedTabModel = + new ArrayList<>(Arrays.asList(mTab2, mTab3, mTab4, mTab1, newTab, mTab5, mTab6)); + + mTabGroupModelFilter.mergeListOfTabsToGroup(tabsToMerge, mTab4); + + verify(mTabModel).moveTab(mTab1.getId(), POSITION4 + 1); + verify(mTabModel).moveTab(newTab.getId(), POSITION4 + 1); + verify(mTabGroupModelFilterObserver).didMergeTabToGroup(mTab1, mTab4.getId()); + verify(mTabGroupModelFilterObserver).didMergeTabToGroup(newTab, mTab4.getId()); + assertArrayEquals(mTabs.toArray(), expectedTabModel.toArray()); + } + + @Test public void moveGroup_Backward() { List<Tab> expectedTabModel = new ArrayList<>(Arrays.asList(mTab1, mTab4, mTab2, mTab3, mTab5, mTab6));
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index e369476..8edaa40 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-77.0.3816.0_rc-r1-merged.afdo.bz2 \ No newline at end of file +chromeos-chrome-amd64-77.0.3817.0_rc-r1-merged.afdo.bz2 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 1ef8995..bea5fd6 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1510,6 +1510,8 @@ "sharing/sharing_service.h", "sharing/sharing_service_factory.cc", "sharing/sharing_service_factory.h", + "sharing/sharing_sync_preference.cc", + "sharing/sharing_sync_preference.h", "shell_integration.cc", "shell_integration.h", "shell_integration_android.cc",
diff --git a/chrome/browser/android/oom_intervention/near_oom_monitor_unittest.cc b/chrome/browser/android/oom_intervention/near_oom_monitor_unittest.cc index bf31354..73f7fdf 100644 --- a/chrome/browser/android/oom_intervention/near_oom_monitor_unittest.cc +++ b/chrome/browser/android/oom_intervention/near_oom_monitor_unittest.cc
@@ -5,8 +5,8 @@ #include "chrome/browser/android/oom_intervention/near_oom_monitor.h" #include "base/bind.h" -#include "base/message_loop/message_loop.h" #include "base/sequenced_task_runner.h" +#include "base/test/scoped_task_environment.h" #include "base/test/test_mock_time_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" @@ -82,7 +82,7 @@ protected: scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<MockNearOomMonitor> monitor_; };
diff --git a/chrome/browser/chromeos/accessibility/magnifier_type.h b/chrome/browser/chromeos/accessibility/magnifier_type.h index 24a79da02..4597fe81 100644 --- a/chrome/browser/chromeos/accessibility/magnifier_type.h +++ b/chrome/browser/chromeos/accessibility/magnifier_type.h
@@ -11,6 +11,7 @@ enum MagnifierType { MAGNIFIER_DISABLED = 0, // Used by enterprise policy. MAGNIFIER_FULL = 1, + MAGNIFIER_DOCKED = 2, // Never shipped. Deprioritized in 2013. http://crbug.com/170850 // MAGNIFIER_PARTIAL = 2, // TODO(afakhy): Consider adding Docked Magnifier type (shipped in M66) for
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen_browsertest.cc b/chrome/browser/chromeos/login/enrollment/enrollment_screen_browsertest.cc index cb27e26b..f042bc4 100644 --- a/chrome/browser/chromeos/login/enrollment/enrollment_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen_browsertest.cc
@@ -25,9 +25,9 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using testing::_; using testing::InvokeWithoutArgs; using testing::Mock; -using testing::_; namespace chromeos { @@ -61,7 +61,6 @@ test::EnrollmentUIMixin enrollment_ui_{&mixin_host_}; private: - DISALLOW_COPY_AND_ASSIGN(EnrollmentScreenTest); }; @@ -109,25 +108,16 @@ EnrollmentScreenView* view = enrollment_screen()->GetView(); ASSERT_TRUE(view); - test::JSChecker checker( - LoginDisplayHost::default_host()->GetOobeWebContents()); - // Run through the flow view->Show(); OobeScreenWaiter(EnrollmentScreenView::kScreenId).Wait(); - checker.ExpectTrue( - "window.getComputedStyle(document.getElementById('oauth-enroll-step-" - "signin')).display !== 'none'"); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSignin); view->ShowEnrollmentSpinnerScreen(); - checker.ExpectTrue( - "window.getComputedStyle(document.getElementById('oauth-enroll-step-" - "working')).display !== 'none'"); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepWorking); view->ShowAttestationBasedEnrollmentSuccessScreen("fake domain"); - checker.ExpectTrue( - "window.getComputedStyle(document.getElementById('oauth-enroll-step-" - "success')).display !== 'none'"); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); } class ForcedAttestationAuthEnrollmentScreenTest : public EnrollmentScreenTest {
diff --git a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc index b7baad8e..743f8626 100644 --- a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc +++ b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
@@ -7,6 +7,7 @@ #include "base/json/json_reader.h" #include "base/json/string_escape.h" #include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h" @@ -38,6 +39,7 @@ namespace { +constexpr char kEnrollmentUI[] = "enterprise-enrollment"; constexpr char kAdDialog[] = "oauth-enroll-ad-join-ui"; constexpr char kAdErrorCard[] = "oauth-enroll-active-directory-join-error-card"; @@ -138,9 +140,7 @@ public: explicit EnterpriseEnrollmentTestBase(bool should_initialize_webui) : LoginManagerTest(true /*should_launch_browser*/, - should_initialize_webui) { - } - + should_initialize_webui) {} // Submits regular enrollment credentials. void SubmitEnrollmentCredentials() { @@ -149,7 +149,6 @@ ExecutePendingJavaScript(); } - // Completes the enrollment process. void CompleteEnrollment() { enrollment_screen()->OnDeviceEnrolled(); @@ -211,7 +210,7 @@ } std::string AdElement(const std::string& inner_id) { - return test::GetOobeElementPath({kAdDialog, inner_id}); + return test::GetOobeElementPath({kEnrollmentUI, kAdDialog, inner_id}); } void ExpectElementValid(const std::string& inner_id, bool is_valid) { @@ -222,28 +221,33 @@ EXPECT_TRUE( enrollment_ui_.IsStepDisplayed(test::ui::kEnrollmentStepADJoin)); - std::initializer_list<base::StringPiece> ad_credentials{kAdDialog, - kAdCredentialsStep}; + std::initializer_list<base::StringPiece> ad_credentials{ + kEnrollmentUI, kAdDialog, kAdCredentialsStep}; test::OobeJS().ExpectVisiblePath(ad_credentials); test::OobeJS().ExpectNE( test::GetOobeElementPath(ad_credentials) + ".clientWidth", 0); test::OobeJS().ExpectNE( test::GetOobeElementPath(ad_credentials) + ".clientHeight", 0); - test::OobeJS().ExpectHiddenPath({kAdDialog, kAdUnlockConfigurationStep}); + test::OobeJS().ExpectHiddenPath( + {kEnrollmentUI, kAdDialog, kAdUnlockConfigurationStep}); } void CheckConfigurationSelectionVisible(bool visible) { if (visible) - test::OobeJS().ExpectVisiblePath({kAdDialog, kAdJoinConfigurationForm}); + test::OobeJS().ExpectVisiblePath( + {kEnrollmentUI, kAdDialog, kAdJoinConfigurationForm}); else - test::OobeJS().ExpectHiddenPath({kAdDialog, kAdJoinConfigurationForm}); + test::OobeJS().ExpectHiddenPath( + {kEnrollmentUI, kAdDialog, kAdJoinConfigurationForm}); } void CheckActiveDirectoryUnlockConfigurationShown() { EXPECT_TRUE( enrollment_ui_.IsStepDisplayed(test::ui::kEnrollmentStepADJoin)); - test::OobeJS().ExpectHiddenPath({kAdDialog, kAdCredentialsStep}); - test::OobeJS().ExpectVisiblePath({kAdDialog, kAdUnlockConfigurationStep}); + test::OobeJS().ExpectHiddenPath( + {kEnrollmentUI, kAdDialog, kAdCredentialsStep}); + test::OobeJS().ExpectVisiblePath( + {kEnrollmentUI, kAdDialog, kAdUnlockConfigurationStep}); } void CheckAttributeValue(const base::Value* config_value, @@ -295,8 +299,9 @@ for (size_t i = 0; i < options->GetList().size(); ++i) { const base::Value& option = options->GetList()[i]; // Select configuration value. - test::OobeJS().SelectElementInPath(std::to_string(i), - {kAdDialog, kAdConfigurationSelect}); + test::OobeJS().SelectElementInPath( + base::NumberToString(i), + {kEnrollmentUI, kAdDialog, kAdConfigurationSelect}); CheckAttributeValue( option.FindKeyOfType("name", base::Value::Type::STRING), "", @@ -331,23 +336,28 @@ const std::string& password) { CheckActiveDirectoryCredentialsShown(); - test::OobeJS().TypeIntoPath(machine_name, {kAdDialog, kAdMachineNameInput}); - test::OobeJS().TypeIntoPath(username, {kAdDialog, kAdUsernameInput}); - test::OobeJS().TypeIntoPath(password, {kAdDialog, kAdPasswordInput}); - - test::OobeJS().TapOnPath({kAdDialog, kAdMoreOptionsButton}); - test::OobeJS().TypeIntoPath(machine_dn, - {kAdDialog, kAdMachineOrgUnitInput}); + test::OobeJS().TypeIntoPath( + machine_name, {kEnrollmentUI, kAdDialog, kAdMachineNameInput}); + test::OobeJS().TypeIntoPath(username, + {kEnrollmentUI, kAdDialog, kAdUsernameInput}); + test::OobeJS().TypeIntoPath(password, + {kEnrollmentUI, kAdDialog, kAdPasswordInput}); + test::OobeJS().TapOnPath({kEnrollmentUI, kAdDialog, kAdMoreOptionsButton}); + test::OobeJS().TypeIntoPath( + machine_dn, {kEnrollmentUI, kAdDialog, kAdMachineOrgUnitInput}); if (!encryption_types.empty()) { - test::OobeJS().SelectElementInPath(encryption_types, - {kAdDialog, kAdEncryptionTypesSelect}); + test::OobeJS().SelectElementInPath( + encryption_types, + {kEnrollmentUI, kAdDialog, kAdEncryptionTypesSelect}); } - test::OobeJS().TapOnPath({kAdDialog, kAdMoreOptionsSaveButton}); + test::OobeJS().TapOnPath( + {kEnrollmentUI, kAdDialog, kAdMoreOptionsSaveButton}); test::OobeJS() - .CreateEnabledWaiter(true /* enabled */, {kAdDialog, kNextButton}) + .CreateEnabledWaiter(true /* enabled */, + {kEnrollmentUI, kAdDialog, kNextButton}) ->Wait(); - test::OobeJS().TapOnPath({kAdDialog, kNextButton}); + test::OobeJS().TapOnPath({kEnrollmentUI, kAdDialog, kNextButton}); } void SetExpectedJoinRequest( @@ -372,7 +382,6 @@ mock_auth_policy_client()->set_expected_request(std::move(request)); } - MockAuthPolicyClient* mock_auth_policy_client() { return mock_auth_policy_client_; } @@ -645,7 +654,7 @@ "legacy", kAdTestUser, "password"); WaitForMessage(&message_queue, "\"ShowADJoinError\""); enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepADJoinError); - test::OobeJS().TapOnPath({kAdErrorCard, kSubmitButton}); + test::OobeJS().TapOnPath({kEnrollmentUI, kAdErrorCard, kSubmitButton}); enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepADJoin); } @@ -671,22 +680,23 @@ ExpectElementValid(kAdUnlockPasswordInput, true); // Test skipping the password step and getting back. - test::OobeJS().TapOnPath({kAdDialog, kSkipButton}); + test::OobeJS().TapOnPath({kEnrollmentUI, kAdDialog, kSkipButton}); CheckActiveDirectoryCredentialsShown(); CheckConfigurationSelectionVisible(false); - test::OobeJS().TapOnPath({kAdDialog, kAdBackToUnlockButton}); + test::OobeJS().TapOnPath({kEnrollmentUI, kAdDialog, kAdBackToUnlockButton}); CheckActiveDirectoryUnlockConfigurationShown(); // Enter wrong unlock password. - test::OobeJS().TypeIntoPath("wrong_password", - {kAdDialog, kAdUnlockPasswordInput}); - test::OobeJS().TapOnPath({kAdDialog, kAdUnlockButton}); + test::OobeJS().TypeIntoPath( + "wrong_password", {kEnrollmentUI, kAdDialog, kAdUnlockPasswordInput}); + test::OobeJS().TapOnPath({kEnrollmentUI, kAdDialog, kAdUnlockButton}); WaitForMessage(&message_queue, "\"ShowJoinDomainError\""); ExpectElementValid(kAdUnlockPasswordInput, false); // Enter right unlock password. - test::OobeJS().TypeIntoPath("test765!", {kAdDialog, kAdUnlockPasswordInput}); - test::OobeJS().TapOnPath({kAdDialog, kAdUnlockButton}); + test::OobeJS().TypeIntoPath( + "test765!", {kEnrollmentUI, kAdDialog, kAdUnlockPasswordInput}); + test::OobeJS().TapOnPath({kEnrollmentUI, kAdDialog, kAdUnlockButton}); WaitForMessage(&message_queue, "\"SetAdJoinConfiguration\""); CheckActiveDirectoryCredentialsShown(); // Configuration selector should be visible.
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc index 3402848..690bc27 100644 --- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc +++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -834,7 +834,7 @@ guest_view::GuestViewManager::set_factory_for_testing( &guest_view_manager_factory_); gaia_frame_parent_ = "oauth-enroll-auth-view"; - authenticator_id_ = "$('oauth-enrollment').authenticator_"; + authenticator_id_ = "$('enterprise-enrollment').authenticator_"; } SAMLEnrollmentTest::~SAMLEnrollmentTest() {}
diff --git a/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.cc b/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.cc index cad3e28..bc28e4b 100644 --- a/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.cc +++ b/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.cc
@@ -31,6 +31,7 @@ #include "ui/message_center/public/cpp/notification.h" #include "ui/message_center/public/cpp/notification_delegate.h" +using message_center::ButtonInfo; using message_center::HandleNotificationClickDelegate; using message_center::Notification; using message_center::NotificationObserver; @@ -53,7 +54,7 @@ message_center::NotifierType::SYSTEM_COMPONENT, kNotificationId); -// Simplest type of notification - has text but no other UI elements. +// Simplest type of notification UI - no progress bars, images etc. const NotificationType kNotificationType = message_center::NOTIFICATION_TYPE_SIMPLE; @@ -64,34 +65,41 @@ // The icon to use for this notification - looks like an office building. const gfx::VectorIcon& kIcon = vector_icons::kBusinessIcon; -// Warning level NORMAL means the notification heading is blue. -const SystemNotificationWarningLevel kWarningLevel = - SystemNotificationWarningLevel::NORMAL; - // Leaving this empty means the notification is attributed to the system - // ie "Chromium OS" or similar. -const base::NoDestructor<base::string16> kDisplaySource; +const base::NoDestructor<base::string16> kEmptyDisplaySource; // No origin URL is needed since the notification comes from the system. const base::NoDestructor<GURL> kEmptyOriginUrl; -// Line separator in the notification body. -const base::NoDestructor<base::string16> kLineSeparator( - base::string16(1, '\n')); +// When the password will expire in |kCriticalWarningDays| or less, the warning +// will have red text, slightly stronger language, and doesn't automatically +// time out - it stays on the screen until the user hides or dismisses it. +const int kCriticalWarningDays = 3; base::string16 GetTitleText(int less_than_n_days) { - const bool hasExpired = (less_than_n_days <= 0); - return hasExpired ? l10n_util::GetStringUTF16(IDS_PASSWORD_HAS_EXPIRED_TITLE) - : l10n_util::GetStringUTF16(IDS_PASSWORD_WILL_EXPIRE_TITLE); + return l10n_util::GetPluralStringFUTF16(IDS_PASSWORD_EXPIRY_DAYS_BODY, + less_than_n_days); } -base::string16 GetBodyText(int less_than_n_days) { - const std::vector<base::string16> body_lines = { - l10n_util::GetPluralStringFUTF16(IDS_PASSWORD_EXPIRY_DAYS_BODY, - std::max(less_than_n_days, 0)), - l10n_util::GetStringUTF16(IDS_PASSWORD_EXPIRY_CHOOSE_NEW_PASSWORD_LINK)}; +base::string16 GetBodyText(bool is_critical) { + return is_critical + ? l10n_util::GetStringUTF16( + IDS_PASSWORD_EXPIRY_CALL_TO_ACTION_CRITICAL) + : l10n_util::GetStringUTF16(IDS_PASSWORD_EXPIRY_CALL_TO_ACTION); +} - return base::JoinString(body_lines, *kLineSeparator); +RichNotificationData GetRichNotificationData(bool is_critical) { + RichNotificationData result; + result.never_timeout = is_critical; + result.buttons = std::vector<ButtonInfo>{ButtonInfo( + l10n_util::GetStringUTF16(IDS_PASSWORD_EXPIRY_CHANGE_PASSWORD_BUTTON))}; + return result; +} + +SystemNotificationWarningLevel GetWarningLevel(bool is_critical) { + return is_critical ? SystemNotificationWarningLevel::CRITICAL_WARNING + : SystemNotificationWarningLevel::WARNING; } void ShowNotificationImpl( @@ -100,15 +108,18 @@ scoped_refptr<message_center::NotificationDelegate> delegate) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + const bool is_critical = less_than_n_days <= kCriticalWarningDays; const base::string16 title = GetTitleText(less_than_n_days); - const base::string16 body = GetBodyText(less_than_n_days); + const base::string16 body = GetBodyText(is_critical); + const RichNotificationData rich_notification_data = + GetRichNotificationData(is_critical); + const SystemNotificationWarningLevel warning_level = + GetWarningLevel(is_critical); - // TODO(olsen): Add button to notification - see UI mock. - RichNotificationData rich_notification_data; std::unique_ptr<Notification> notification = ash::CreateSystemNotification( - kNotificationType, kNotificationId, title, body, *kDisplaySource, + kNotificationType, kNotificationId, title, body, *kEmptyDisplaySource, *kEmptyOriginUrl, *kNotifierId, rich_notification_data, delegate, kIcon, - kWarningLevel); + warning_level); NotificationDisplayService* nds = NotificationDisplayServiceFactory::GetForProfile(profile); @@ -278,8 +289,10 @@ void Rechecker::Click(const base::Optional<int>& button_index, const base::Optional<base::string16>& reply) { - // TODO(olsen): Add a button, only handle clicks on the button itself. - PasswordChangeDialog::Show(profile_); + bool clicked_on_button = button_index.has_value(); + if (clicked_on_button) { + PasswordChangeDialog::Show(profile_); + } } void Rechecker::Close(bool by_user) {
diff --git a/chrome/browser/chromeos/login/saml/saml_password_expiry_notification_unittest.cc b/chrome/browser/chromeos/login/saml/saml_password_expiry_notification_unittest.cc index e6194499..b247e5d 100644 --- a/chrome/browser/chromeos/login/saml/saml_password_expiry_notification_unittest.cc +++ b/chrome/browser/chromeos/login/saml/saml_password_expiry_notification_unittest.cc
@@ -109,9 +109,9 @@ ShowSamlPasswordExpiryNotification(profile_, 0); ASSERT_TRUE(Notification().has_value()); - EXPECT_EQ(utf16("Password has expired"), Notification()->title()); - EXPECT_EQ(utf16("Your current password has expired!\n" - "Click here to choose a new password"), + EXPECT_EQ(utf16("Your current password has expired!"), + Notification()->title()); + EXPECT_EQ(utf16("Please choose a new password immediately"), Notification()->message()); DismissSamlPasswordExpiryNotification(profile_); @@ -122,9 +122,9 @@ ShowSamlPasswordExpiryNotification(profile_, 14); ASSERT_TRUE(Notification().has_value()); - EXPECT_EQ(utf16("Password will soon expire"), Notification()->title()); - EXPECT_EQ(utf16("Your current password will expire in less than 14 days!\n" - "Click here to choose a new password"), + EXPECT_EQ(utf16("Your current password will expire in less than 14 days!"), + Notification()->title()); + EXPECT_EQ(utf16("Please choose a new password now"), Notification()->message()); DismissSamlPasswordExpiryNotification(profile_); @@ -156,29 +156,32 @@ // Notification is shown immediately since password has expired. EXPECT_TRUE(Notification().has_value()); - EXPECT_EQ(utf16("Password has expired"), Notification()->title()); + EXPECT_EQ(utf16("Your current password has expired!"), + Notification()->title()); } TEST_F(SamlPasswordExpiryNotificationTest, MaybeShow_WillSoonExpire) { - SetExpirationTime(base::Time::Now() + (kAdvanceWarningTime / 2)); + SetExpirationTime(base::Time::Now() + (kAdvanceWarningTime / 2) - kOneHour); MaybeShowSamlPasswordExpiryNotification(profile_); // Notification is shown immediately since password will soon expire. EXPECT_TRUE(Notification().has_value()); - EXPECT_EQ(utf16("Password will soon expire"), Notification()->title()); + EXPECT_EQ(utf16("Your current password will expire in less than 7 days!"), + Notification()->title()); } TEST_F(SamlPasswordExpiryNotificationTest, MaybeShow_WillEventuallyExpire) { - SetExpirationTime(base::Time::Now() + kOneYear + (kAdvanceWarningTime / 2)); + SetExpirationTime(base::Time::Now() + kOneYear + kAdvanceWarningTime); MaybeShowSamlPasswordExpiryNotification(profile_); // Notification is not shown when expiration is still over a year away. EXPECT_FALSE(Notification().has_value()); // But, it will be shown once we are in the advance warning window: - test_environment_.FastForwardBy(kOneYear); + test_environment_.FastForwardBy(kOneYear + kOneHour); EXPECT_TRUE(Notification().has_value()); - EXPECT_EQ(utf16("Password will soon expire"), Notification()->title()); + EXPECT_EQ(utf16("Your current password will expire in less than 14 days!"), + Notification()->title()); } TEST_F(SamlPasswordExpiryNotificationTest, MaybeShow_DeleteExpirationTime) { @@ -195,12 +198,13 @@ } TEST_F(SamlPasswordExpiryNotificationTest, MaybeShow_PasswordChanged) { - SetExpirationTime(base::Time::Now() + (kAdvanceWarningTime / 2)); + SetExpirationTime(base::Time::Now() + (kAdvanceWarningTime / 2) - kOneHour); MaybeShowSamlPasswordExpiryNotification(profile_); // Notification is shown immediately since password will soon expire. EXPECT_TRUE(Notification().has_value()); - EXPECT_EQ(utf16("Password will soon expire"), Notification()->title()); + EXPECT_EQ(utf16("Your current password will expire in less than 7 days!"), + Notification()->title()); // Password is changed and notification is dismissed. SamlPasswordAttributes::DeleteFromPrefs(profile_->GetPrefs()); @@ -231,45 +235,44 @@ } TEST_F(SamlPasswordExpiryNotificationTest, TimePasses_NoUserActionTaken) { - SetExpirationTime(base::Time::Now() + kOneYear + kAdvanceWarningTime + - (kOneDay / 2)); + SetExpirationTime(base::Time::Now() + kOneYear + kAdvanceWarningTime); MaybeShowSamlPasswordExpiryNotification(profile_); // Notification is not shown immediately. EXPECT_FALSE(Notification().has_value()); // After one year, we are still not quite inside the advance warning window. - test_environment_.FastForwardBy(kOneYear); + test_environment_.FastForwardBy(kOneYear - (kOneDay / 2)); EXPECT_FALSE(Notification().has_value()); // But the next day, the notification is shown. test_environment_.FastForwardBy(kOneDay); EXPECT_TRUE(Notification().has_value()); - EXPECT_EQ(utf16("Password will soon expire"), Notification()->title()); - EXPECT_EQ(utf16("Your current password will expire in less than 14 days!\n" - "Click here to choose a new password"), + EXPECT_EQ(utf16("Your current password will expire in less than 14 days!"), + Notification()->title()); + EXPECT_EQ(utf16("Please choose a new password now"), Notification()->message()); // As time passes, the notification updates each day. test_environment_.FastForwardBy(kAdvanceWarningTime / 2); EXPECT_TRUE(Notification().has_value()); - EXPECT_EQ(utf16("Password will soon expire"), Notification()->title()); - EXPECT_EQ(utf16("Your current password will expire in less than 7 days!\n" - "Click here to choose a new password"), + EXPECT_EQ(utf16("Your current password will expire in less than 7 days!"), + Notification()->title()); + EXPECT_EQ(utf16("Please choose a new password now"), Notification()->message()); test_environment_.FastForwardBy(kAdvanceWarningTime / 2); EXPECT_TRUE(Notification().has_value()); - EXPECT_EQ(utf16("Password has expired"), Notification()->title()); - EXPECT_EQ(utf16("Your current password has expired!\n" - "Click here to choose a new password"), + EXPECT_EQ(utf16("Your current password has expired!"), + Notification()->title()); + EXPECT_EQ(utf16("Please choose a new password immediately"), Notification()->message()); test_environment_.FastForwardBy(kOneYear); EXPECT_TRUE(Notification().has_value()); - EXPECT_EQ(utf16("Password has expired"), Notification()->title()); - EXPECT_EQ(utf16("Your current password has expired!\n" - "Click here to choose a new password"), + EXPECT_EQ(utf16("Your current password has expired!"), + Notification()->title()); + EXPECT_EQ(utf16("Please choose a new password immediately"), Notification()->message()); }
diff --git a/chrome/browser/chromeos/login/test/enrollment_ui_mixin.cc b/chrome/browser/chromeos/login/test/enrollment_ui_mixin.cc index 7a1d6f4..fcd7be8 100644 --- a/chrome/browser/chromeos/login/test/enrollment_ui_mixin.cc +++ b/chrome/browser/chromeos/login/test/enrollment_ui_mixin.cc
@@ -51,16 +51,18 @@ ui::kEnrollmentStepDeviceAttributesError}; std::string StepVisibleExpression(const std::string& step) { - return "document.getElementsByClassName('oauth-enroll-state-" + step + - "').length > 0"; + return "Polymer.dom($('enterprise-enrollment').root)." + "querySelectorAll('.oauth-enroll-state-" + + step + "').length > 0"; } const std::initializer_list<base::StringPiece> kEnrollmentErrorRetryButtonPath = - {"oauth-enroll-error-card", "submitButton"}; + {"enterprise-enrollment", "oauth-enroll-error-card", "submitButton"}; const std::initializer_list<base::StringPiece> kEnrollmentDeviceAttributesErrorButtonPath = { - "oauth-enroll-attribute-prompt-error-card", "submitButton"}; + "enterprise-enrollment", "oauth-enroll-attribute-prompt-error-card", + "submitButton"}; } // namespace @@ -85,18 +87,19 @@ void EnrollmentUIMixin::SelectEnrollmentLicense( const std::string& license_type) { - OobeJS().SelectRadioPath( - {"oauth-enroll-license-ui", "license-option-" + license_type}); + OobeJS().SelectRadioPath({"enterprise-enrollment", "oauth-enroll-license-ui", + "license-option-" + license_type}); } void EnrollmentUIMixin::UseSelectedLicense() { - OobeJS().TapOnPath({"oauth-enroll-license-ui", "next"}); + OobeJS().TapOnPath( + {"enterprise-enrollment", "oauth-enroll-license-ui", "next"}); } void EnrollmentUIMixin::ExpectErrorMessage(int error_message_id, bool can_retry) { const std::string element_path = - GetOobeElementPath({"oauth-enroll-error-card"}); + GetOobeElementPath({"enterprise-enrollment", "oauth-enroll-error-card"}); const std::string message = OobeJS().GetString(element_path + ".textContent"); ASSERT_TRUE(std::string::npos != message.find(l10n_util::GetStringUTF8(error_message_id))); @@ -118,9 +121,12 @@ void EnrollmentUIMixin::SubmitDeviceAttributes(const std::string& asset_id, const std::string& location) { - OobeJS().TypeIntoPath(asset_id, {"oauth-enroll-asset-id"}); - OobeJS().TypeIntoPath(location, {"oauth-enroll-location"}); - OobeJS().TapOn("enroll-attributes-submit-button"); + OobeJS().TypeIntoPath(asset_id, + {"enterprise-enrollment", "oauth-enroll-asset-id"}); + OobeJS().TypeIntoPath(location, + {"enterprise-enrollment", "oauth-enroll-location"}); + OobeJS().TapOnPath( + {"enterprise-enrollment", "enroll-attributes-submit-button"}); } void EnrollmentUIMixin::SetExitHandler() {
diff --git a/chrome/browser/chromeos/login/test/enrollment_ui_mixin.h b/chrome/browser/chromeos/login/test/enrollment_ui_mixin.h index f27102f6..d6986d9b 100644 --- a/chrome/browser/chromeos/login/test/enrollment_ui_mixin.h +++ b/chrome/browser/chromeos/login/test/enrollment_ui_mixin.h
@@ -20,6 +20,7 @@ // WaitForStep(...) constants. extern const char kEnrollmentStepSignin[]; +extern const char kEnrollmentStepWorking[]; extern const char kEnrollmentStepLicenses[]; extern const char kEnrollmentStepDeviceAttributes[]; extern const char kEnrollmentStepSuccess[];
diff --git a/chrome/browser/chromeos/login/test/oobe_auth_page_waiter.cc b/chrome/browser/chromeos/login/test/oobe_auth_page_waiter.cc index 0d5bb49a..b8374e91 100644 --- a/chrome/browser/chromeos/login/test/oobe_auth_page_waiter.cc +++ b/chrome/browser/chromeos/login/test/oobe_auth_page_waiter.cc
@@ -16,7 +16,7 @@ constexpr char kGaiaAuthenticator[] = "$('gaia-signin').authenticator_"; constexpr char kEnrollmentAuthenticator[] = - "$('oauth-enrollment').authenticator_"; + "$('enterprise-enrollment').authenticator_"; void MaybeWaitForOobeToInitialize() { base::RunLoop run_loop;
diff --git a/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator.cc b/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator.cc index b3dea73..5bc3674 100644 --- a/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator.cc +++ b/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator.cc
@@ -15,8 +15,10 @@ AffiliatedCloudPolicyInvalidator::AffiliatedCloudPolicyInvalidator( enterprise_management::DeviceRegisterRequest::Type type, CloudPolicyCore* core, - AffiliatedInvalidationServiceProvider* invalidation_service_provider) - : type_(type), + AffiliatedInvalidationServiceProvider* invalidation_service_provider, + bool is_fcm_enabled) + : is_fcm_enabled_(is_fcm_enabled), + type_(type), core_(core), invalidation_service_provider_(invalidation_service_provider), highest_handled_invalidation_version_(0) { @@ -45,8 +47,8 @@ DCHECK(!invalidator_); invalidator_.reset(new CloudPolicyInvalidator( type_, core_, base::ThreadTaskRunnerHandle::Get(), - base::DefaultClock::GetInstance(), - highest_handled_invalidation_version_)); + base::DefaultClock::GetInstance(), highest_handled_invalidation_version_, + is_fcm_enabled_)); invalidator_->Initialize(invalidation_service); }
diff --git a/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator.h b/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator.h index b07a54f2..611ba9c 100644 --- a/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator.h +++ b/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator.h
@@ -36,7 +36,8 @@ AffiliatedCloudPolicyInvalidator( enterprise_management::DeviceRegisterRequest::Type type, CloudPolicyCore* core, - AffiliatedInvalidationServiceProvider* invalidation_service_provider); + AffiliatedInvalidationServiceProvider* invalidation_service_provider, + bool is_fcm_enabled); ~AffiliatedCloudPolicyInvalidator() override; // AffiliatedInvalidationServiceProvider::Consumer: @@ -53,6 +54,10 @@ // Destroy the current |CloudPolicyInvalidator|, if any. void DestroyInvalidator(); + // Whether or not should use FCM (Firebase Cloud Messaging) topic for + // registration. + const bool is_fcm_enabled_; + const enterprise_management::DeviceRegisterRequest::Type type_; CloudPolicyCore* const core_;
diff --git a/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator_unittest.cc b/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator_unittest.cc index 9bf16b6..d434e66 100644 --- a/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator_unittest.cc +++ b/chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator_unittest.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/policy/cloud/cloud_policy_invalidator.h" #include "components/invalidation/impl/fake_invalidation_service.h" #include "components/invalidation/public/invalidation.h" +#include "components/invalidation/public/invalidation_util.h" #include "components/invalidation/public/object_id_invalidation_map.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/cloud_policy_core.h" @@ -40,6 +41,7 @@ const int kInvalidationSource = 123; const char kInvalidationName[] = "invalidation"; +const char kPolicyInvalidationTopic[] = "policy_invalidation_topic"; class FakeCloudPolicyStore : public CloudPolicyStore { public: @@ -68,11 +70,17 @@ } // namespace +// Accepts boolean param is_fcm_enabled. +// true if FCM (Firebase Cloud Messaging) is enabled, +// and false otherwise. +class AffiliatedCloudPolicyInvalidatorTest + : public testing::TestWithParam<bool> {}; + // Verifies that an invalidator is created/destroyed as an invalidation service // becomes available/unavailable. Also verifies that invalidations are handled // correctly and the highest handled invalidation version is preserved when // switching invalidation services. -TEST(AffiliatedCloudPolicyInvalidatorTest, CreateUseDestroy) { +TEST_P(AffiliatedCloudPolicyInvalidatorTest, CreateUseDestroy) { content::TestBrowserThreadBundle thread_bundle; // Set up a CloudPolicyCore backed by a simple CloudPolicyStore that does no @@ -98,16 +106,26 @@ core.StartRefreshScheduler(); DevicePolicyBuilder policy; - policy.policy_data().set_invalidation_source(kInvalidationSource); - policy.policy_data().set_invalidation_name(kInvalidationName); + + const bool is_fcm_enabled = GetParam(); + if (is_fcm_enabled) { + // Pass deprecated source if FCM (Firebase Cloud Messaging) is enabled, + // because server does not support source field with FCM and + // InvalidationService fills the source field with kDeprecatedSourceForFCM. + policy.policy_data().set_invalidation_source( + syncer::kDeprecatedSourceForFCM); + policy.policy_data().set_policy_invalidation_topic( + kPolicyInvalidationTopic); + } else { + policy.policy_data().set_invalidation_source(kInvalidationSource); + policy.policy_data().set_invalidation_name(kInvalidationName); + } policy.Build(); store.Store(policy.policy()); FakeAffiliatedInvalidationServiceProvider provider; AffiliatedCloudPolicyInvalidator affiliated_invalidator( - em::DeviceRegisterRequest::DEVICE, - &core, - &provider); + em::DeviceRegisterRequest::DEVICE, &core, &provider, is_fcm_enabled); // Verify that no invalidator exists initially. EXPECT_FALSE(affiliated_invalidator.GetInvalidatorForTest()); @@ -130,10 +148,15 @@ // timestamp in microseconds. The policy blob contains a timestamp in // milliseconds. Convert from one to the other by multiplying by 1000. const int64_t invalidation_version = policy.policy_data().timestamp() * 1000; - syncer::Invalidation invalidation = syncer::Invalidation::Init( - invalidation::ObjectId(kInvalidationSource, kInvalidationName), - invalidation_version, - "dummy payload"); + syncer::Invalidation invalidation = + is_fcm_enabled + ? syncer::Invalidation::Init( + invalidation::ObjectId(syncer::kDeprecatedSourceForFCM, + kPolicyInvalidationTopic), + invalidation_version, "dummy payload") + : syncer::Invalidation::Init( + invalidation::ObjectId(kInvalidationSource, kInvalidationName), + invalidation_version, "dummy payload"); syncer::ObjectIdInvalidationMap invalidation_map; invalidation_map.Insert(invalidation); invalidator->OnIncomingInvalidation(invalidation_map); @@ -197,4 +220,8 @@ affiliated_invalidator.OnInvalidationServiceSet(nullptr); } +INSTANTIATE_TEST_SUITE_P(FCMEnabledAndFCMDisabled, + AffiliatedCloudPolicyInvalidatorTest, + testing::Bool() /* is_fcm_enabled */); + } // namespace policy
diff --git a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc index 403e179..b3e1d30 100644 --- a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc +++ b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc
@@ -19,9 +19,12 @@ #include "chrome/browser/chromeos/settings/device_identity_provider.h" #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h" #include "chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.h" +#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" +#include "components/gcm_driver/instance_id/instance_id_driver.h" +#include "components/invalidation/impl/fcm_invalidation_service.h" #include "components/invalidation/impl/invalidation_state_tracker.h" #include "components/invalidation/impl/invalidator_storage.h" #include "components/invalidation/impl/profile_invalidation_provider.h" @@ -37,6 +40,7 @@ #include "content/public/browser/network_service_instance.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" +#include "services/data_decoder/public/cpp/safe_json_parser.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/mojom/network_context.mojom.h" @@ -44,6 +48,17 @@ namespace { +invalidation::ProfileInvalidationProvider* GetInvalidationProvider( + Profile* profile, + bool is_fcm_enabled) { + if (is_fcm_enabled) { + return invalidation::ProfileInvalidationProviderFactory::GetForProfile( + profile); + } + return invalidation::DeprecatedProfileInvalidationProviderFactory:: + GetForProfile(profile); +} + // Runs on UI thread. void RequestProxyResolvingSocketFactoryOnUIThread( base::WeakPtr<invalidation::TiclInvalidationService> owner, @@ -154,13 +169,17 @@ } AffiliatedInvalidationServiceProviderImpl:: -AffiliatedInvalidationServiceProviderImpl() + AffiliatedInvalidationServiceProviderImpl(bool is_fcm_enabled, + std::string fcm_sender_id) : invalidation_service_(nullptr), consumer_count_(0), - is_shut_down_(false) { + is_shut_down_(false), + is_fcm_enabled_(is_fcm_enabled), + fcm_sender_id_(std::move(fcm_sender_id)) { // The AffiliatedInvalidationServiceProviderImpl should be created before any // user Profiles. DCHECK(g_browser_process->profile_manager()->GetLoadedProfiles().empty()); + DCHECK_EQ(is_fcm_enabled_, !fcm_sender_id_.empty()); // Subscribe to notification about new user profiles becoming available. registrar_.Add(this, @@ -182,8 +201,7 @@ DCHECK(!is_shut_down_); Profile* profile = content::Details<Profile>(details).ptr(); invalidation::ProfileInvalidationProvider* invalidation_provider = - invalidation::DeprecatedProfileInvalidationProviderFactory::GetForProfile( - profile); + GetInvalidationProvider(profile, is_fcm_enabled_); if (!invalidation_provider) { // If the Profile does not support invalidation (e.g. guest, incognito), // ignore it. @@ -198,8 +216,14 @@ } // Create a state observer for the user's invalidation service. - invalidation::InvalidationService* invalidation_service = - invalidation_provider->GetInvalidationService(); + invalidation::InvalidationService* invalidation_service; + if (is_fcm_enabled_) { + invalidation_service = + invalidation_provider->GetInvalidationServiceForCustomSender( + fcm_sender_id_); + } else { + invalidation_service = invalidation_provider->GetInvalidationService(); + } profile_invalidation_service_observers_.push_back( std::make_unique<InvalidationServiceObserver>(this, invalidation_service)); @@ -255,9 +279,9 @@ DestroyDeviceInvalidationService(); } -invalidation::TiclInvalidationService* -AffiliatedInvalidationServiceProviderImpl:: - GetDeviceInvalidationServiceForTest() const { +invalidation::InvalidationService* +AffiliatedInvalidationServiceProviderImpl::GetDeviceInvalidationServiceForTest() + const { return device_invalidation_service_.get(); } @@ -334,32 +358,9 @@ } if (!device_invalidation_service_) { - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory; - if (g_browser_process->system_network_context_manager()) { - // system_network_context_manager() can be null during unit tests. - url_loader_factory = g_browser_process->system_network_context_manager() - ->GetSharedURLLoaderFactory(); - } - - identity_provider_ = std::make_unique<chromeos::DeviceIdentityProvider>( - chromeos::DeviceOAuth2TokenServiceFactory::Get()); - - DCHECK(identity_provider_); // If no other connected invalidation service was found and no device-global // invalidation service exists, create one. - device_invalidation_service_ = - std::make_unique<invalidation::TiclInvalidationService>( - GetUserAgent(), identity_provider_.get(), - g_browser_process->gcm_driver(), - base::BindRepeating(&RequestProxyResolvingSocketFactory), - base::CreateSingleThreadTaskRunnerWithTraits( - {content::BrowserThread::IO}), - std::move(url_loader_factory), - content::GetNetworkConnectionTracker()); - device_invalidation_service_->Init( - std::unique_ptr<syncer::InvalidationStateTracker>( - new invalidation::InvalidatorStorage( - g_browser_process->local_state()))); + device_invalidation_service_ = InitializeDeviceInvalidationService(); device_invalidation_service_observer_.reset( new InvalidationServiceObserver( this, @@ -386,7 +387,56 @@ AffiliatedInvalidationServiceProviderImpl::DestroyDeviceInvalidationService() { device_invalidation_service_observer_.reset(); device_invalidation_service_.reset(); - identity_provider_.reset(); + device_identity_provider_.reset(); + device_instance_id_driver_.reset(); +} + +std::unique_ptr<invalidation::InvalidationService> +AffiliatedInvalidationServiceProviderImpl:: + InitializeDeviceInvalidationService() { + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory; + if (g_browser_process->system_network_context_manager()) { + // system_network_context_manager() can be null during unit tests. + url_loader_factory = g_browser_process->system_network_context_manager() + ->GetSharedURLLoaderFactory(); + DCHECK(url_loader_factory); + } + + device_identity_provider_ = + std::make_unique<chromeos::DeviceIdentityProvider>( + chromeos::DeviceOAuth2TokenServiceFactory::Get()); + + if (is_fcm_enabled_) { + device_instance_id_driver_ = + std::make_unique<instance_id::InstanceIDDriver>( + g_browser_process->gcm_driver()); + DCHECK(device_instance_id_driver_); + auto device_invalidation_service = + std::make_unique<invalidation::FCMInvalidationService>( + device_identity_provider_.get(), g_browser_process->gcm_driver(), + device_instance_id_driver_.get(), g_browser_process->local_state(), + base::BindRepeating( + data_decoder::SafeJsonParser::Parse, + content::ServiceManagerConnection::GetForProcess() + ->GetConnector()), + url_loader_factory.get(), fcm_sender_id_); + device_invalidation_service->Init(); + return device_invalidation_service; + } + auto device_invalidation_service = + std::make_unique<invalidation::TiclInvalidationService>( + GetUserAgent(), device_identity_provider_.get(), + g_browser_process->gcm_driver(), + base::BindRepeating(&RequestProxyResolvingSocketFactory), + base::CreateSingleThreadTaskRunnerWithTraits( + {content::BrowserThread::IO}), + std::move(url_loader_factory), + content::GetNetworkConnectionTracker()); + + device_invalidation_service->Init( + std::make_unique<invalidation::InvalidatorStorage>( + g_browser_process->local_state())); + return device_invalidation_service; } } // namespace policy
diff --git a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.h b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.h index 6cf803c..d9ed2b26 100644 --- a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.h +++ b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_CHROMEOS_POLICY_AFFILIATED_INVALIDATION_SERVICE_PROVIDER_IMPL_H_ #include <memory> +#include <string> #include <vector> #include "base/macros.h" @@ -17,7 +18,10 @@ namespace invalidation { class InvalidationService; -class TiclInvalidationService; +} + +namespace instance_id { +class InstanceIDDriver; } namespace policy { @@ -26,7 +30,8 @@ : public AffiliatedInvalidationServiceProvider, public content::NotificationObserver { public: - AffiliatedInvalidationServiceProviderImpl(); + AffiliatedInvalidationServiceProviderImpl(bool is_fcm_enabled, + std::string fcm_sender_id); ~AffiliatedInvalidationServiceProviderImpl() override; // content::NotificationObserver: @@ -39,8 +44,8 @@ void UnregisterConsumer(Consumer* consumer) override; void Shutdown() override; - invalidation::TiclInvalidationService* - GetDeviceInvalidationServiceForTest() const; + invalidation::InvalidationService* GetDeviceInvalidationServiceForTest() + const; private: // Helper that monitors the status of a single |InvalidationService|. @@ -69,19 +74,29 @@ // Destroy the device-global invalidation service, if any. void DestroyDeviceInvalidationService(); - content::NotificationRegistrar registrar_; + // Initializes and returns either TiclInvalidationService or + // FCMInvalidationService depending on the value of |is_fcm_enabled|. + std::unique_ptr<invalidation::InvalidationService> + InitializeDeviceInvalidationService(); - // Device-global invalidation service. - std::unique_ptr<invalidation::TiclInvalidationService> - device_invalidation_service_; + content::NotificationRegistrar registrar_; // State observer for the device-global invalidation service. std::unique_ptr<InvalidationServiceObserver> device_invalidation_service_observer_; - // The |identity_provider_| must be declared before |invalidation_service_| - // becaise the service has a pointer to it. - std::unique_ptr<invalidation::IdentityProvider> identity_provider_; + // The |device_identity_provider_| must be declared before + // |device_invalidation_service_| because the service has a pointer to it. + std::unique_ptr<invalidation::IdentityProvider> device_identity_provider_; + + // The |device_instance_id_driver_| must be declared before + // |device_invalidation_service_| because the service has a pointer to it. Not + // null only when FCM is enabled. + std::unique_ptr<instance_id::InstanceIDDriver> device_instance_id_driver_; + + // Device-global invalidation service. + std::unique_ptr<invalidation::InvalidationService> + device_invalidation_service_; // State observers for logged-in users' invalidation services. std::vector<std::unique_ptr<InvalidationServiceObserver>> @@ -97,6 +112,15 @@ bool is_shut_down_; + // Whether FCM (Firebase Cloud Messaging) should be used for invalidating + // policies. If false, TICL (Tango Invalidation Client Library) is used + // instead. + const bool is_fcm_enabled_; + + // Sender ID coming from the Firebase console. Is set only when + // |is_fcm_enabled_| is true. + const std::string fcm_sender_id_; + DISALLOW_COPY_AND_ASSIGN(AffiliatedInvalidationServiceProviderImpl); };
diff --git a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc index 06f235a..0fabf88 100644 --- a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc +++ b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc
@@ -12,11 +12,13 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" +#include "base/task/post_task.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h" #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h" #include "chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.h" +#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" @@ -24,6 +26,7 @@ #include "chromeos/dbus/cryptohome/cryptohome_client.h" #include "components/invalidation/impl/fake_invalidation_handler.h" #include "components/invalidation/impl/fake_invalidation_service.h" +#include "components/invalidation/impl/fcm_invalidation_service.h" #include "components/invalidation/impl/profile_invalidation_provider.h" #include "components/invalidation/impl/ticl_invalidation_service.h" #include "components/invalidation/public/invalidation_service.h" @@ -32,9 +35,14 @@ #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/user_manager/scoped_user_manager.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" +#include "content/public/common/service_manager_connection.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "services/data_decoder/public/cpp/safe_json_parser.h" +#include "services/data_decoder/public/cpp/testing_json_parser.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h" #include "testing/gtest/include/gtest/gtest.h" @@ -47,16 +55,54 @@ const char kAffiliatedUserID2[] = "test_2@example.com"; const char kUnaffiliatedUserID[] = "test@other_domain.test"; -std::unique_ptr<KeyedService> BuildProfileInvalidationProvider( - content::BrowserContext* context) { +const char kFCMSenderId[] = "112233"; + +std::unique_ptr<invalidation::InvalidationService> +CreateInvalidationServiceForSenderId(const std::string& fcm_sender_id) { std::unique_ptr<invalidation::FakeInvalidationService> invalidation_service( new invalidation::FakeInvalidationService); invalidation_service->SetInvalidatorState( syncer::TRANSIENT_INVALIDATION_ERROR); + return invalidation_service; +} + +std::unique_ptr<KeyedService> BuildProfileInvalidationProvider( + bool is_fcm_enabled, + content::BrowserContext* context) { + if (is_fcm_enabled) { + return std::make_unique<invalidation::ProfileInvalidationProvider>( + nullptr, nullptr, + base::BindRepeating(&CreateInvalidationServiceForSenderId)); + } + auto invalidation_service = + std::make_unique<invalidation::FakeInvalidationService>(); + invalidation_service->SetInvalidatorState( + syncer::TRANSIENT_INVALIDATION_ERROR); return std::make_unique<invalidation::ProfileInvalidationProvider>( std::move(invalidation_service), nullptr); } +data_decoder::SafeJsonParser* CreateTestingJsonParser( + const std::string& unsafe_json, + data_decoder::SafeJsonParser::SuccessCallback success_callback, + data_decoder::SafeJsonParser::ErrorCallback error_callback) { + return new data_decoder::TestingJsonParser( + unsafe_json, std::move(success_callback), std::move(error_callback)); +} + +void SendInvalidatorStateChangeNotification( + invalidation::InvalidationService* service, + syncer::InvalidatorState state, + bool is_fcm_enabled) { + if (is_fcm_enabled) { + static_cast<invalidation::FCMInvalidationService*>(service) + ->OnInvalidatorStateChange(state); + return; + } + static_cast<invalidation::TiclInvalidationService*>(service) + ->OnInvalidatorStateChange(state); +} + } // namespace // A simple AffiliatedInvalidationServiceProvider::Consumer that registers a @@ -84,9 +130,12 @@ DISALLOW_COPY_AND_ASSIGN(FakeConsumer); }; -class AffiliatedInvalidationServiceProviderImplTest : public testing::Test { +// The param is is_fcm_enabled_. See below. +class AffiliatedInvalidationServiceProviderImplTest + : public testing::TestWithParam<bool> { public: AffiliatedInvalidationServiceProviderImplTest(); + ~AffiliatedInvalidationServiceProviderImplTest(); // testing::Test: void SetUp() override; @@ -128,8 +177,11 @@ bool is_affiliated); std::unique_ptr<AffiliatedInvalidationServiceProviderImpl> provider_; std::unique_ptr<FakeConsumer> consumer_; - invalidation::TiclInvalidationService* device_invalidation_service_; + invalidation::InvalidationService* device_invalidation_service_; invalidation::FakeInvalidationService* profile_invalidation_service_; + // Boolean param, true if FCM (Firebase Cloud Messaging) is enabled, + // and false otherwise. + const bool is_fcm_enabled_; private: content::TestBrowserThreadBundle thread_bundle_; @@ -191,11 +243,30 @@ AffiliatedInvalidationServiceProviderImplTest() : device_invalidation_service_(nullptr), profile_invalidation_service_(nullptr), + is_fcm_enabled_(GetParam()), fake_user_manager_(new chromeos::FakeChromeUserManager), user_manager_enabler_(base::WrapUnique(fake_user_manager_)), profile_manager_(TestingBrowserProcess::GetGlobal()) { cros_settings_test_helper_.InstallAttributes()->SetCloudManaged("example.com", "device_id"); + + if (is_fcm_enabled_) { + data_decoder::SafeJsonParser::SetFactoryForTesting( + &CreateTestingJsonParser); + + content::ServiceManagerConnection::SetForProcess( + content::ServiceManagerConnection::Create( + nullptr, base::CreateSingleThreadTaskRunnerWithTraits( + {content::BrowserThread::IO}))); + } +} + +AffiliatedInvalidationServiceProviderImplTest:: + ~AffiliatedInvalidationServiceProviderImplTest() { + if (is_fcm_enabled_) { + content::ServiceManagerConnection::DestroyForProcess(); + data_decoder::SafeJsonParser::SetFactoryForTesting(nullptr); + } } void AffiliatedInvalidationServiceProviderImplTest::SetUp() { @@ -207,11 +278,21 @@ test_url_loader_factory_.GetSafeWeakWrapper(), TestingBrowserProcess::GetGlobal()->local_state()); - invalidation::DeprecatedProfileInvalidationProviderFactory::GetInstance() - ->RegisterTestingFactory( - base::BindRepeating(&BuildProfileInvalidationProvider)); + if (is_fcm_enabled_) { + invalidation::ProfileInvalidationProviderFactory::GetInstance() + ->RegisterTestingFactory(base::BindRepeating( + &BuildProfileInvalidationProvider, is_fcm_enabled_)); + } else { + invalidation::DeprecatedProfileInvalidationProviderFactory::GetInstance() + ->RegisterTestingFactory(base::BindRepeating( + &BuildProfileInvalidationProvider, is_fcm_enabled_)); + } - provider_ = std::make_unique<AffiliatedInvalidationServiceProviderImpl>(); + provider_ = is_fcm_enabled_ + ? std::make_unique<AffiliatedInvalidationServiceProviderImpl>( + is_fcm_enabled_, kFCMSenderId) + : std::make_unique<AffiliatedInvalidationServiceProviderImpl>( + is_fcm_enabled_, ""); } void AffiliatedInvalidationServiceProviderImplTest::TearDown() { @@ -219,9 +300,15 @@ provider_->Shutdown(); provider_.reset(); - invalidation::DeprecatedProfileInvalidationProviderFactory::GetInstance() - ->RegisterTestingFactory( - BrowserContextKeyedServiceFactory::TestingFactory()); + if (is_fcm_enabled_) { + invalidation::ProfileInvalidationProviderFactory::GetInstance() + ->RegisterTestingFactory( + BrowserContextKeyedServiceFactory::TestingFactory()); + } else { + invalidation::DeprecatedProfileInvalidationProviderFactory::GetInstance() + ->RegisterTestingFactory( + BrowserContextKeyedServiceFactory::TestingFactory()); + } chromeos::DeviceOAuth2TokenServiceFactory::Shutdown(); chromeos::CryptohomeClient::Shutdown(); chromeos::SystemSaltGetter::Shutdown(); @@ -311,8 +398,9 @@ // Indicate that the device-global invalidation service has connected. Verify // that the consumer is informed about this. EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount()); - device_invalidation_service_->OnInvalidatorStateChange( - syncer::INVALIDATIONS_ENABLED); + SendInvalidatorStateChangeNotification(device_invalidation_service_, + syncer::INVALIDATIONS_ENABLED, + is_fcm_enabled_); EXPECT_EQ(1, consumer_->GetAndClearInvalidationServiceSetCount()); EXPECT_EQ(device_invalidation_service_, consumer_->GetInvalidationService()); } @@ -336,13 +424,26 @@ invalidation::FakeInvalidationService* AffiliatedInvalidationServiceProviderImplTest::GetProfileInvalidationService( Profile* profile, bool create) { - invalidation::ProfileInvalidationProvider* invalidation_provider = - static_cast<invalidation::ProfileInvalidationProvider*>( - invalidation::DeprecatedProfileInvalidationProviderFactory:: - GetInstance() - ->GetServiceForBrowserContext(profile, create)); + invalidation::ProfileInvalidationProvider* invalidation_provider; + if (is_fcm_enabled_) { + invalidation_provider = + static_cast<invalidation::ProfileInvalidationProvider*>( + invalidation::ProfileInvalidationProviderFactory::GetInstance() + ->GetServiceForBrowserContext(profile, create)); + } else { + invalidation_provider = + static_cast<invalidation::ProfileInvalidationProvider*>( + invalidation::DeprecatedProfileInvalidationProviderFactory:: + GetInstance() + ->GetServiceForBrowserContext(profile, create)); + } if (!invalidation_provider) return nullptr; + if (is_fcm_enabled_) { + return static_cast<invalidation::FakeInvalidationService*>( + invalidation_provider->GetInvalidationServiceForCustomSender( + kFCMSenderId)); + } return static_cast<invalidation::FakeInvalidationService*>( invalidation_provider->GetInvalidationService()); } @@ -351,7 +452,7 @@ // AffiliatedInvalidationServiceProviderImpl. Verifies that no device-global // invalidation service is created, whether an affiliated user is logged in or // not. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, NoConsumers) { +TEST_P(AffiliatedInvalidationServiceProviderImplTest, NoConsumers) { // Verify that no device-global invalidation service has been created. EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest()); @@ -364,7 +465,7 @@ // Verifies that when no connected invalidation service is available for use, // none is made available to consumers. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, +TEST_P(AffiliatedInvalidationServiceProviderImplTest, NoInvalidationServiceAvailable) { // Register a consumer. Verify that the consumer is not called back // immediately as no connected invalidation service exists yet. @@ -377,7 +478,7 @@ // affiliated user is available, a device-global invalidation service is // created. Further verifies that when the device-global invalidation service // connects, it is made available to the consumer. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, +TEST_P(AffiliatedInvalidationServiceProviderImplTest, UseDeviceInvalidationService) { consumer_.reset(new FakeConsumer(provider_.get())); @@ -388,8 +489,9 @@ // Indicate that the device-global invalidation service has disconnected. // Verify that the consumer is informed about this. EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount()); - device_invalidation_service_->OnInvalidatorStateChange( - syncer::INVALIDATION_CREDENTIALS_REJECTED); + SendInvalidatorStateChangeNotification( + device_invalidation_service_, syncer::INVALIDATION_CREDENTIALS_REJECTED, + is_fcm_enabled_); EXPECT_EQ(1, consumer_->GetAndClearInvalidationServiceSetCount()); EXPECT_EQ(nullptr, consumer_->GetInvalidationService()); @@ -400,7 +502,7 @@ // A consumer is registered with the AffiliatedInvalidationServiceProviderImpl. // Verifies that when a per-profile invalidation service belonging to an // affiliated user connects, it is made available to the consumer. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, +TEST_P(AffiliatedInvalidationServiceProviderImplTest, UseAffiliatedProfileInvalidationService) { consumer_.reset(new FakeConsumer(provider_.get())); @@ -422,7 +524,7 @@ // A consumer is registered with the AffiliatedInvalidationServiceProviderImpl. // Verifies that when a per-profile invalidation service belonging to an // unaffiliated user connects, it is ignored. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, +TEST_P(AffiliatedInvalidationServiceProviderImplTest, DoNotUseUnaffiliatedProfileInvalidationService) { consumer_.reset(new FakeConsumer(provider_.get())); @@ -441,7 +543,7 @@ // available to the consumer. Verifies that when a per-profile invalidation // service belonging to an affiliated user connects, it is made available to the // consumer instead and the device-global invalidation service is destroyed. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, +TEST_P(AffiliatedInvalidationServiceProviderImplTest, SwitchToAffiliatedProfileInvalidationService) { consumer_.reset(new FakeConsumer(provider_.get())); @@ -462,7 +564,7 @@ // service belonging to an unaffiliated user connects, it is ignored and the // device-global invalidation service continues to be made available to the // consumer. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, +TEST_P(AffiliatedInvalidationServiceProviderImplTest, DoNotSwitchToUnaffiliatedProfileInvalidationService) { consumer_.reset(new FakeConsumer(provider_.get())); @@ -483,7 +585,7 @@ // per-profile invalidation service disconnects, a device-global invalidation // service is created. Further verifies that when the device-global invalidation // service connects, it is made available to the consumer. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, +TEST_P(AffiliatedInvalidationServiceProviderImplTest, SwitchToDeviceInvalidationService) { consumer_.reset(new FakeConsumer(provider_.get())); @@ -513,7 +615,7 @@ // connected. Verifies that when the per-profile invalidation service belonging // to the first user disconnects, the per-profile invalidation service belonging // to the second user is made available to the consumer instead. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, +TEST_P(AffiliatedInvalidationServiceProviderImplTest, SwitchBetweenAffiliatedProfileInvalidationServices) { consumer_.reset(new FakeConsumer(provider_.get())); @@ -568,7 +670,7 @@ // invalidation service is not destroyed and remains available to the second // consumer. Further verifies that when the second consumer also unregisters, // the device-global invalidation service is destroyed. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, MultipleConsumers) { +TEST_P(AffiliatedInvalidationServiceProviderImplTest, MultipleConsumers) { consumer_.reset(new FakeConsumer(provider_.get())); // Indicate that the device-global invalidation service connected. Verify that @@ -604,7 +706,7 @@ // device-global invalidation service is created and a per-profile invalidation // service belonging to a second affiliated user that subsequently connects is // ignored. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, NoServiceAfterShutdown) { +TEST_P(AffiliatedInvalidationServiceProviderImplTest, NoServiceAfterShutdown) { consumer_.reset(new FakeConsumer(provider_.get())); // Verify that a device-global invalidation service has been created. @@ -654,7 +756,7 @@ // consumer is informed that no invalidation service is available for use // anymore before the device-global invalidation service is destroyed. // This is a regression test for http://crbug.com/455504. -TEST_F(AffiliatedInvalidationServiceProviderImplTest, +TEST_P(AffiliatedInvalidationServiceProviderImplTest, ConnectedDeviceGlobalInvalidationServiceOnShutdown) { consumer_.reset(new FakeConsumer(provider_.get())); @@ -680,4 +782,8 @@ EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest()); } +INSTANTIATE_TEST_SUITE_P(FCMEnabledAndFCMDisabled, + AffiliatedInvalidationServiceProviderImplTest, + testing::Bool() /* is_fcm_enabled */); + } // namespace policy
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc index 4d5260c..6f8ebe1 100644 --- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc +++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
@@ -45,6 +45,7 @@ #include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chrome/browser/chromeos/system/timezone_util.h" #include "chrome/browser/policy/device_management_service_configuration.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chromeos/attestation/attestation_flow.h" #include "chromeos/constants/chromeos_paths.h" @@ -64,6 +65,7 @@ #include "chromeos/system/statistics_provider.h" #include "chromeos/tpm/install_attributes.h" #include "components/policy/core/common/cloud/cloud_policy_client.h" +#include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h" #include "components/policy/core/common/cloud/resource_cache.h" #include "components/policy/core/common/proxy_policy_provider.h" @@ -165,8 +167,12 @@ local_state_ = local_state; ChromeBrowserPolicyConnector::Init(local_state, url_loader_factory); + const bool is_fcm_enabled = + base::FeatureList::IsEnabled(features::kPolicyFcmInvalidations); affiliated_invalidation_service_provider_ = - std::make_unique<AffiliatedInvalidationServiceProviderImpl>(); + std::make_unique<AffiliatedInvalidationServiceProviderImpl>( + is_fcm_enabled, + is_fcm_enabled ? policy::kPolicyFCMInvalidationSenderID : ""); if (device_cloud_policy_manager_) { // Note: for now the |device_cloud_policy_manager_| is using the global @@ -196,7 +202,7 @@ std::make_unique<AffiliatedCloudPolicyInvalidator>( em::DeviceRegisterRequest::DEVICE, device_cloud_policy_manager_->core(), - affiliated_invalidation_service_provider_.get()); + affiliated_invalidation_service_provider_.get(), is_fcm_enabled); device_remote_commands_invalidator_ = std::make_unique<AffiliatedRemoteCommandsInvalidator>( device_cloud_policy_manager_->core(),
diff --git a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc index 561cb41..f9ea7db 100644 --- a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc +++ b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc
@@ -340,7 +340,7 @@ ScreenMagnifierPolicyHandler::ScreenMagnifierPolicyHandler() : IntRangePolicyHandlerBase(key::kScreenMagnifierType, chromeos::MAGNIFIER_DISABLED, - chromeos::MAGNIFIER_FULL, + chromeos::MAGNIFIER_DOCKED, false) {} ScreenMagnifierPolicyHandler::~ScreenMagnifierPolicyHandler() { @@ -352,10 +352,10 @@ const base::Value* value = policies.GetValue(policy_name()); int value_in_range; if (value && EnsureInRange(value, &value_in_range, nullptr)) { - // The "type" is only used to enable or disable the feature as a whole. - // http://crbug.com/170850 prefs->SetBoolean(ash::prefs::kAccessibilityScreenMagnifierEnabled, - value_in_range != chromeos::MAGNIFIER_DISABLED); + value_in_range == chromeos::MAGNIFIER_FULL); + prefs->SetBoolean(ash::prefs::kDockedMagnifierEnabled, + value_in_range == chromeos::MAGNIFIER_DOCKED); } }
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc index 6f3e1b1..e03310d 100644 --- a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc +++ b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/chromeos/policy/device_local_account_policy_store.h" #include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chrome/common/chrome_content_client.h" +#include "chrome/common/chrome_features.h" #include "chromeos/constants/chromeos_paths.h" #include "chromeos/dbus/session_manager/session_manager_client.h" #include "chromeos/settings/cros_settings_names.h" @@ -209,9 +210,8 @@ core_.StartRefreshScheduler(); UpdateRefreshDelay(); invalidator_.reset(new AffiliatedCloudPolicyInvalidator( - em::DeviceRegisterRequest::DEVICE, - &core_, - invalidation_service_provider_)); + em::DeviceRegisterRequest::DEVICE, &core_, invalidation_service_provider_, + base::FeatureList::IsEnabled(features::kPolicyFcmInvalidations))); } void DeviceLocalAccountPolicyBroker::UpdateRefreshDelay() {
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc index ec1072f..1450d902a 100644 --- a/chrome/browser/net/system_network_context_manager.cc +++ b/chrome/browser/net/system_network_context_manager.cc
@@ -61,6 +61,7 @@ #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/mojom/host_resolver.mojom.h" #include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h" +#include "third_party/blink/public/common/features.h" #include "url/gurl.h" #if defined(OS_ANDROID) @@ -642,19 +643,25 @@ // respect prefs::kEnableReferrers from the appropriate pref store. network_context_params->enable_referrers = false; - std::string quic_user_agent_id = chrome::GetChannelName(); - if (!quic_user_agent_id.empty()) - quic_user_agent_id.push_back(' '); - quic_user_agent_id.append( - version_info::GetProductNameAndVersionForUserAgent()); - quic_user_agent_id.push_back(' '); - quic_user_agent_id.append( - content::BuildOSCpuInfo(false /* include_android_build_number */)); - network_context_params->quic_user_agent_id = quic_user_agent_id; - const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); + std::string quic_user_agent_id; + + if (base::FeatureList::IsEnabled(blink::features::kFreezeUserAgent)) { + quic_user_agent_id = ""; + } else { + quic_user_agent_id = chrome::GetChannelName(); + if (!quic_user_agent_id.empty()) + quic_user_agent_id.push_back(' '); + quic_user_agent_id.append( + version_info::GetProductNameAndVersionForUserAgent()); + quic_user_agent_id.push_back(' '); + quic_user_agent_id.append( + content::BuildOSCpuInfo(false /* include_android_build_number */)); + } + network_context_params->quic_user_agent_id = quic_user_agent_id; + // TODO(eroman): Figure out why this doesn't work in single-process mode, // or if it does work, now. // Should be possible now that a private isolate is used.
diff --git a/chrome/browser/net/system_network_context_manager_browsertest.cc b/chrome/browser/net/system_network_context_manager_browsertest.cc index 5d917e5..f340365f 100644 --- a/chrome/browser/net/system_network_context_manager_browsertest.cc +++ b/chrome/browser/net/system_network_context_manager_browsertest.cc
@@ -13,14 +13,19 @@ #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" +#include "chrome/common/channel_info.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/prefs/pref_service.h" +#include "components/version_info/version_info.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/user_agent.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_service.mojom.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" namespace { @@ -297,3 +302,45 @@ INSTANTIATE_TEST_SUITE_P(, SystemNetworkContextManagerStubResolverBrowsertest, ::testing::Values(false, true)); + +class SystemNetworkContextManagerFreezeQUICUaBrowsertest + : public SystemNetworkContextManagerBrowsertest, + public testing::WithParamInterface<bool> { + public: + SystemNetworkContextManagerFreezeQUICUaBrowsertest() { + scoped_feature_list_.InitWithFeatureState(blink::features::kFreezeUserAgent, + GetParam()); + } + ~SystemNetworkContextManagerFreezeQUICUaBrowsertest() override {} + + void SetUpOnMainThread() override {} + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +bool ContainsSubstring(std::string super, std::string sub) { + return super.find(sub) != std::string::npos; +} + +IN_PROC_BROWSER_TEST_P(SystemNetworkContextManagerFreezeQUICUaBrowsertest, + QUICUaConfig) { + network::mojom::NetworkContextParamsPtr network_context_params = + g_browser_process->system_network_context_manager() + ->CreateDefaultNetworkContextParams(); + + std::string quic_ua = network_context_params->quic_user_agent_id; + + if (GetParam()) { // if the UA Freeze feature is turned on + EXPECT_EQ("", quic_ua); + } else { + EXPECT_TRUE(ContainsSubstring(quic_ua, chrome::GetChannelName())); + EXPECT_TRUE(ContainsSubstring( + quic_ua, version_info::GetProductNameAndVersionForUserAgent())); + EXPECT_TRUE(ContainsSubstring(quic_ua, content::BuildOSCpuInfo(false))); + } +} + +INSTANTIATE_TEST_SUITE_P(, + SystemNetworkContextManagerFreezeQUICUaBrowsertest, + ::testing::Values(true, false));
diff --git a/chrome/browser/password_manager/password_accessory_metrics_util.h b/chrome/browser/password_manager/password_accessory_metrics_util.h index 240d9a4..ca36c8b 100644 --- a/chrome/browser/password_manager/password_accessory_metrics_util.h +++ b/chrome/browser/password_manager/password_accessory_metrics_util.h
@@ -43,6 +43,7 @@ PASSWORD = 1, PAYMENT_INFO = 2, ADDRESS_INFO = 3, + TOUCH_TO_FILL_INFO = 4, COUNT, };
diff --git a/chrome/browser/password_manager/password_store_x.cc b/chrome/browser/password_manager/password_store_x.cc index 394977ce..e6994c2 100644 --- a/chrome/browser/password_manager/password_store_x.cc +++ b/chrome/browser/password_manager/password_store_x.cc
@@ -188,13 +188,14 @@ } PasswordStoreChangeList PasswordStoreX::UpdateLoginImpl( - const PasswordForm& form) { + const PasswordForm& form, + password_manager::UpdateLoginError* error) { CheckMigration(); PasswordStoreChangeList changes; if (use_native_backend() && backend_->UpdateLogin(form, &changes)) { allow_fallback_ = false; } else if (allow_default_store()) { - changes = PasswordStoreDefault::UpdateLoginImpl(form); + changes = PasswordStoreDefault::UpdateLoginImpl(form, error); } return changes; }
diff --git a/chrome/browser/password_manager/password_store_x.h b/chrome/browser/password_manager/password_store_x.h index 9b4bf0c..8eb0b6f 100644 --- a/chrome/browser/password_manager/password_store_x.h +++ b/chrome/browser/password_manager/password_store_x.h
@@ -158,7 +158,8 @@ const autofill::PasswordForm& form, password_manager::AddLoginError* error = nullptr) override; password_manager::PasswordStoreChangeList UpdateLoginImpl( - const autofill::PasswordForm& form) override; + const autofill::PasswordForm& form, + password_manager::UpdateLoginError* error = nullptr) override; password_manager::PasswordStoreChangeList RemoveLoginImpl( const autofill::PasswordForm& form) override; password_manager::PasswordStoreChangeList RemoveLoginsByURLAndTimeImpl(
diff --git a/chrome/browser/policy/cloud/cloud_policy_invalidator.cc b/chrome/browser/policy/cloud/cloud_policy_invalidator.cc index 5631ae9..ec6035e 100644 --- a/chrome/browser/policy/cloud/cloud_policy_invalidator.cc +++ b/chrome/browser/policy/cloud/cloud_policy_invalidator.cc
@@ -25,6 +25,11 @@ namespace policy { +namespace { + +constexpr char kFcmPolicyPublicTopicPrefix[] = "cs-"; +} // namespace + const int CloudPolicyInvalidator::kMissingPayloadDelay = 5; const int CloudPolicyInvalidator::kMaxFetchDelayDefault = 10000; const int CloudPolicyInvalidator::kMaxFetchDelayMin = 1000; @@ -38,7 +43,8 @@ CloudPolicyCore* core, const scoped_refptr<base::SequencedTaskRunner>& task_runner, base::Clock* clock, - int64_t highest_handled_invalidation_version) + int64_t highest_handled_invalidation_version, + bool is_fcm_enabled) : state_(UNINITIALIZED), type_(type), core_(core), @@ -55,6 +61,7 @@ highest_handled_invalidation_version), max_fetch_delay_(kMaxFetchDelayDefault), policy_hash_value_(0), + is_fcm_enabled_(is_fcm_enabled), weak_factory_(this) { DCHECK(core); DCHECK(task_runner.get()); @@ -132,6 +139,10 @@ std::string CloudPolicyInvalidator::GetOwnerName() const { return "Cloud"; } +bool CloudPolicyInvalidator::IsPublicTopic(const syncer::Topic& topic) const { + return base::StringPiece(topic).starts_with(kFcmPolicyPublicTopicPrefix); +} + void CloudPolicyInvalidator::OnCoreConnected(CloudPolicyCore* core) {} void CloudPolicyInvalidator::OnRefreshSchedulerStarted(CloudPolicyCore* core) { @@ -275,16 +286,31 @@ void CloudPolicyInvalidator::UpdateRegistration( const enterprise_management::PolicyData* policy) { // Create the ObjectId based on the policy data. - // If the policy does not specify an the ObjectId, then unregister. - if (!policy || - !policy->has_invalidation_source() || - !policy->has_invalidation_name()) { + if (!policy) { Unregister(); return; } - invalidation::ObjectId object_id( - policy->invalidation_source(), - policy->invalidation_name()); + + // If the policy does not specify an ObjectId, then unregister. + invalidation::ObjectId object_id; + if (is_fcm_enabled_) { + if (!policy->has_policy_invalidation_topic() || + policy->policy_invalidation_topic().empty()) { + Unregister(); + return; + } + object_id = invalidation::ObjectId(syncer::kDeprecatedSourceForFCM, + policy->policy_invalidation_topic()); + } else { + if (!policy->has_invalidation_source() || + !policy->has_invalidation_name() || + policy->invalidation_name().empty()) { + Unregister(); + return; + } + object_id = invalidation::ObjectId(policy->invalidation_source(), + policy->invalidation_name()); + } // If the policy object id in the policy data is different from the currently // registered object id, update the object registration.
diff --git a/chrome/browser/policy/cloud/cloud_policy_invalidator.h b/chrome/browser/policy/cloud/cloud_policy_invalidator.h index 9da9400..ccbf9614 100644 --- a/chrome/browser/policy/cloud/cloud_policy_invalidator.h +++ b/chrome/browser/policy/cloud/cloud_policy_invalidator.h
@@ -75,7 +75,8 @@ CloudPolicyCore* core, const scoped_refptr<base::SequencedTaskRunner>& task_runner, base::Clock* clock, - int64_t highest_handled_invalidation_version); + int64_t highest_handled_invalidation_version, + bool is_fcm_enabled); ~CloudPolicyInvalidator() override; // Initializes the invalidator. No invalidations will be generated before this @@ -93,6 +94,10 @@ return invalidations_enabled_; } + // Whether to use FCM (Firebase Cloud Messaging) topics when registering + // to invalidations. + bool is_fcm_enabled() { return is_fcm_enabled_; } + // The highest invalidation version that was handled already. int64_t highest_handled_invalidation_version() const { return highest_handled_invalidation_version_; @@ -107,6 +112,7 @@ void OnIncomingInvalidation( const syncer::ObjectIdInvalidationMap& invalidation_map) override; std::string GetOwnerName() const override; + bool IsPublicTopic(const syncer::Topic& topic) const override; // CloudPolicyCore::Observer: void OnCoreConnected(CloudPolicyCore* core) override; @@ -237,6 +243,10 @@ // policy is different from the current one. uint32_t policy_hash_value_; + // Whether the CloudPolicyInvalidator should use FCM (Firebase Cloud + // Messaging) topics. + const bool is_fcm_enabled_; + // A thread checker to make sure that callbacks are invoked on the correct // thread. base::ThreadChecker thread_checker_;
diff --git a/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc b/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc index f056d4b..8f76ce2 100644 --- a/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc +++ b/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc
@@ -42,7 +42,19 @@ namespace policy { -class CloudPolicyInvalidatorTest : public testing::Test { +namespace { + +struct TestParams { + const bool is_fcm_enabled; + const em::DeviceRegisterRequest::Type policy_type; + + TestParams(bool is_fcm_enabled, em::DeviceRegisterRequest::Type policy_type) + : is_fcm_enabled(is_fcm_enabled), policy_type(std::move(policy_type)) {} +}; + +} // namespace + +class CloudPolicyInvalidatorTestBase : public testing::Test { protected: // Policy objects which can be used in tests. enum PolicyObject { @@ -51,7 +63,7 @@ POLICY_OBJECT_B }; - CloudPolicyInvalidatorTest(); + explicit CloudPolicyInvalidatorTestBase(bool is_fcm_enabled); void TearDown() override; @@ -175,6 +187,10 @@ // Get the policy type that the |invalidator_| is responsible for. virtual em::DeviceRegisterRequest::Type GetPolicyType() const; + // if true FCMInvalidationService is used as InvalidationService and + // TiclInvalidationService otherwise. + const bool is_fcm_enabled_; + private: // Checks that the policy was refreshed due to an invalidation with the given // base delay. @@ -212,36 +228,45 @@ const char* policy_value_cur_; }; -CloudPolicyInvalidatorTest::CloudPolicyInvalidatorTest() - : core_(dm_protocol::kChromeUserPolicyType, +CloudPolicyInvalidatorTestBase::CloudPolicyInvalidatorTestBase( + bool is_fcm_enabled) + : is_fcm_enabled_(is_fcm_enabled), + core_(dm_protocol::kChromeUserPolicyType, std::string(), &store_, loop_.task_runner(), network::TestNetworkConnectionTracker::CreateGetter()), client_(nullptr), task_runner_(new base::TestSimpleTaskRunner()), - object_id_a_(135, "asdf"), - object_id_b_(246, "zxcv"), policy_value_a_("asdf"), policy_value_b_("zxcv"), policy_value_cur_(policy_value_a_) { + if (is_fcm_enabled_) { + object_id_a_ = + invalidation::ObjectId(syncer::kDeprecatedSourceForFCM, "asdf"); + object_id_b_ = + invalidation::ObjectId(syncer::kDeprecatedSourceForFCM, "zxcv"); + } else { + object_id_a_ = invalidation::ObjectId(135, "asdf"); + object_id_b_ = invalidation::ObjectId(246, "zxcv"); + } clock_.SetNow(base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(987654321)); } -void CloudPolicyInvalidatorTest::TearDown() { +void CloudPolicyInvalidatorTestBase::TearDown() { if (invalidator_) invalidator_->Shutdown(); core_.Disconnect(); } -void CloudPolicyInvalidatorTest::StartInvalidator( +void CloudPolicyInvalidatorTestBase::StartInvalidator( bool initialize, bool start_refresh_scheduler, int64_t highest_handled_invalidation_version) { - invalidator_.reset( - new CloudPolicyInvalidator(GetPolicyType(), &core_, task_runner_, &clock_, - highest_handled_invalidation_version)); + invalidator_.reset(new CloudPolicyInvalidator( + GetPolicyType(), &core_, task_runner_, &clock_, + highest_handled_invalidation_version, is_fcm_enabled_)); if (start_refresh_scheduler) { ConnectCore(); StartRefreshScheduler(); @@ -250,41 +275,45 @@ InitializeInvalidator(); } -void CloudPolicyInvalidatorTest::InitializeInvalidator() { +void CloudPolicyInvalidatorTestBase::InitializeInvalidator() { invalidator_->Initialize(&invalidation_service_); } -void CloudPolicyInvalidatorTest::ShutdownInvalidator() { +void CloudPolicyInvalidatorTestBase::ShutdownInvalidator() { invalidator_->Shutdown(); } -void CloudPolicyInvalidatorTest::DestroyInvalidator() { +void CloudPolicyInvalidatorTestBase::DestroyInvalidator() { invalidator_.reset(); } -void CloudPolicyInvalidatorTest::ConnectCore() { +void CloudPolicyInvalidatorTestBase::ConnectCore() { client_ = new MockCloudPolicyClient(); client_->SetDMToken("dm"); core_.Connect(std::unique_ptr<CloudPolicyClient>(client_)); } -void CloudPolicyInvalidatorTest::StartRefreshScheduler() { +void CloudPolicyInvalidatorTestBase::StartRefreshScheduler() { core_.StartRefreshScheduler(); } -void CloudPolicyInvalidatorTest::DisconnectCore() { +void CloudPolicyInvalidatorTestBase::DisconnectCore() { client_ = nullptr; core_.Disconnect(); } -void CloudPolicyInvalidatorTest::StorePolicy(PolicyObject object, - int64_t invalidation_version, - bool policy_changed, - const base::Time& time) { +void CloudPolicyInvalidatorTestBase::StorePolicy(PolicyObject object, + int64_t invalidation_version, + bool policy_changed, + const base::Time& time) { em::PolicyData* data = new em::PolicyData(); if (object != POLICY_OBJECT_NONE) { data->set_invalidation_source(GetPolicyObjectId(object).source()); data->set_invalidation_name(GetPolicyObjectId(object).name()); + // When FCM is enabled CloudPolicyInvalidator expects the name in this + // field. + if (is_fcm_enabled_) + data->set_policy_invalidation_topic(GetPolicyObjectId(object).name()); } data->set_timestamp(time.ToJavaTime()); // Swap the policy value if a policy change is desired. @@ -306,16 +335,16 @@ store_.NotifyStoreLoaded(); } -void CloudPolicyInvalidatorTest::DisableInvalidationService() { +void CloudPolicyInvalidatorTestBase::DisableInvalidationService() { invalidation_service_.SetInvalidatorState( syncer::TRANSIENT_INVALIDATION_ERROR); } -void CloudPolicyInvalidatorTest::EnableInvalidationService() { +void CloudPolicyInvalidatorTestBase::EnableInvalidationService() { invalidation_service_.SetInvalidatorState(syncer::INVALIDATIONS_ENABLED); } -syncer::Invalidation CloudPolicyInvalidatorTest::FireInvalidation( +syncer::Invalidation CloudPolicyInvalidatorTestBase::FireInvalidation( PolicyObject object, int64_t version, const std::string& payload) { @@ -327,7 +356,8 @@ return invalidation; } -syncer::Invalidation CloudPolicyInvalidatorTest::FireUnknownVersionInvalidation( +syncer::Invalidation +CloudPolicyInvalidatorTestBase::FireUnknownVersionInvalidation( PolicyObject object) { syncer::Invalidation invalidation = syncer::Invalidation::InitUnknownVersion( GetPolicyObjectId(object)); @@ -335,7 +365,7 @@ return invalidation; } -bool CloudPolicyInvalidatorTest::CheckInvalidationInfo( +bool CloudPolicyInvalidatorTestBase::CheckInvalidationInfo( int64_t version, const std::string& payload) { MockCloudPolicyClient* client = @@ -344,29 +374,29 @@ payload == client->invalidation_payload_; } -bool CloudPolicyInvalidatorTest::CheckPolicyNotRefreshed() { +bool CloudPolicyInvalidatorTestBase::CheckPolicyNotRefreshed() { return CheckPolicyRefreshCount(0); } -bool CloudPolicyInvalidatorTest::CheckPolicyRefreshed() { +bool CloudPolicyInvalidatorTestBase::CheckPolicyRefreshed() { return CheckPolicyRefreshed(base::TimeDelta()); } -bool CloudPolicyInvalidatorTest::IsUnsent( +bool CloudPolicyInvalidatorTestBase::IsUnsent( const syncer::Invalidation& invalidation) { return invalidation_service_.GetMockAckHandler()->IsUnsent(invalidation); } -bool CloudPolicyInvalidatorTest::CheckPolicyRefreshedWithUnknownVersion() { +bool CloudPolicyInvalidatorTestBase::CheckPolicyRefreshedWithUnknownVersion() { return CheckPolicyRefreshed(base::TimeDelta::FromMinutes( CloudPolicyInvalidator::kMissingPayloadDelay)); } -bool CloudPolicyInvalidatorTest::InvalidationsEnabled() { +bool CloudPolicyInvalidatorTestBase::InvalidationsEnabled() { return core_.refresh_scheduler()->invalidations_available(); } -bool CloudPolicyInvalidatorTest::IsInvalidationAcknowledged( +bool CloudPolicyInvalidatorTestBase::IsInvalidationAcknowledged( const syncer::Invalidation& invalidation) { // The acknowledgement task is run through a WeakHandle that posts back to our // own thread. We need to run any posted tasks before we can check @@ -377,38 +407,39 @@ return !invalidation_service_.GetMockAckHandler()->IsUnacked(invalidation); } -bool CloudPolicyInvalidatorTest::IsInvalidatorRegistered() { +bool CloudPolicyInvalidatorTestBase::IsInvalidatorRegistered() { return !invalidation_service_.invalidator_registrar() .GetRegisteredIds(invalidator_.get()).empty(); } -int64_t CloudPolicyInvalidatorTest::GetHighestHandledInvalidationVersion() +int64_t CloudPolicyInvalidatorTestBase::GetHighestHandledInvalidationVersion() const { return invalidator_->highest_handled_invalidation_version(); } -void CloudPolicyInvalidatorTest::AdvanceClock(base::TimeDelta delta) { +void CloudPolicyInvalidatorTestBase::AdvanceClock(base::TimeDelta delta) { clock_.Advance(delta); } -base::Time CloudPolicyInvalidatorTest::Now() { +base::Time CloudPolicyInvalidatorTestBase::Now() { return clock_.Now(); } -int64_t CloudPolicyInvalidatorTest::V(int version) { +int64_t CloudPolicyInvalidatorTestBase::V(int version) { return GetVersion(Now()) + version; } -int64_t CloudPolicyInvalidatorTest::GetVersion(base::Time time) { +int64_t CloudPolicyInvalidatorTestBase::GetVersion(base::Time time) { return (time - base::Time::UnixEpoch()).InMicroseconds(); } -em::DeviceRegisterRequest::Type -CloudPolicyInvalidatorTest::GetPolicyType() const { +em::DeviceRegisterRequest::Type CloudPolicyInvalidatorTestBase::GetPolicyType() + const { return UserCloudPolicyInvalidator::GetPolicyType(); } -bool CloudPolicyInvalidatorTest::CheckPolicyRefreshed(base::TimeDelta delay) { +bool CloudPolicyInvalidatorTestBase::CheckPolicyRefreshed( + base::TimeDelta delay) { base::TimeDelta max_delay = delay + base::TimeDelta::FromMilliseconds( CloudPolicyInvalidator::kMaxFetchDelayMin); @@ -421,7 +452,7 @@ return CheckPolicyRefreshCount(1); } -bool CloudPolicyInvalidatorTest::CheckPolicyRefreshCount(int count) { +bool CloudPolicyInvalidatorTestBase::CheckPolicyRefreshCount(int count) { if (!client_) { task_runner_->RunUntilIdle(); return count == 0; @@ -439,13 +470,22 @@ return testing::Mock::VerifyAndClearExpectations(client_); } -const invalidation::ObjectId& CloudPolicyInvalidatorTest::GetPolicyObjectId( +const invalidation::ObjectId& CloudPolicyInvalidatorTestBase::GetPolicyObjectId( PolicyObject object) const { EXPECT_TRUE(object == POLICY_OBJECT_A || object == POLICY_OBJECT_B); return object == POLICY_OBJECT_A ? object_id_a_ : object_id_b_; } -TEST_F(CloudPolicyInvalidatorTest, Uninitialized) { +class CloudPolicyInvalidatorTest : public CloudPolicyInvalidatorTestBase, + public testing::WithParamInterface<bool> { + protected: + CloudPolicyInvalidatorTest(); +}; + +CloudPolicyInvalidatorTest::CloudPolicyInvalidatorTest() + : CloudPolicyInvalidatorTestBase(GetParam() /* is_fcm_enabled */) {} + +TEST_P(CloudPolicyInvalidatorTest, Uninitialized) { // No invalidations should be processed if the invalidator is not initialized. StartInvalidator(false, /* initialize */ true, /* start_refresh_scheduler */ @@ -457,7 +497,7 @@ EXPECT_EQ(0, GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, RefreshSchedulerNotStarted) { +TEST_P(CloudPolicyInvalidatorTest, RefreshSchedulerNotStarted) { // No invalidations should be processed if the refresh scheduler is not // started. StartInvalidator(true, /* initialize */ @@ -470,7 +510,7 @@ EXPECT_EQ(0, GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, DisconnectCoreThenInitialize) { +TEST_P(CloudPolicyInvalidatorTest, DisconnectCoreThenInitialize) { // No invalidations should be processed if the core is disconnected before // initialization. StartInvalidator(false, /* initialize */ @@ -485,7 +525,7 @@ EXPECT_EQ(0, GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, InitializeThenStartRefreshScheduler) { +TEST_P(CloudPolicyInvalidatorTest, InitializeThenStartRefreshScheduler) { // Make sure registration occurs and invalidations are processed when // Initialize is called before starting the refresh scheduler. // Note that the reverse case (start refresh scheduler then initialize) is @@ -503,7 +543,7 @@ EXPECT_EQ(0, GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, RegisterOnStoreLoaded) { +TEST_P(CloudPolicyInvalidatorTest, RegisterOnStoreLoaded) { // No registration when store is not loaded. StartInvalidator(); EXPECT_FALSE(IsInvalidatorRegistered()); @@ -531,7 +571,7 @@ EXPECT_EQ(0, GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, ChangeRegistration) { +TEST_P(CloudPolicyInvalidatorTest, ChangeRegistration) { // Register for object A. StartInvalidator(); StorePolicy(POLICY_OBJECT_A); @@ -560,7 +600,7 @@ EXPECT_EQ(0, GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, UnregisterOnStoreLoaded) { +TEST_P(CloudPolicyInvalidatorTest, UnregisterOnStoreLoaded) { // Register for object A. StartInvalidator(); StorePolicy(POLICY_OBJECT_A); @@ -589,7 +629,7 @@ EXPECT_EQ(0, GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, HandleInvalidation) { +TEST_P(CloudPolicyInvalidatorTest, HandleInvalidation) { // Register and fire invalidation StorePolicy(POLICY_OBJECT_A); StartInvalidator(); @@ -611,7 +651,7 @@ EXPECT_EQ(V(12), GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, HandleInvalidationWithUnknownVersion) { +TEST_P(CloudPolicyInvalidatorTest, HandleInvalidationWithUnknownVersion) { // Register and fire invalidation with unknown version. StorePolicy(POLICY_OBJECT_A); StartInvalidator(); @@ -631,7 +671,7 @@ EXPECT_EQ(0, GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, HandleMultipleInvalidations) { +TEST_P(CloudPolicyInvalidatorTest, HandleMultipleInvalidations) { // Generate multiple invalidations. StorePolicy(POLICY_OBJECT_A); StartInvalidator(); @@ -663,7 +703,7 @@ EXPECT_EQ(V(3), GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, +TEST_P(CloudPolicyInvalidatorTest, HandleMultipleInvalidationsWithUnknownVersion) { // Validate that multiple invalidations with unknown version each generate // unique invalidation version numbers. @@ -697,7 +737,7 @@ EXPECT_EQ(0, GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, +TEST_P(CloudPolicyInvalidatorTest, InitialHighestHandledInvalidationVersionNonZero) { StorePolicy(POLICY_OBJECT_A); StartInvalidator(true, /* initialize */ @@ -738,7 +778,7 @@ EXPECT_EQ(V(3), GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, AcknowledgeBeforeRefresh) { +TEST_P(CloudPolicyInvalidatorTest, AcknowledgeBeforeRefresh) { // Generate an invalidation. StorePolicy(POLICY_OBJECT_A); StartInvalidator(); @@ -754,7 +794,7 @@ EXPECT_EQ(V(3), GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, NoCallbackAfterShutdown) { +TEST_P(CloudPolicyInvalidatorTest, NoCallbackAfterShutdown) { // Generate an invalidation. StorePolicy(POLICY_OBJECT_A); StartInvalidator(); @@ -768,7 +808,7 @@ DestroyInvalidator(); } -TEST_F(CloudPolicyInvalidatorTest, StateChanged) { +TEST_P(CloudPolicyInvalidatorTest, StateChanged) { // Test invalidation service state changes while not registered. StartInvalidator(); DisableInvalidationService(); @@ -806,7 +846,7 @@ EXPECT_EQ(0, GetHighestHandledInvalidationVersion()); } -TEST_F(CloudPolicyInvalidatorTest, Disconnect) { +TEST_P(CloudPolicyInvalidatorTest, Disconnect) { // Generate an invalidation. StorePolicy(POLICY_OBJECT_A); StartInvalidator(); @@ -846,9 +886,13 @@ EXPECT_EQ(0, GetHighestHandledInvalidationVersion()); } +INSTANTIATE_TEST_SUITE_P(FCMEnabledAndFCMDisabled, + CloudPolicyInvalidatorTest, + testing::Bool() /* is_fcm_enabled */); + class CloudPolicyInvalidatorUserTypedTest - : public CloudPolicyInvalidatorTest, - public testing::WithParamInterface<em::DeviceRegisterRequest::Type> { + : public CloudPolicyInvalidatorTestBase, + public testing::WithParamInterface<TestParams> { protected: CloudPolicyInvalidatorUserTypedTest(); virtual ~CloudPolicyInvalidatorUserTypedTest(); @@ -877,8 +921,8 @@ DISALLOW_COPY_AND_ASSIGN(CloudPolicyInvalidatorUserTypedTest); }; -CloudPolicyInvalidatorUserTypedTest::CloudPolicyInvalidatorUserTypedTest() { -} +CloudPolicyInvalidatorUserTypedTest::CloudPolicyInvalidatorUserTypedTest() + : CloudPolicyInvalidatorTestBase(GetParam().is_fcm_enabled) {} CloudPolicyInvalidatorUserTypedTest::~CloudPolicyInvalidatorUserTypedTest() { } @@ -911,7 +955,7 @@ em::DeviceRegisterRequest::Type CloudPolicyInvalidatorUserTypedTest::GetPolicyType() const { - return GetParam(); + return GetParam().policy_type; } std::unique_ptr<base::HistogramSamples> @@ -1084,19 +1128,32 @@ } #if defined(OS_CHROMEOS) -INSTANTIATE_TEST_SUITE_P(CloudPolicyInvalidatorUserTypedTestInstance, - CloudPolicyInvalidatorUserTypedTest, - testing::Values(em::DeviceRegisterRequest::USER, - em::DeviceRegisterRequest::DEVICE)); +INSTANTIATE_TEST_SUITE_P( + CloudPolicyInvalidatorUserTypedTestInstance, + CloudPolicyInvalidatorUserTypedTest, + testing::Values( + TestParams(false /* is_fcm_enabled */, em::DeviceRegisterRequest::USER), + TestParams(true /* is_fcm_enabled */, em::DeviceRegisterRequest::USER), + TestParams(false /* is_fcm_enabled */, + em::DeviceRegisterRequest::DEVICE), + TestParams(true /* is_fcm_enabled */, + em::DeviceRegisterRequest::DEVICE))); #elif defined(OS_ANDROID) INSTANTIATE_TEST_SUITE_P( CloudPolicyInvalidatorUserTypedTestInstance, CloudPolicyInvalidatorUserTypedTest, - testing::Values(em::DeviceRegisterRequest::ANDROID_BROWSER)); + testing::Values(TestParams(false /* is_fcm_enabled */, + em::DeviceRegisterRequest::ANDROID_BROWSER), + TestParams(true /* is_fcm_enabled */, + em::DeviceRegisterRequest::ANDROID_BROWSER))); #else -INSTANTIATE_TEST_SUITE_P(CloudPolicyInvalidatorUserTypedTestInstance, - CloudPolicyInvalidatorUserTypedTest, - testing::Values(em::DeviceRegisterRequest::BROWSER)); +INSTANTIATE_TEST_SUITE_P( + CloudPolicyInvalidatorUserTypedTestInstance, + CloudPolicyInvalidatorUserTypedTest, + testing::Values(TestParams(false /* is_fcm_enabled */, + em::DeviceRegisterRequest::BROWSER), + TestParams(true /* is_fcm_enabled */, + em::DeviceRegisterRequest::BROWSER))); #endif } // namespace policy
diff --git a/chrome/browser/policy/cloud/user_cloud_policy_invalidator.cc b/chrome/browser/policy/cloud/user_cloud_policy_invalidator.cc index ac26099..8bc8e5b4 100644 --- a/chrome/browser/policy/cloud/user_cloud_policy_invalidator.cc +++ b/chrome/browser/policy/cloud/user_cloud_policy_invalidator.cc
@@ -12,21 +12,41 @@ #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.h" +#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" #include "components/invalidation/impl/profile_invalidation_provider.h" #include "components/policy/core/common/cloud/cloud_policy_manager.h" #include "content/public/browser/notification_source.h" +namespace { + +invalidation::ProfileInvalidationProvider* GetInvalidationProvider( + Profile* profile, + bool is_fcm_enabled) { + if (is_fcm_enabled) { + return invalidation::ProfileInvalidationProviderFactory::GetForProfile( + profile); + } + return invalidation::DeprecatedProfileInvalidationProviderFactory:: + GetForProfile(profile); +} + +} // namespace + namespace policy { UserCloudPolicyInvalidator::UserCloudPolicyInvalidator( Profile* profile, - CloudPolicyManager* policy_manager) + CloudPolicyManager* policy_manager, + bool is_fcm_enabled, + std::string fcm_sender_id) : CloudPolicyInvalidator(GetPolicyType(), policy_manager->core(), base::ThreadTaskRunnerHandle::Get(), base::DefaultClock::GetInstance(), - 0 /* highest_handled_invalidation_version */), - profile_(profile) { + 0 /* highest_handled_invalidation_version */, + is_fcm_enabled), + profile_(profile), + fcm_sender_id_(std::move(fcm_sender_id)) { DCHECK(profile); // Register for notification that profile creation is complete. The @@ -65,10 +85,15 @@ // service can safely be initialized. DCHECK_EQ(chrome::NOTIFICATION_PROFILE_ADDED, type); invalidation::ProfileInvalidationProvider* invalidation_provider = - invalidation::DeprecatedProfileInvalidationProviderFactory::GetForProfile( - profile_); - if (invalidation_provider) + GetInvalidationProvider(profile_, is_fcm_enabled()); + if (!invalidation_provider) + return; + if (is_fcm_enabled()) { + Initialize(invalidation_provider->GetInvalidationServiceForCustomSender( + fcm_sender_id_)); + } else { Initialize(invalidation_provider->GetInvalidationService()); + } } } // namespace policy
diff --git a/chrome/browser/policy/cloud/user_cloud_policy_invalidator.h b/chrome/browser/policy/cloud/user_cloud_policy_invalidator.h index 0a69c0f..038e69d 100644 --- a/chrome/browser/policy/cloud/user_cloud_policy_invalidator.h +++ b/chrome/browser/policy/cloud/user_cloud_policy_invalidator.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_POLICY_CLOUD_USER_CLOUD_POLICY_INVALIDATOR_H_ #define CHROME_BROWSER_POLICY_CLOUD_USER_CLOUD_POLICY_INVALIDATOR_H_ +#include <string> + #include "base/macros.h" #include "chrome/browser/policy/cloud/cloud_policy_invalidator.h" #include "components/keyed_service/core/keyed_service.h" @@ -28,10 +30,13 @@ // a reference to the profile's invalidation service. Both the profile and // invalidation service must remain valid until Shutdown is called. // |policy_manager| is the policy manager for the user policy and must remain - // valid until Shutdown is called. - UserCloudPolicyInvalidator( - Profile* profile, - CloudPolicyManager* policy_manager); + // valid until Shutdown is called. |is_fcm_enabled| is the flag denoting + // FCM is being used as InvalidationService. |fcm_sender_id| is the id of + // FCM Policy Invalidation sender coming from Firebase console. + UserCloudPolicyInvalidator(Profile* profile, + CloudPolicyManager* policy_manager, + bool is_fcm_enabled, + std::string fcm_sender_id); static enterprise_management::DeviceRegisterRequest::Type GetPolicyType(); @@ -50,6 +55,9 @@ // Used to register for notification that profile creation is complete. content::NotificationRegistrar registrar_; + // Sender ID coming from the Firebase console. + const std::string fcm_sender_id_; + DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyInvalidator); };
diff --git a/chrome/browser/policy/cloud/user_cloud_policy_invalidator_factory.cc b/chrome/browser/policy/cloud/user_cloud_policy_invalidator_factory.cc index 87d71f6..1e782098 100644 --- a/chrome/browser/policy/cloud/user_cloud_policy_invalidator_factory.cc +++ b/chrome/browser/policy/cloud/user_cloud_policy_invalidator_factory.cc
@@ -4,11 +4,15 @@ #include "chrome/browser/policy/cloud/user_cloud_policy_invalidator_factory.h" +#include "base/feature_list.h" #include "build/build_config.h" #include "chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.h" +#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" #include "chrome/browser/policy/cloud/user_cloud_policy_invalidator.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/common/chrome_features.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/policy/core/common/cloud/cloud_policy_constants.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" #else @@ -29,6 +33,7 @@ BrowserContextDependencyManager::GetInstance()) { DependsOn(invalidation::DeprecatedProfileInvalidationProviderFactory:: GetInstance()); + DependsOn(invalidation::ProfileInvalidationProviderFactory::GetInstance()); } UserCloudPolicyInvalidatorFactory::~UserCloudPolicyInvalidatorFactory() {} @@ -45,7 +50,10 @@ if (!policy_manager) return NULL; - return new UserCloudPolicyInvalidator(profile, policy_manager); + return new UserCloudPolicyInvalidator( + profile, policy_manager, + base::FeatureList::IsEnabled(features::kPolicyFcmInvalidations), + policy::kPolicyFCMInvalidationSenderID); } bool UserCloudPolicyInvalidatorFactory::
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index ab4c61d..21457c6 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -610,9 +610,6 @@ { key::kStickyKeysEnabled, ash::prefs::kAccessibilityStickyKeysEnabled, base::Value::Type::BOOLEAN }, - { key::kDockedMagnifierEnabled, - ash::prefs::kDockedMagnifierEnabled, - base::Value::Type::BOOLEAN }, { key::kDeviceLoginScreenDefaultLargeCursorEnabled, nullptr, base::Value::Type::BOOLEAN }, @@ -1409,7 +1406,7 @@ key::kUptimeLimit, prefs::kUptimeLimit, 3600, INT_MAX, true)); handlers->AddHandler(std::make_unique<IntRangePolicyHandler>( key::kDeviceLoginScreenDefaultScreenMagnifierType, nullptr, - chromeos::MAGNIFIER_DISABLED, chromeos::MAGNIFIER_FULL, false)); + chromeos::MAGNIFIER_DISABLED, chromeos::MAGNIFIER_DOCKED, false)); // TODO(binjin): Remove LegacyPoliciesDeprecatingPolicyHandler for these two // policies once deprecation of legacy power management policies is done. // http://crbug.com/346229
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 17d06fe..41d2cf6 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -3940,6 +3940,9 @@ // Verify that the screen magnifier cannot be enabled manually anymore. magnification_manager->SetMagnifierEnabled(true); EXPECT_FALSE(magnification_manager->IsMagnifierEnabled()); + // Verify that the docked magnifier cannot be enabled manually anymore. + magnification_manager->SetDockedMagnifierEnabled(true); + EXPECT_FALSE(magnification_manager->IsDockedMagnifierEnabled()); } IN_PROC_BROWSER_TEST_F(PolicyTest, ScreenMagnifierTypeFull) { @@ -3964,6 +3967,29 @@ EXPECT_TRUE(magnification_manager->IsMagnifierEnabled()); } +IN_PROC_BROWSER_TEST_F(PolicyTest, ScreenMagnifierTypeDocked) { + // Verifies that the docked magnifier accessibility feature can be + // controlled through policy. + chromeos::MagnificationManager* magnification_manager = + chromeos::MagnificationManager::Get(); + + // Verify that the docked magnifier is initially disabled + EXPECT_FALSE(magnification_manager->IsDockedMagnifierEnabled()); + + // Verify that policy overrides the manual setting. + PolicyMap policies; + policies.Set(key::kScreenMagnifierType, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, + std::make_unique<base::Value>(chromeos::MAGNIFIER_DOCKED), + nullptr); + UpdateProviderPolicy(policies); + EXPECT_TRUE(magnification_manager->IsDockedMagnifierEnabled()); + + // Verify that the docked magnifier cannot be disabled manually anymore. + magnification_manager->SetDockedMagnifierEnabled(false); + EXPECT_TRUE(magnification_manager->IsDockedMagnifierEnabled()); +} + IN_PROC_BROWSER_TEST_F(PolicyTest, AccessibilityVirtualKeyboardEnabled) { // Verifies that the on-screen keyboard accessibility feature can be // controlled through policy. @@ -4013,31 +4039,6 @@ EXPECT_FALSE(accessibility_manager->IsStickyKeysEnabled()); } -IN_PROC_BROWSER_TEST_F(PolicyTest, DockedMagnifierEnabled) { - // Verifies that the docked magnifier accessibility feature can be - // controlled through policy. - chromeos::MagnificationManager* magnification_manager = - chromeos::MagnificationManager::Get(); - - // Verify that the docked magnifier is initially disabled - EXPECT_FALSE(magnification_manager->IsDockedMagnifierEnabled()); - - // Manually enable the docked magnifier. - magnification_manager->SetDockedMagnifierEnabled(true); - EXPECT_TRUE(magnification_manager->IsDockedMagnifierEnabled()); - - // Verify that policy overrides the manual setting. - PolicyMap policies; - policies.Set(key::kDockedMagnifierEnabled, POLICY_LEVEL_MANDATORY, - POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, - std::make_unique<base::Value>(false), nullptr); - UpdateProviderPolicy(policies); - EXPECT_FALSE(magnification_manager->IsDockedMagnifierEnabled()); - - // Verify that the docked magnifier cannot be enabled manually anymore. - magnification_manager->SetDockedMagnifierEnabled(true); - EXPECT_FALSE(magnification_manager->IsDockedMagnifierEnabled()); -} IN_PROC_BROWSER_TEST_F(PolicyTest, VirtualKeyboardEnabled) { auto* keyboard_client = ChromeKeyboardControllerClient::Get();
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index fc3b400..2d69e32 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -62,6 +62,7 @@ #include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h" #include "chrome/browser/search/local_ntp_first_run_field_trial_handler.h" #include "chrome/browser/search/search.h" +#include "chrome/browser/sharing/sharing_sync_preference.h" #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h" #include "chrome/browser/ssl/ssl_config_service_manager.h" #include "chrome/browser/task_manager/task_manager_interface.h" @@ -301,6 +302,7 @@ #include "chromeos/services/multidevice_setup/multidevice_setup_service.h" #include "chromeos/timezone/timezone_resolver.h" #include "components/arc/arc_prefs.h" +#include "components/invalidation/impl/fcm_invalidation_service.h" #include "components/invalidation/impl/invalidator_storage.h" #include "components/onc/onc_pref_names.h" #include "components/quirks/quirks_manager.h" @@ -618,6 +620,7 @@ extensions::ExtensionAssetsManagerChromeOS::RegisterPrefs(registry); extensions::lock_screen_data::LockScreenItemStorage::RegisterLocalState( registry); + invalidation::FCMInvalidationService::RegisterPrefs(registry); invalidation::InvalidatorStorage::RegisterPrefs(registry); ::onc::RegisterPrefs(registry); policy::AutoEnrollmentClientImpl::RegisterPrefs(registry); @@ -631,6 +634,8 @@ policy::WebUsbAllowDevicesForUrlsPolicyHandler::RegisterPrefs(registry); quirks::QuirksManager::RegisterPrefs(registry); UpgradeDetectorChromeos::RegisterPrefs(registry); + syncer::PerUserTopicRegistrationManager::RegisterPrefs(registry); + syncer::InvalidatorRegistrarWithMemory::RegisterPrefs(registry); #endif #if defined(OS_MACOSX) @@ -719,6 +724,7 @@ safe_browsing::RegisterProfilePrefs(registry); SafeBrowsingTriggeredPopupBlocker::RegisterProfilePrefs(registry); SessionStartupPref::RegisterProfilePrefs(registry); + SharingSyncPreference::RegisterProfilePrefs(registry); sync_sessions::SessionSyncPrefs::RegisterProfilePrefs(registry); syncer::SyncPrefs::RegisterProfilePrefs(registry); syncer::PerUserTopicRegistrationManager::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision.html b/chrome/browser/resources/chromeos/add_supervision/add_supervision.html index 55ac2da2..a1d0917 100644 --- a/chrome/browser/resources/chromeos/add_supervision/add_supervision.html +++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision.html
@@ -17,6 +17,8 @@ html, body { height: 100%; + overflow: auto; + overflow-y: hidden; } </style> </head>
diff --git a/chrome/browser/resources/chromeos/login/cr_ui.js b/chrome/browser/resources/chromeos/login/cr_ui.js index 81edcba..07ee6f21 100644 --- a/chrome/browser/resources/chromeos/login/cr_ui.js +++ b/chrome/browser/resources/chromeos/login/cr_ui.js
@@ -342,11 +342,10 @@ * attribute screen if it's present. */ Oobe.isEnrollmentSuccessfulForTest = function() { - if (document.querySelector('.oauth-enroll-state-attribute-prompt')) + if ($('enterprise-enrollment').$$('.oauth-enroll-state-attribute-prompt')) chrome.send('oauthEnrollAttributes', ['', '']); - return $('oauth-enrollment') - .classList.contains('oauth-enroll-state-success'); + return !!$('enterprise-enrollment').$$('.oauth-enroll-state-success'); }; /**
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_login.html b/chrome/browser/resources/chromeos/login/custom_elements_login.html index 0770d227..280f17d 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_login.html +++ b/chrome/browser/resources/chromeos/login/custom_elements_login.html
@@ -24,6 +24,8 @@ <include src="oobe_reset_confirmation_overlay.html"> <include src="oobe_supervision_transition.html"> <include src="encryption_migration.html"> +<include src="enrollment_license_card.html"> +<include src="enterprise_enrollment.html"> <include src="sync_consent.html"> <include src="fingerprint_setup.html"> <include src="recommend_apps.html">
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_login.js b/chrome/browser/resources/chromeos/login/custom_elements_login.js index a400a60..93c1d26 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_login.js +++ b/chrome/browser/resources/chromeos/login/custom_elements_login.js
@@ -39,3 +39,5 @@ // <include src="../assistant_optin/assistant_optin_flow.js"> // <include src="multidevice_setup_first_run.js"> // <include src="supervision_onboarding.js"> +// <include src="enrollment_license_card.js"> +// <include src="enterprise_enrollment.js">
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html index 4e7ca93..618f0cc 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html +++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
@@ -34,6 +34,7 @@ <include src="active_directory_password_change.html"> <include src="arc_terms_of_service.html"> <include src="enrollment_license_card.html"> +<include src="enterprise_enrollment.html"> <include src="sync_consent.html"> <include src="fingerprint_setup.html"> <include src="demo_setup.html">
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js index 7eeeca0f..b91be2ea 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js +++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
@@ -45,6 +45,7 @@ // <include src="arc_terms_of_service.js"> // <include src="oobe_supervision_transition.js"> // <include src="enrollment_license_card.js"> +// <include src="enterprise_enrollment.js"> // <include src="sync_consent.js"> // <include src="fingerprint_setup.js"> // <include src="demo_setup.js">
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css b/chrome/browser/resources/chromeos/login/enterprise_enrollment.css similarity index 93% rename from chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css rename to chrome/browser/resources/chromeos/login/enterprise_enrollment.css index cd1296b..d532e10f 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css +++ b/chrome/browser/resources/chromeos/login/enterprise_enrollment.css
@@ -2,16 +2,18 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#oauth-enrollment { - height: 640px; +:host { padding: 0; - width: 768px; } -#oauth-enrollment.saml { +:host(.saml) #oauth-enroll-step-contents { padding-top: 44px; } +:host(:not(.saml)) #oauth-saml-notice-container { + display: none; +} + #oauth-enroll-step-contents { color: #666; height: 100%; @@ -91,10 +93,6 @@ top: 0; } -#oauth-enrollment:not(.saml) #oauth-saml-notice-container { - display: none; -} - #oauth-saml-notice-message { color: rgb(106, 106, 106); font-size: 13px;
diff --git a/chrome/browser/resources/chromeos/login/enterprise_enrollment.html b/chrome/browser/resources/chromeos/login/enterprise_enrollment.html new file mode 100644 index 0000000..3db3a2a --- /dev/null +++ b/chrome/browser/resources/chromeos/login/enterprise_enrollment.html
@@ -0,0 +1,140 @@ +<!-- Copyright 2015 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<link rel="import" href="chrome://oobe/custom_elements.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> +<link rel="stylesheet" href="gaia_card_parameters.css"> + +<dom-module id="enterprise-enrollment"> + <template> + <div id="oauth-enroll-step-contents"> + <link rel="stylesheet" href="oobe_flex_layout.css"> + <link rel="stylesheet" href="oobe_dialog_host.css"> + <link rel="stylesheet" href="enterprise_enrollment.css"> + <div id="oauth-enroll-step-signin"> + <oobe-dialog class="gaia-dialog" role="dialog" + id="enrollment-gaia-dialog" has-buttons no-header + no-footer-padding> + <div slot="footer" class="flex layout vertical"> + <webview id="oauth-enroll-auth-view" + name="oauth-enroll-auth-view"> + </webview> + </div> + <div slot="bottom-buttons" + class="flex layout horizontal center self-start"> + <oobe-back-button id="oobe-signin-back-button"></oobe-back-button> + </div> + </oobe-dialog> + </div> + <div id="oauth-enroll-step-working"> + <oobe-dialog id="oauth-enroll-working"> + <hd-iron-icon slot="oobe-icon" + icon1x="oobe-enrollment-32:briefcase" + icon2x="oobe-enrollment-64:briefcase"> + </hd-iron-icon> + <h1 slot="title" i18n-content="oauthEnrollScreenTitle"></h1> + <paper-progress slot="progress" indeterminate> + </paper-progress> + + <div slot="footer" class="flex layout vertical" role="alert"> + <div class="oauth-enroll-step-message"> + <span i18n-content="oauthEnrollWorking"></span> + </div> + </div> + </oobe-dialog> + </div> + <div id="oauth-enroll-step-license"> + <enrollment-license-card id="oauth-enroll-license-ui" + i18n-values="button-text:oauthEnrollNextBtn"> + </enrollment-license-card> + </div> + <div id="oauth-enroll-step-ad-join"> + <offline-ad-login id="oauth-enroll-ad-join-ui" is-domain-join + class="fit" i18n-values= + "ad-welcome-message:oauthEnrollAdDomainJoinWelcomeMessage"> + </offline-ad-login> + </div> + <div id="oauth-enroll-step-error" role="alert"> + <notification-card id="oauth-enroll-error-card" type="fail" + i18n-values="button-label:oauthEnrollRetry"> + </notification-card> + </div> + <div id="oauth-enroll-step-success" role="alert"> + <oobe-dialog id="oauth-enroll-success-card" has-buttons> + <hd-iron-icon slot="oobe-icon" + icon1x="oobe-enrollment-32:briefcase" + icon2x="oobe-enrollment-64:briefcase"></hd-iron-icon> + <h1 slot="title" i18n-content="oauthEnrollSuccessTitle"></h1> + <oobe-enrollment-success-with-domain + id="oauth-enroll-success-subtitle" + slot="subtitle"> + </oobe-enrollment-success-with-domain> + <div slot="footer" class="flex layout vertical center end-justified"> + <img srcset="images/enrollment_success_illustration_1x.png 1x, + images/enrollment_success_illustration_2x.png 2x" + i18n-values="alt:enrollmentSuccessIllustrationTitle"> + </div> + <div slot="bottom-buttons" class="layout horizontal end-justified"> + <oobe-text-button inverse id="enroll-success-done-button" + class="focus-on-show"> + <div i18n-content="oauthEnrollDone"></div> + </oobe-text-button> + </div> + </oobe-dialog> + </div> + <div id="oauth-enroll-step-attribute-prompt"> + <oobe-dialog id="oauth-enroll-attribute-prompt-card" has-buttons> + <hd-iron-icon slot="oobe-icon" + icon1x="oobe-enrollment-32:briefcase" + icon2x="oobe-enrollment-64:briefcase"></hd-iron-icon> + <h1 slot="title" i18n-content="oauthEnrollScreenTitle"></h1> + <div slot="subtitle" i18n-content="oauthEnrollDeviceInformation"> + </div> + <div slot="footer" class="layout vertical start"> + <div class="oauth-enroll-step-message"> + <span id="oauth-enroll-attribute-prompt-message" + i18n-content="oauthEnrollAttributeExplanation"> + </span> + <a href="#" id="oauth-enroll-learn-more-link" + class="oauth-enroll-link" + i18n-content="oauthEnrollExplainAttributeLink"></a> + </div> + <gaia-input id="oauth-enroll-asset-id" type="text" + class="focus-on-show"> + <div slot="label" i18n-content="oauthEnrollAssetIdLabel"> + </div> + </gaia-input> + <gaia-input id="oauth-enroll-location" type="text"> + <div slot="label" i18n-content="oauthEnrollLocationLabel"> + </div> + </gaia-input> + </div> + <div slot="bottom-buttons" class="layout horizontal end-justified"> + <oobe-text-button id="enroll-attributes-skip-button"> + <div i18n-content="oauthEnrollSkip"></div> + </oobe-text-button> + <div class="flex"></div> + <oobe-next-button + id="enroll-attributes-submit-button"></oobe-next-button> + </div> + </oobe-dialog> + </div> + <div id="oauth-enroll-step-attribute-prompt-error"> + <notification-card id="oauth-enroll-attribute-prompt-error-card" + type="fail" i18n-values="button-label:oauthEnrollDone"> + </notification-card> + </div> + <div id="oauth-enroll-step-active-directory-join-error"> + <notification-card id="oauth-enroll-active-directory-join-error-card" + type="fail" i18n-values="button-label:oauthEnrollRetry"> + </notification-card> + </div> + </div> + <div id="oauth-saml-notice-container"> + <span id="oauth-saml-notice-message"></span> + </div> + <navigation-bar id="oauth-enroll-navigation"></navigation-bar> + </template> +</dom-module>
diff --git a/chrome/browser/resources/chromeos/login/enterprise_enrollment.js b/chrome/browser/resources/chromeos/login/enterprise_enrollment.js new file mode 100644 index 0000000..cca50da --- /dev/null +++ b/chrome/browser/resources/chromeos/login/enterprise_enrollment.js
@@ -0,0 +1,551 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Polymer element for Enterprise Enrollment screen. + */ + +/* Code which is embedded inside of the webview. See below for details. +/** @const */ +var INJECTED_WEBVIEW_SCRIPT = String.raw` + (function() { + // <include src="../keyboard/keyboard_utils.js"> + keyboard.initializeKeyboardFlow(true); + })();`; + +/** @const */ var ENROLLMENT_STEP = { + SIGNIN: 'signin', + AD_JOIN: 'ad-join', + LICENSE_TYPE: 'license', + WORKING: 'working', + ATTRIBUTE_PROMPT: 'attribute-prompt', + ERROR: 'error', + SUCCESS: 'success', + + /* TODO(dzhioev): define this step on C++ side. + */ + ATTRIBUTE_PROMPT_ERROR: 'attribute-prompt-error', + ACTIVE_DIRECTORY_JOIN_ERROR: 'active-directory-join-error', +}; + +Polymer({ + is: 'enterprise-enrollment', + + behaviors: [I18nBehavior, OobeDialogHostBehavior], + + properties: { + /** + * Reference to OOBE screen object. + * @type {!{ + * onAuthFrameLoaded_: function(), + * onAuthCompleted_: function(string), + * onAdCompleteLogin_: function(string, string, string, string, string), + * onAdUnlockConfiguration_: function(string), + * onLicenseTypeSelected_: function(string), + * closeEnrollment_: function(string), + * onAttributesEntered_: function(string, string), + * }} + */ + screen: { + type: Object, + }, + }, + + /** + * Authenticator object that wraps GAIA webview. + */ + authenticator_: null, + + /** + * The current step. This is the last value passed to showStep(). + */ + currentStep_: null, + + /** + * We block esc, back button and cancel button until gaia is loaded to + * prevent multiple cancel events. + */ + isCancelDisabled_: null, + + get isCancelDisabled() { + return this.isCancelDisabled_; + }, + set isCancelDisabled(disabled) { + this.isCancelDisabled_ = disabled; + }, + + isManualEnrollment_: undefined, + + /** + * An element containing UI for picking license type. + * @type {EnrollmentLicenseCard} + * @private + */ + licenseUi_: undefined, + + /** + * An element containing navigation buttons. + */ + navigation_: undefined, + + /** + * An element containing UI to join an AD domain. + * @type {OfflineAdLoginElement} + * @private + */ + offlineAdUi_: undefined, + + /** + * Value contained in the last received 'backButton' event. + * @type {boolean} + * @private + */ + lastBackMessageValue_: false, + + ready: function() { + this.navigation_ = this.$['oauth-enroll-navigation']; + this.offlineAdUi_ = this.$['oauth-enroll-ad-join-ui']; + this.licenseUi_ = this.$['oauth-enroll-license-ui']; + + let authView = this.$['oauth-enroll-auth-view']; + this.authenticator_ = new cr.login.Authenticator(authView); + + // Establish an initial messaging between content script and + // host script so that content script can message back. + authView.addEventListener('loadstop', function(e) { + e.target.contentWindow.postMessage( + 'initialMessage', authView.src); + }); + + // When we get the advancing focus command message from injected content + // script, we can execute it on host script context. + window.addEventListener('message', function(e) { + if (e.data == 'forwardFocus') + keyboard.onAdvanceFocus(false); + else if (e.data == 'backwardFocus') + keyboard.onAdvanceFocus(true); + }); + + this.authenticator_.addEventListener( + 'ready', (function() { + if (this.currentStep_ != ENROLLMENT_STEP.SIGNIN) + return; + this.isCancelDisabled = false; + this.screen.onAuthFrameLoaded_(); + }).bind(this)); + + this.authenticator_.addEventListener( + 'authCompleted', + (function(e) { + var detail = e.detail; + if (!detail.email) { + this.showError( + loadTimeData.getString('fatalEnrollmentError'), false); + return; + } + this.screen.onAuthCompleted_(detail.email); + }).bind(this)); + + this.offlineAdUi_.addEventListener('authCompleted', function(e) { + this.offlineAdUi_.disabled = true; + this.offlineAdUi_.loading = true; + this.screen.onAdCompleteLogin_( + e.detail.machine_name, + e.detail.distinguished_name, + e.detail.encryption_types, + e.detail.username, + e.detail.password); + }.bind(this)); + this.offlineAdUi_.addEventListener('unlockPasswordEntered', function(e) { + this.offlineAdUi_.disabled = true; + this.screen.onAdUnlockConfiguration_(e.detail.unlock_password); + }.bind(this)); + + this.authenticator_.addEventListener( + 'authFlowChange', (function(e) { + var isSAML = this.authenticator_.authFlow == + cr.login.Authenticator.AuthFlow.SAML; + if (isSAML) { + this.$['oauth-saml-notice-message'].textContent = + loadTimeData.getStringF( + 'samlNotice', + this.authenticator_.authDomain); + } + this.classList.toggle('saml', isSAML); + if (Oobe.getInstance().currentScreen == this) + Oobe.getInstance().updateScreenSize(this); + this.lastBackMessageValue_ = false; + this.updateControlsState(); + }).bind(this)); + + this.authenticator_.addEventListener( + 'backButton', (function(e) { + this.lastBackMessageValue_ = !!e.detail; + this.$['oauth-enroll-auth-view'].focus(); + this.updateControlsState(); + }).bind(this)); + + this.authenticator_.addEventListener( + 'dialogShown', (function(e) { + this.navigation_.disabled = true; + this.$['oobe-signin-back-button'].disabled = true; + // TODO(alemate): update the visual style. + }).bind(this)); + + this.authenticator_.addEventListener( + 'dialogHidden', (function(e) { + this.navigation_.disabled = false; + this.$['oobe-signin-back-button'].disabled = false; + // TODO(alemate): update the visual style. + }).bind(this)); + + this.authenticator_.insecureContentBlockedCallback = + (function(url) { + this.showError( + loadTimeData.getStringF('insecureURLEnrollmentError', url), + false); + }).bind(this); + + this.authenticator_.missingGaiaInfoCallback = + (function() { + this.showError( + loadTimeData.getString('fatalEnrollmentError'), false); + }).bind(this); + + this.$['oauth-enroll-error-card'] + .addEventListener('buttonclick', this.doRetry_.bind(this)); + + this.$['oauth-enroll-attribute-prompt-error-card'] + .addEventListener( + 'buttonclick', this.onEnrollmentFinished_.bind(this)); + + this.$['enroll-success-done-button'] + .addEventListener('tap', this.onEnrollmentFinished_.bind(this)); + + this.$['enroll-attributes-skip-button'] + .addEventListener('tap', this.onSkipButtonClicked.bind(this)); + this.$['enroll-attributes-submit-button'] + .addEventListener('tap', this.onAttributesSubmitted.bind(this)); + + + this.$['oauth-enroll-active-directory-join-error-card'] + .addEventListener('buttonclick', function() { + this.showStep(ENROLLMENT_STEP.AD_JOIN); + }.bind(this)); + + this.navigation_.addEventListener('close', this.cancel.bind(this)); + this.navigation_.addEventListener('refresh', this.cancel.bind(this)); + + this.$['oobe-signin-back-button'] + .addEventListener('tap', this.onBackButtonClicked_.bind(this)); + + + this.$['oauth-enroll-learn-more-link'] + .addEventListener('click', function(event) { + chrome.send('oauthEnrollOnLearnMore'); + }); + + + this.licenseUi_.addEventListener('buttonclick', function() { + this.screen.onLicenseTypeSelected_(this.licenseUi_.selected); + }.bind(this)); + }, + + /** + * Event handler that is invoked just before the frame is shown. + * @param {Object} data Screen init payload, contains the signin frame + * URL. + */ + onBeforeShow: function(data) { + if (Oobe.getInstance().forceKeyboardFlow) { + // We run the tab remapping logic inside of the webview so that the + // simulated tab events will use the webview tab-stops. Simulated tab + // events created from the webui treat the entire webview as one tab + // stop. Real tab events do not do this. See crbug.com/543865. + this.$['oauth-enroll-auth-view'].addContentScripts([{ + name: 'injectedTabHandler', + matches: ['http://*/*', 'https://*/*'], + js: {code: INJECTED_WEBVIEW_SCRIPT}, + run_at: 'document_start' + }]); + } + + this.$['oauth-enroll-auth-view'].partition = data.webviewPartitionName; + + Oobe.getInstance().setSigninUIState(SIGNIN_UI_STATE.ENROLLMENT); + this.classList.remove('saml'); + + var gaiaParams = {}; + gaiaParams.gaiaUrl = data.gaiaUrl; + gaiaParams.clientId = data.clientId; + gaiaParams.needPassword = false; + gaiaParams.hl = data.hl; + if (data.management_domain) { + gaiaParams.enterpriseEnrollmentDomain = data.management_domain; + gaiaParams.emailDomain = data.management_domain; + } + gaiaParams.flow = data.flow; + this.authenticator_.load( + cr.login.Authenticator.AuthMode.DEFAULT, gaiaParams); + + var modes = ['manual', 'forced', 'recovery']; + for (var i = 0; i < modes.length; ++i) { + this.classList.toggle( + 'mode-' + modes[i], data.enrollment_mode == modes[i]); + } + this.isManualEnrollment_ = data.enrollment_mode === 'manual'; + this.navigation_.disabled = false; + + this.offlineAdUi_.onBeforeShow(); + if (!this.currentStep_) { + this.showStep(data.attestationBased ? + ENROLLMENT_STEP.WORKING : ENROLLMENT_STEP.SIGNIN); + } + this.behaviors.forEach((behavior) => { + if (behavior.onBeforeShow) + behavior.onBeforeShow.call(this); + }); + }, + + onBeforeHide: function() { + Oobe.getInstance().setSigninUIState(SIGNIN_UI_STATE.HIDDEN); + }, + + /** + * Shows attribute-prompt step with pre-filled asset ID and + * location. + */ + showAttributePromptStep: function(annotatedAssetId, annotatedLocation) { + this.$['oauth-enroll-asset-id'].value = annotatedAssetId; + this.$['oauth-enroll-location'].value = annotatedLocation; + this.showStep(ENROLLMENT_STEP.ATTRIBUTE_PROMPT); + }, + + /** + * Shows a success card for attestation-based enrollment that shows + * which domain the device was enrolled into. + */ + showAttestationBasedEnrollmentSuccess: function( + device, enterpriseEnrollmentDomain) { + this.$['oauth-enroll-success-subtitle'].deviceName = device; + this.$['oauth-enroll-success-subtitle'].enrollmentDomain = + enterpriseEnrollmentDomain; + this.showStep(ENROLLMENT_STEP.SUCCESS); + }, + + /** + * Cancels the current authentication and drops the user back to the next + * screen (either the next authentication or the login screen). + */ + cancel: function() { + if (this.isCancelDisabled) + return; + this.isCancelDisabled = true; + this.screen.closeEnrollment_('cancel'); + }, + + /** + * Updates the list of available license types in license selection dialog. + */ + setAvailableLicenseTypes: function(licenseTypes) { + var licenses = [ + { + id: 'perpetual', + label: 'perpetualLicenseTypeTitle', + }, + { + id: 'annual', + label: 'annualLicenseTypeTitle', + }, + { + id: 'kiosk', + label: 'kioskLicenseTypeTitle', + } + ]; + for (var i = 0, item; item = licenses[i]; ++i) { + if (item.id in licenseTypes) { + item.count = parseInt(licenseTypes[item.id]); + item.disabled = item.count == 0; + item.hidden = false; + } else { + item.count = 0; + item.disabled = true; + item.hidden = true; + } + } + this.licenseUi_.disabled = false; + this.licenseUi_.licenses = licenses; + }, + + /** + * Switches between the different steps in the enrollment flow. + * @param {string} step the steps to show, one of "signin", "working", + * "attribute-prompt", "error", "success". + */ + showStep: function(step) { + let classList = this.$['oauth-enroll-step-contents'].classList; + classList.toggle('oauth-enroll-state-' + this.currentStep_, false); + classList.toggle('oauth-enroll-state-' + step, true); + + this.isCancelDisabled = + (step == ENROLLMENT_STEP.SIGNIN && !this.isManualEnrollment_) || + step == ENROLLMENT_STEP.AD_JOIN || step == ENROLLMENT_STEP.WORKING; + if (step == ENROLLMENT_STEP.SIGNIN) { + this.$['oauth-enroll-auth-view'].focus(); + } else if (step == ENROLLMENT_STEP.LICENSE_TYPE) { + this.$['oauth-enroll-license-ui'].show(); + } else if (step == ENROLLMENT_STEP.ERROR) { + this.$['oauth-enroll-error-card'].submitButton.focus(); + } else if (step == ENROLLMENT_STEP.SUCCESS) { + this.$['oauth-enroll-success-card'].show(); + } else if (step == ENROLLMENT_STEP.ATTRIBUTE_PROMPT) { + this.$['oauth-enroll-attribute-prompt-card'].show(); + } else if (step == ENROLLMENT_STEP.ATTRIBUTE_PROMPT_ERROR) { + this.$['oauth-enroll-attribute-prompt-error-card'].submitButton.focus(); + } else if (step == ENROLLMENT_STEP.ACTIVE_DIRECTORY_JOIN_ERROR) { + this.$['oauth-enroll-active-directory-join-error-card'].submitButton + .focus(); + } else if (step == ENROLLMENT_STEP.AD_JOIN) { + this.offlineAdUi_.disabled = false; + this.offlineAdUi_.loading = false; + this.offlineAdUi_.focus(); + } + + this.currentStep_ = step; + this.lastBackMessageValue_ = false; + this.updateControlsState(); + }, + + /** + * Sets an error message and switches to the error screen. + * @param {string} message the error message. + * @param {boolean} retry whether the retry link should be shown. + */ + showError: function(message, retry) { + if (this.currentStep_ == ENROLLMENT_STEP.ATTRIBUTE_PROMPT) { + this.$['oauth-enroll-attribute-prompt-error-card'].textContent = message; + this.showStep(ENROLLMENT_STEP.ATTRIBUTE_PROMPT_ERROR); + return; + } + if (this.currentStep_ == ENROLLMENT_STEP.AD_JOIN) { + this.$['oauth-enroll-active-directory-join-error-card'].textContent = + message; + this.showStep(ENROLLMENT_STEP.ACTIVE_DIRECTORY_JOIN_ERROR); + return; + } + this.$['oauth-enroll-error-card'].textContent = message; + this.$['oauth-enroll-error-card'].buttonLabel = + retry ? loadTimeData.getString('oauthEnrollRetry') : ''; + this.showStep(ENROLLMENT_STEP.ERROR); + }, + + doReload: function() { + this.lastBackMessageValue_ = false; + this.authenticator_.reload(); + this.updateControlsState(); + }, + + /** + * Sets Active Directory join screen params. + * @param {string} machineName + * @param {string} userName + * @param {ACTIVE_DIRECTORY_ERROR_STATE} errorState + * @param {boolean} showUnlockConfig true if there is an encrypted + * configuration (and not unlocked yet). + */ + setAdJoinParams: function( + machineName, userName, errorState, showUnlockConfig) { + this.offlineAdUi_.disabled = false; + this.offlineAdUi_.machineName = machineName; + this.offlineAdUi_.userName = userName; + this.offlineAdUi_.errorState = errorState; + this.offlineAdUi_.unlockPasswordStep = showUnlockConfig; + }, + + /** + * Sets Active Directory join screen with the unlocked configuration. + * @param {Array<JoinConfigType>} options + */ + setAdJoinConfiguration: function(options) { + this.offlineAdUi_.disabled = false; + this.offlineAdUi_.setJoinConfigurationOptions(options); + this.offlineAdUi_.unlockPasswordStep = false; + }, + + /** + * Retries the enrollment process after an error occurred in a previous + * attempt. This goes to the C++ side through |chrome| first to clean up the + * profile, so that the next attempt is performed with a clean state. + */ + doRetry_: function() { + chrome.send('oauthEnrollRetry'); + }, + + /** + * Skips the device attribute update, + * shows the successful enrollment step. + */ + onSkipButtonClicked: function() { + this.showStep(ENROLLMENT_STEP.SUCCESS); + }, + + /** + * Skips the device attribute update, + * shows the successful enrollment step. + */ + onBackButtonClicked_: function() { + if (this.currentStep_ == ENROLLMENT_STEP.SIGNIN) { + if (this.lastBackMessageValue_) { + this.lastBackMessageValue_ = false; + this.$['oauth-enroll-auth-view'].back(); + } else { + this.cancel(); + } + } + }, + + + /** + * Uploads the device attributes to server. This goes to C++ side through + * |chrome| and launches the device attribute update negotiation. + */ + onAttributesSubmitted: function() { + this.screen.onAttributesEntered_(this.$['oauth-enroll-asset-id'].value, + this.$['oauth-enroll-location'].value); + }, + + /** + * Returns true if we are at the begging of enrollment flow (i.e. the email + * page). + * + * @type {boolean} + */ + isAtTheBeginning: function() { + return !this.lastBackMessageValue_ && + this.currentStep_ == ENROLLMENT_STEP.SIGNIN; + }, + + /** + * Updates visibility of navigation buttons. + */ + updateControlsState: function() { + this.navigation_.refreshVisible = this.isAtTheBeginning() && + this.isManualEnrollment_ === false; + this.navigation_.closeVisible = + (this.currentStep_ == ENROLLMENT_STEP.ERROR + && !this.navigation_.refreshVisible) || + this.currentStep_ == ENROLLMENT_STEP.LICENSE_TYPE; + }, + + /** + * Notifies chrome that enrollment have finished. + */ + onEnrollmentFinished_: function() { + this.screen.closeEnrollment_('done'); + }, + + updateLocalizedContent: function() { + this.offlineAdUi_.i18nUpdateLocale(); + } +});
diff --git a/chrome/browser/resources/chromeos/login/md_login.html b/chrome/browser/resources/chromeos/login/md_login.html index 844aba8..7ba5cf9 100644 --- a/chrome/browser/resources/chromeos/login/md_login.html +++ b/chrome/browser/resources/chromeos/login/md_login.html
@@ -57,7 +57,6 @@ <link rel="stylesheet" href="oobe_screen_terms_of_service.css"> <link rel="stylesheet" href="oobe_screen_auto_enrollment_check.css"> <link rel="stylesheet" href="oobe_screen_supervision_transition.css"> -<link rel="stylesheet" href="oobe_screen_oauth_enrollment.css"> <link rel="stylesheet" href="screen_app_launch_splash.css"> <link rel="stylesheet" href="screen_arc_kiosk_splash.css"> <link rel="stylesheet" href="screen_arc_terms_of_service.css">
diff --git a/chrome/browser/resources/chromeos/login/oobe.html b/chrome/browser/resources/chromeos/login/oobe.html index 3ad80e1..48bfbaa 100644 --- a/chrome/browser/resources/chromeos/login/oobe.html +++ b/chrome/browser/resources/chromeos/login/oobe.html
@@ -62,7 +62,6 @@ <link rel="stylesheet" href="oobe_screen_terms_of_service.css"> <link rel="stylesheet" href="oobe_screen_auto_enrollment_check.css"> <link rel="stylesheet" href="oobe_screen_supervision_transition.css"> -<link rel="stylesheet" href="oobe_screen_oauth_enrollment.css"> <link rel="stylesheet" href="screen_app_launch_splash.css"> <link rel="stylesheet" href="screen_arc_kiosk_splash.css">
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.html b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.html index 7df1bcd..3d59747 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.html +++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.html
@@ -5,126 +5,7 @@ <link rel="import" href="chrome://oobe/custom_elements.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> -<link rel="stylesheet" href="gaia_card_parameters.css"> <div id="oauth-enrollment" class="step hidden" hidden> - <div id="oauth-enroll-step-contents"> - <link rel="stylesheet" href="oobe_flex_layout.css"> - <div id="oauth-enroll-step-signin"> - <oobe-dialog class="gaia-dialog" role="dialog" id="enrollment-gaia-dialog" - has-buttons no-header no-footer-padding> - <div slot="footer" class="flex layout vertical"> - <webview id="oauth-enroll-auth-view" name="oauth-enroll-auth-view"> - </webview> - </div> - <div slot="bottom-buttons" - class="flex layout horizontal center self-start"> - <oobe-back-button id="oobe-signin-back-button"></oobe-back-button> - </div> - </oobe-dialog> - </div> - <div id="oauth-enroll-step-working"> - <oobe-dialog id="oauth-enroll-working"> - <hd-iron-icon slot="oobe-icon" - icon1x="oobe-enrollment-32:briefcase" - icon2x="oobe-enrollment-64:briefcase"></hd-iron-icon> - <h1 slot="title" i18n-content="oauthEnrollScreenTitle"></h1> - <paper-progress slot="progress" indeterminate> - </paper-progress> - - <div slot="footer" class="flex layout vertical" role="alert"> - <div class="oauth-enroll-step-message"> - <span i18n-content="oauthEnrollWorking"></span> - </div> - </div> - </oobe-dialog> - </div> - <div id="oauth-enroll-step-license"> - <enrollment-license-card id="oauth-enroll-license-ui" - i18n-values="button-text:oauthEnrollNextBtn"> - </enrollment-license-card> - </div> - <div id="oauth-enroll-step-ad-join"> - <offline-ad-login id="oauth-enroll-ad-join-ui" is-domain-join - class="fit" i18n-values= - "ad-welcome-message:oauthEnrollAdDomainJoinWelcomeMessage"> - </offline-ad-login> - </div> - <div id="oauth-enroll-step-error" role="alert"> - <notification-card id="oauth-enroll-error-card" type="fail" - i18n-values="button-label:oauthEnrollRetry"> - </notification-card> - </div> - <div id="oauth-enroll-step-success" role="alert"> - <oobe-dialog id="oauth-enroll-success-card" has-buttons> - <hd-iron-icon slot="oobe-icon" - icon1x="oobe-enrollment-32:briefcase" - icon2x="oobe-enrollment-64:briefcase"></hd-iron-icon> - <h1 slot="title" i18n-content="oauthEnrollSuccessTitle"></h1> - <oobe-enrollment-success-with-domain id="oauth-enroll-success-subtitle" - slot="subtitle"> - </oobe-enrollment-success-with-domain> - <div slot="footer" class="flex layout vertical center end-justified"> - <img srcset="images/enrollment_success_illustration_1x.png 1x, - images/enrollment_success_illustration_2x.png 2x" - i18n-values="alt:enrollmentSuccessIllustrationTitle"> - </div> - <div slot="bottom-buttons" class="layout horizontal end-justified"> - <oobe-text-button inverse id="enroll-success-done-button" - class="focus-on-show"> - <div i18n-content="oauthEnrollDone"></div> - </oobe-text-button> - </div> - </oobe-dialog> - </div> - <div id="oauth-enroll-step-attribute-prompt"> - <oobe-dialog id="oauth-enroll-attribute-prompt-card" has-buttons> - <hd-iron-icon slot="oobe-icon" - icon1x="oobe-enrollment-32:briefcase" - icon2x="oobe-enrollment-64:briefcase"></hd-iron-icon> - <h1 slot="title" i18n-content="oauthEnrollScreenTitle"></h1> - <div slot="subtitle" i18n-content="oauthEnrollDeviceInformation"></div> - <div slot="footer" class="layout vertical start"> - <div class="oauth-enroll-step-message"> - <span id="oauth-enroll-attribute-prompt-message" - i18n-content="oauthEnrollAttributeExplanation"></span> - <a href="#" id="oauth-enroll-learn-more-link" - class="oauth-enroll-link" - i18n-content="oauthEnrollExplainAttributeLink"></a> - </div> - <gaia-input id="oauth-enroll-asset-id" type="text" - class="focus-on-show"> - <div slot="label" i18n-content="oauthEnrollAssetIdLabel"> - </div> - </gaia-input> - <gaia-input id="oauth-enroll-location" type="text"> - <div slot="label" i18n-content="oauthEnrollLocationLabel"> - </div> - </gaia-input> - </div> - <div slot="bottom-buttons" class="layout horizontal end-justified"> - <oobe-text-button id="enroll-attributes-skip-button"> - <div i18n-content="oauthEnrollSkip"></div> - </oobe-text-button> - <div class="flex"></div> - <oobe-next-button - id="enroll-attributes-submit-button"></oobe-next-button> - </div> - </oobe-dialog> - </div> - <div id="oauth-enroll-step-attribute-prompt-error"> - <notification-card id="oauth-enroll-attribute-prompt-error-card" - type="fail" i18n-values="button-label:oauthEnrollDone"> - </notification-card> - </div> - <div id="oauth-enroll-step-active-directory-join-error"> - <notification-card id="oauth-enroll-active-directory-join-error-card" - type="fail" i18n-values="button-label:oauthEnrollRetry"> - </notification-card> - </div> - </div> - <div id="oauth-saml-notice-container"> - <span id="oauth-saml-notice-message"></span> - </div> - <navigation-bar id="oauth-enroll-navigation"></navigation-bar> + <enterprise-enrollment id="enterprise-enrollment"></enterprise-enrollment> </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js index 868ec34..c0c9e4e 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js
@@ -3,26 +3,6 @@ // found in the LICENSE file. login.createScreen('OAuthEnrollmentScreen', 'oauth-enrollment', function() { - /* Code which is embedded inside of the webview. See below for details. - /** @const */ var INJECTED_WEBVIEW_SCRIPT = String.raw` - (function() { - // <include src="../keyboard/keyboard_utils.js"> - keyboard.initializeKeyboardFlow(true); - })();`; - - /** @const */ var STEP_SIGNIN = 'signin'; - /** @const */ var STEP_AD_JOIN = 'ad-join'; - /** @const */ var STEP_LICENSE_TYPE = 'license'; - /** @const */ var STEP_WORKING = 'working'; - /** @const */ var STEP_ATTRIBUTE_PROMPT = 'attribute-prompt'; - /** @const */ var STEP_ERROR = 'error'; - /** @const */ var STEP_SUCCESS = 'success'; - - /* TODO(dzhioev): define this step on C++ side. - /** @const */ var STEP_ATTRIBUTE_PROMPT_ERROR = 'attribute-prompt-error'; - /** @const */ var STEP_ACTIVE_DIRECTORY_JOIN_ERROR = - 'active-directory-join-error'; - return { EXTERNAL_API: [ 'showStep', @@ -36,257 +16,23 @@ ], /** - * Authenticator object that wraps GAIA webview. + * Returns the control which should receive initial focus. */ - authenticator_: null, - - /** - * The current step. This is the last value passed to showStep(). - */ - currentStep_: null, - - /** - * We block esc, back button and cancel button until gaia is loaded to - * prevent multiple cancel events. - */ - isCancelDisabled_: null, - - get isCancelDisabled() { - return this.isCancelDisabled_; - }, - set isCancelDisabled(disabled) { - this.isCancelDisabled_ = disabled; + get defaultControl() { + return $('enterprise-enrollment'); }, - isManualEnrollment_: undefined, - /** - * An element containing UI for picking license type. - * @type {EnrollmentLicenseCard} - * @private + * This is called after resources are updated. */ - licenseUi_: undefined, + updateLocalizedContent: function() { + $('enterprise-enrollment').updateLocalizedContent(); + }, - /** - * An element containg navigation buttons. - */ - navigation_: undefined, - - /** - * An element containing UI to join an AD domain. - * @type {OfflineAdLoginElement} - * @private - */ - offlineAdUi_: undefined, - - /** - * Value contained in the last received 'backButton' event. - * @type {boolean} - * @private - */ - lastBackMessageValue_: false, /** @override */ decorate: function() { - this.navigation_ = $('oauth-enroll-navigation'); - this.offlineAdUi_ = $('oauth-enroll-ad-join-ui'); - this.licenseUi_ = $('oauth-enroll-license-ui'); - - this.authenticator_ = - new cr.login.Authenticator($('oauth-enroll-auth-view')); - - // Establish an initial messaging between content script and - // host script so that content script can message back. - $('oauth-enroll-auth-view').addEventListener('loadstop', function(e) { - e.target.contentWindow.postMessage( - 'initialMessage', $('oauth-enroll-auth-view').src); - }); - - // When we get the advancing focus command message from injected content - // script, we can execute it on host script context. - window.addEventListener('message', function(e) { - if (e.data == 'forwardFocus') - keyboard.onAdvanceFocus(false); - else if (e.data == 'backwardFocus') - keyboard.onAdvanceFocus(true); - }); - - this.authenticator_.addEventListener( - 'ready', (function() { - if (this.currentStep_ != STEP_SIGNIN) - return; - this.isCancelDisabled = false; - chrome.send('frameLoadingCompleted'); - }).bind(this)); - - this.authenticator_.addEventListener( - 'authCompleted', - (function(e) { - var detail = e.detail; - if (!detail.email) { - this.showError( - loadTimeData.getString('fatalEnrollmentError'), false); - return; - } - chrome.send('oauthEnrollCompleteLogin', [detail.email]); - }).bind(this)); - - this.offlineAdUi_.addEventListener('authCompleted', function(e) { - this.offlineAdUi_.disabled = true; - this.offlineAdUi_.loading = true; - chrome.send('oauthEnrollAdCompleteLogin', [ - e.detail.machine_name, e.detail.distinguished_name, - e.detail.encryption_types, e.detail.username, e.detail.password - ]); - }.bind(this)); - this.offlineAdUi_.addEventListener('unlockPasswordEntered', function(e) { - this.offlineAdUi_.disabled = true; - chrome.send( - 'oauthEnrollAdUnlockConfiguration', [e.detail.unlock_password]); - }.bind(this)); - - this.authenticator_.addEventListener( - 'authFlowChange', (function(e) { - var isSAML = this.authenticator_.authFlow == - cr.login.Authenticator.AuthFlow.SAML; - if (isSAML) { - $('oauth-saml-notice-message').textContent = - loadTimeData.getStringF( - 'samlNotice', - this.authenticator_.authDomain); - } - this.classList.toggle('saml', isSAML); - if (Oobe.getInstance().currentScreen == this) - Oobe.getInstance().updateScreenSize(this); - this.lastBackMessageValue_ = false; - this.updateControlsState(); - }).bind(this)); - - this.authenticator_.addEventListener( - 'backButton', (function(e) { - this.lastBackMessageValue_ = !!e.detail; - $('oauth-enroll-auth-view').focus(); - this.updateControlsState(); - }).bind(this)); - - this.authenticator_.addEventListener( - 'dialogShown', (function(e) { - this.navigation_.disabled = true; - $('oobe-signin-back-button').disabled = true; - // TODO(alemate): update the visual style. - }).bind(this)); - - this.authenticator_.addEventListener( - 'dialogHidden', (function(e) { - this.navigation_.disabled = false; - $('oobe-signin-back-button').disabled = false; - // TODO(alemate): update the visual style. - }).bind(this)); - - this.authenticator_.insecureContentBlockedCallback = - (function(url) { - this.showError( - loadTimeData.getStringF('insecureURLEnrollmentError', url), - false); - }).bind(this); - - this.authenticator_.missingGaiaInfoCallback = - (function() { - this.showError( - loadTimeData.getString('fatalEnrollmentError'), false); - }).bind(this); - - $('oauth-enroll-error-card') - .addEventListener('buttonclick', this.doRetry_.bind(this)); - - $('oauth-enroll-attribute-prompt-error-card') - .addEventListener( - 'buttonclick', this.onEnrollmentFinished_.bind(this)); - - $('enroll-success-done-button') - .addEventListener('tap', this.onEnrollmentFinished_.bind(this)); - - $('enroll-attributes-skip-button') - .addEventListener('tap', this.onSkipButtonClicked.bind(this)); - $('enroll-attributes-submit-button') - .addEventListener('tap', this.onAttributesSubmitted.bind(this)); - - - $('oauth-enroll-active-directory-join-error-card') - .addEventListener('buttonclick', function() { - this.showStep(STEP_AD_JOIN); - }.bind(this)); - - this.navigation_.addEventListener('close', this.cancel.bind(this)); - this.navigation_.addEventListener('refresh', this.cancel.bind(this)); - - $('oobe-signin-back-button') - .addEventListener('tap', this.onBackButtonClicked_.bind(this)); - - - $('oauth-enroll-learn-more-link') - .addEventListener('click', function(event) { - chrome.send('oauthEnrollOnLearnMore'); - }); - - - this.licenseUi_.addEventListener('buttonclick', function() { - chrome.send('onLicenseTypeSelected', [this.licenseUi_.selected]); - }.bind(this)); - }, - - /** - * Event handler that is invoked just before the frame is shown. - * @param {Object} data Screen init payload, contains the signin frame - * URL. - */ - onBeforeShow: function(data) { - if (Oobe.getInstance().forceKeyboardFlow) { - // We run the tab remapping logic inside of the webview so that the - // simulated tab events will use the webview tab-stops. Simulated tab - // events created from the webui treat the entire webview as one tab - // stop. Real tab events do not do this. See crbug.com/543865. - $('oauth-enroll-auth-view').addContentScripts([{ - name: 'injectedTabHandler', - matches: ['http://*/*', 'https://*/*'], - js: {code: INJECTED_WEBVIEW_SCRIPT}, - run_at: 'document_start' - }]); - } - - $('oauth-enroll-auth-view').partition = data.webviewPartitionName; - - Oobe.getInstance().setSigninUIState(SIGNIN_UI_STATE.ENROLLMENT); - this.classList.remove('saml'); - - var gaiaParams = {}; - gaiaParams.gaiaUrl = data.gaiaUrl; - gaiaParams.clientId = data.clientId; - gaiaParams.needPassword = false; - gaiaParams.hl = data.hl; - if (data.management_domain) { - gaiaParams.enterpriseEnrollmentDomain = data.management_domain; - gaiaParams.emailDomain = data.management_domain; - } - gaiaParams.flow = data.flow; - this.authenticator_.load( - cr.login.Authenticator.AuthMode.DEFAULT, gaiaParams); - - var modes = ['manual', 'forced', 'recovery']; - for (var i = 0; i < modes.length; ++i) { - this.classList.toggle( - 'mode-' + modes[i], data.enrollment_mode == modes[i]); - } - this.isManualEnrollment_ = data.enrollment_mode === 'manual'; - this.navigation_.disabled = false; - - this.offlineAdUi_.onBeforeShow(); - if (!this.currentStep_) - this.showStep(data.attestationBased ? STEP_WORKING : STEP_SIGNIN); - }, - - onBeforeHide: function() { - Oobe.getInstance().setSigninUIState(SIGNIN_UI_STATE.HIDDEN); + $('enterprise-enrollment').screen = this; }, /** @@ -294,9 +40,8 @@ * location. */ showAttributePromptStep: function(annotatedAssetId, annotatedLocation) { - $('oauth-enroll-asset-id').value = annotatedAssetId; - $('oauth-enroll-location').value = annotatedLocation; - this.showStep(STEP_ATTRIBUTE_PROMPT); + $('enterprise-enrollment') + .showAttributePromptStep(annotatedAssetId, annotatedLocation); }, /** @@ -305,54 +50,16 @@ */ showAttestationBasedEnrollmentSuccess: function( device, enterpriseEnrollmentDomain) { - $('oauth-enroll-success-subtitle').deviceName = device; - $('oauth-enroll-success-subtitle').enrollmentDomain = - enterpriseEnrollmentDomain; - this.showStep(STEP_SUCCESS); - }, - - /** - * Cancels the current authentication and drops the user back to the next - * screen (either the next authentication or the login screen). - */ - cancel: function() { - if (this.isCancelDisabled) - return; - this.isCancelDisabled = true; - chrome.send('oauthEnrollClose', ['cancel']); + $('enterprise-enrollment') + .showAttestationBasedEnrollmentSuccess( + device, enterpriseEnrollmentDomain); }, /** * Updates the list of available license types in license selection dialog. */ setAvailableLicenseTypes: function(licenseTypes) { - var licenses = [ - { - id: 'perpetual', - label: 'perpetualLicenseTypeTitle', - }, - { - id: 'annual', - label: 'annualLicenseTypeTitle', - }, - { - id: 'kiosk', - label: 'kioskLicenseTypeTitle', - } - ]; - for (var i = 0, item; item = licenses[i]; ++i) { - if (item.id in licenseTypes) { - item.count = parseInt(licenseTypes[item.id]); - item.disabled = item.count == 0; - item.hidden = false; - } else { - item.count = 0; - item.disabled = true; - item.hidden = true; - } - } - this.licenseUi_.disabled = false; - this.licenseUi_.licenses = licenses; + $('enterprise-enrollment').setAvailableLicenseTypes(licenseTypes); }, /** @@ -361,35 +68,7 @@ * "attribute-prompt", "error", "success". */ showStep: function(step) { - this.classList.toggle('oauth-enroll-state-' + this.currentStep_, false); - this.classList.toggle('oauth-enroll-state-' + step, true); - - this.isCancelDisabled = - (step == STEP_SIGNIN && !this.isManualEnrollment_) || - step == STEP_AD_JOIN || step == STEP_WORKING; - if (step == STEP_SIGNIN) { - $('oauth-enroll-auth-view').focus(); - } else if (step == STEP_LICENSE_TYPE) { - $('oauth-enroll-license-ui').show(); - } else if (step == STEP_ERROR) { - $('oauth-enroll-error-card').submitButton.focus(); - } else if (step == STEP_SUCCESS) { - $('oauth-enroll-success-card').show(); - } else if (step == STEP_ATTRIBUTE_PROMPT) { - $('oauth-enroll-attribute-prompt-card').show(); - } else if (step == STEP_ATTRIBUTE_PROMPT_ERROR) { - $('oauth-enroll-attribute-prompt-error-card').submitButton.focus(); - } else if (step == STEP_ACTIVE_DIRECTORY_JOIN_ERROR) { - $('oauth-enroll-active-directory-join-error-card').submitButton.focus(); - } else if (step == STEP_AD_JOIN) { - this.offlineAdUi_.disabled = false; - this.offlineAdUi_.loading = false; - this.offlineAdUi_.focus(); - } - - this.currentStep_ = step; - this.lastBackMessageValue_ = false; - this.updateControlsState(); + $('enterprise-enrollment').showStep(step); }, /** @@ -398,27 +77,11 @@ * @param {boolean} retry whether the retry link should be shown. */ showError: function(message, retry) { - if (this.currentStep_ == STEP_ATTRIBUTE_PROMPT) { - $('oauth-enroll-attribute-prompt-error-card').textContent = message; - this.showStep(STEP_ATTRIBUTE_PROMPT_ERROR); - return; - } - if (this.currentStep_ == STEP_AD_JOIN) { - $('oauth-enroll-active-directory-join-error-card').textContent = - message; - this.showStep(STEP_ACTIVE_DIRECTORY_JOIN_ERROR); - return; - } - $('oauth-enroll-error-card').textContent = message; - $('oauth-enroll-error-card').buttonLabel = - retry ? loadTimeData.getString('oauthEnrollRetry') : ''; - this.showStep(STEP_ERROR); + $('enterprise-enrollment').showError(message, retry); }, doReload: function() { - this.lastBackMessageValue_ = false; - this.authenticator_.reload(); - this.updateControlsState(); + $('enterprise-enrollment').doReload(); }, /** @@ -431,11 +94,8 @@ */ setAdJoinParams: function( machineName, userName, errorState, showUnlockConfig) { - this.offlineAdUi_.disabled = false; - this.offlineAdUi_.machineName = machineName; - this.offlineAdUi_.userName = userName; - this.offlineAdUi_.errorState = errorState; - this.offlineAdUi_.unlockPasswordStep = showUnlockConfig; + $('enterprise-enrollment') + .setAdJoinParams(machineName, userName, errorState, showUnlockConfig); }, /** @@ -443,84 +103,39 @@ * @param {Array<JoinConfigType>} options */ setAdJoinConfiguration: function(options) { - this.offlineAdUi_.disabled = false; - this.offlineAdUi_.setJoinConfigurationOptions(options); - this.offlineAdUi_.unlockPasswordStep = false; + $('enterprise-enrollment').setAdJoinConfiguration(options); }, - /** - * Retries the enrollment process after an error occurred in a previous - * attempt. This goes to the C++ side through |chrome| first to clean up the - * profile, so that the next attempt is performed with a clean state. - */ - doRetry_: function() { - chrome.send('oauthEnrollRetry'); + closeEnrollment_: function(result) { + chrome.send('oauthEnrollClose', [result]); }, - /** - * Skips the device attribute update, - * shows the successful enrollment step. - */ - onSkipButtonClicked: function() { - this.showStep(STEP_SUCCESS); + onAttributesEntered_: function(asset_id, location) { + chrome.send('oauthEnrollAttributes', [asset_id, location]); }, - /** - * Skips the device attribute update, - * shows the successful enrollment step. - */ - onBackButtonClicked_: function() { - if (this.currentStep_ == STEP_SIGNIN) { - if (this.lastBackMessageValue_) { - this.lastBackMessageValue_ = false; - $('oauth-enroll-auth-view').back(); - } else { - this.cancel(); - } - } + onAuthCompleted_: function(email) { + chrome.send('oauthEnrollCompleteLogin', [email]); }, - - /** - * Uploads the device attributes to server. This goes to C++ side through - * |chrome| and launches the device attribute update negotiation. - */ - onAttributesSubmitted: function() { - chrome.send( - 'oauthEnrollAttributes', - [$('oauth-enroll-asset-id').value, $('oauth-enroll-location').value]); + onAuthFrameLoaded_: function() { + chrome.send('frameLoadingCompleted'); }, - /** - * Returns true if we are at the begging of enrollment flow (i.e. the email - * page). - * - * @type {boolean} - */ - isAtTheBeginning: function() { - return !this.lastBackMessageValue_ && this.currentStep_ == STEP_SIGNIN; + onAdCompleteLogin_: function( + machine_name, distinguished_name, encryption_types, username, + password) { + chrome.send('oauthEnrollAdCompleteLogin', [ + machine_name, distinguished_name, encryption_types, username, password + ]); }, - /** - * Updates visibility of navigation buttons. - */ - updateControlsState: function() { - this.navigation_.refreshVisible = - this.isAtTheBeginning() && this.isManualEnrollment_ === false; - this.navigation_.closeVisible = - (this.currentStep_ == STEP_ERROR && !this.navigation_.refreshVisible) - || this.currentStep_ == STEP_LICENSE_TYPE; + onAdUnlockConfiguration_: function(unlock_password) { + chrome.send('oauthEnrollAdUnlockConfiguration', [unlock_password]); }, - /** - * Notifies chrome that enrollment have finished. - */ - onEnrollmentFinished_: function() { - chrome.send('oauthEnrollClose', ['done']); - }, - - updateLocalizedContent: function() { - this.offlineAdUi_.i18nUpdateLocale(); + onLicenseTypeSelected_: function(license_type) { + chrome.send('onLicenseTypeSelected', [license_type]); }, }; });
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc index 512167f..059578d 100644 --- a/chrome/browser/search/instant_service.cc +++ b/chrome/browser/search/instant_service.cc
@@ -584,20 +584,6 @@ !pref_service_->GetBoolean(prefs::kNtpUseMostVisitedTiles); } -namespace { - -// Converts SkColor to RGBAColor -RGBAColor SkColorToRGBAColor(const SkColor& sKColor) { - RGBAColor color; - color.r = SkColorGetR(sKColor); - color.g = SkColorGetG(sKColor); - color.b = SkColorGetB(sKColor); - color.a = SkColorGetA(sKColor); - return color; -} - -} // namespace - void InstantService::BuildThemeInfo() { // Get theme information from theme service. theme_info_.reset(new ThemeBackgroundInfo()); @@ -618,9 +604,9 @@ theme_provider.GetColor(ThemeProperties::COLOR_NTP_TEXT_LIGHT); // Set colors. - theme_info_->background_color = SkColorToRGBAColor(background_color); - theme_info_->text_color = SkColorToRGBAColor(text_color); - theme_info_->text_color_light = SkColorToRGBAColor(text_color_light); + theme_info_->background_color = background_color; + theme_info_->text_color = text_color; + theme_info_->text_color_light = text_color_light; int logo_alternate = theme_provider.GetDisplayProperty(ThemeProperties::NTP_LOGO_ALTERNATE);
diff --git a/chrome/browser/sharing/sharing_sync_preference.cc b/chrome/browser/sharing/sharing_sync_preference.cc new file mode 100644 index 0000000..88a4cb22 --- /dev/null +++ b/chrome/browser/sharing/sharing_sync_preference.cc
@@ -0,0 +1,135 @@ +// Copyright 2019 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 "chrome/browser/sharing/sharing_sync_preference.h" + +#include "base/base64.h" +#include "base/value_conversions.h" +#include "components/prefs/scoped_user_pref_update.h" +#include "components/sync_preferences/pref_service_syncable.h" + +namespace { + +const char kVapidKey[] = "sharing.vapid_key"; +const char kVapidECPrivateKey[] = "vapid_private_key"; +const char kVapidCreationTimestamp[] = "vapid_creation_timestamp"; + +const char kSyncedDevices[] = "sharing.synced_devices"; +const char kDeviceFcmToken[] = "device_fcm_token"; +const char kDeviceP256dh[] = "device_p256dh"; +const char kDeviceAuthSecret[] = "device_auth_secret"; +const char kDeviceCapabilities[] = "device_capabilities"; +} // namespace + +SharingSyncPreference::Device::Device(const std::string& fcm_token, + const std::string& p256dh, + const std::string& auth_secret, + const int capabilities) + : fcm_token(fcm_token), + p256dh(p256dh), + auth_secret(auth_secret), + capabilities(capabilities) {} + +SharingSyncPreference::Device::Device(Device&& other) = default; + +SharingSyncPreference::Device::~Device() = default; + +SharingSyncPreference::SharingSyncPreference(PrefService* prefs) + : prefs_(prefs) {} + +SharingSyncPreference::~SharingSyncPreference() = default; + +// static +void SharingSyncPreference::RegisterProfilePrefs( + user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterDictionaryPref( + kSyncedDevices, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + registry->RegisterDictionaryPref( + kVapidKey, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); +} + +base::Optional<std::vector<uint8_t>> SharingSyncPreference::GetVapidKey() + const { + const base::DictionaryValue* vapid_key = prefs_->GetDictionary(kVapidKey); + std::string base64_private_key, private_key; + if (!vapid_key->GetString(kVapidECPrivateKey, &base64_private_key)) + return base::nullopt; + + if (base::Base64Decode(base64_private_key, &private_key)) { + return std::vector<uint8_t>(private_key.begin(), private_key.end()); + } else { + LOG(ERROR) << "Could not decode stored vapid keys."; + return base::nullopt; + } +} + +void SharingSyncPreference::SetVapidKey( + const std::vector<uint8_t>& vapid_key) const { + base::Time creation_timestamp = base::Time::Now(); + std::string base64_vapid_key; + base::Base64Encode(std::string(vapid_key.begin(), vapid_key.end()), + &base64_vapid_key); + + DictionaryPrefUpdate update(prefs_, kVapidKey); + update->SetString(kVapidECPrivateKey, base64_vapid_key); + update->SetString(kVapidCreationTimestamp, + base::CreateTimeValue(creation_timestamp).GetString()); +} + +std::map<std::string, SharingSyncPreference::Device> +SharingSyncPreference::GetSyncedDevices() const { + std::map<std::string, Device> synced_devices; + const base::DictionaryValue* devices_preferences = + prefs_->GetDictionary(kSyncedDevices); + for (const auto& it : devices_preferences->DictItems()) { + base::Optional<Device> device = ValueToDevice(it.second); + if (device) + synced_devices.emplace(it.first, std::move(*device)); + } + return synced_devices; +} + +void SharingSyncPreference::SetSyncDevice(const std::string& guid, + const Device& device) { + DictionaryPrefUpdate update(prefs_, kSyncedDevices); + update->SetKey(guid, DeviceToValue(device)); +} + +void SharingSyncPreference::RemoveDevice(const std::string& guid) { + DictionaryPrefUpdate update(prefs_, kSyncedDevices); + update->RemoveKey(guid); +} + +base::Value SharingSyncPreference::DeviceToValue(const Device& device) const { + std::string base64_p256dh, base64_auth_secret; + base::Base64Encode(device.p256dh, &base64_p256dh); + base::Base64Encode(device.auth_secret, &base64_auth_secret); + + base::Value result(base::Value::Type::DICTIONARY); + result.SetStringKey(kDeviceFcmToken, device.fcm_token); + result.SetStringKey(kDeviceP256dh, base64_p256dh); + result.SetStringKey(kDeviceAuthSecret, base64_auth_secret); + result.SetIntKey(kDeviceCapabilities, device.capabilities); + return result; +} + +base::Optional<SharingSyncPreference::Device> +SharingSyncPreference::ValueToDevice(const base::Value& value) const { + const std::string* fcm_token = value.FindStringKey(kDeviceFcmToken); + const std::string* base64_p256dh = value.FindStringKey(kDeviceP256dh); + const std::string* base64_auth_secret = + value.FindStringKey(kDeviceAuthSecret); + const base::Optional<int> capabilities = + value.FindIntKey(kDeviceCapabilities); + + std::string p256dh, auth_secret; + if (!fcm_token || !base64_p256dh || !base64_auth_secret || !capabilities || + !base::Base64Decode(*base64_p256dh, &p256dh) || + !base::Base64Decode(*base64_auth_secret, &auth_secret)) { + LOG(ERROR) << "Could not convert synced value to device object."; + return base::nullopt; + } else { + return Device(*fcm_token, p256dh, auth_secret, *capabilities); + } +}
diff --git a/chrome/browser/sharing/sharing_sync_preference.h b/chrome/browser/sharing/sharing_sync_preference.h new file mode 100644 index 0000000..050ace6 --- /dev/null +++ b/chrome/browser/sharing/sharing_sync_preference.h
@@ -0,0 +1,86 @@ +// Copyright 2019 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 CHROME_BROWSER_SHARING_SHARING_SYNC_PREFERENCE_H_ +#define CHROME_BROWSER_SHARING_SHARING_SYNC_PREFERENCE_H_ + +#include <stdint.h> +#include <map> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/optional.h" +#include "base/values.h" + +namespace user_prefs { +class PrefRegistrySyncable; +} + +class PrefService; + +// SharingSyncPreference manages all preferences related to Sharing using Sync, +// such as storing list of user devices synced via Chrome and VapidKey used +// for authentication. +class SharingSyncPreference { + public: + struct Device { + Device(const std::string& fcm_token, + const std::string& p256dh, + const std::string& auth_secret, + const int capabilities); + Device(Device&& other); + ~Device(); + + // FCM registration token of device for sending SharingMessage. + std::string fcm_token; + + // Subscription public key required for WebPush protocol. + std::string p256dh; + + // Auth secret key required for WebPush protocol. + std::string auth_secret; + + // Bitmask of capabilities, defined in SharingDeviceCapability enum, that + // are supported by the device. + int capabilities; + }; + + explicit SharingSyncPreference(PrefService* prefs); + ~SharingSyncPreference(); + + static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + + // Returns VAPID key from preferences if present, otherwise returns + // base::nullopt. + // For more information on vapid keys, please see + // https://tools.ietf.org/html/draft-thomson-webpush-vapid-02 + base::Optional<std::vector<uint8_t>> GetVapidKey() const; + + // Adds VAPID key to preferences for syncing across devices. + void SetVapidKey(const std::vector<uint8_t>& vapid_key) const; + + // Returns the map of guid to device from sharing preferences. Guid is same + // as sync device guid. + std::map<std::string, Device> GetSyncedDevices() const; + + // Stores |device| with key |guid| in sharing preferences. + // |guid| is same as sync device guid. + void SetSyncDevice(const std::string& guid, const Device& device); + + // Removes device corresponding to |guid| from sharing preferences. + // |guid| is same as sync device guid. + void RemoveDevice(const std::string& guid); + + private: + base::Value DeviceToValue(const Device& device) const; + + base::Optional<Device> ValueToDevice(const base::Value& value) const; + + PrefService* prefs_; + + DISALLOW_COPY_AND_ASSIGN(SharingSyncPreference); +}; + +#endif // CHROME_BROWSER_SHARING_SHARING_SYNC_PREFERENCE_H_
diff --git a/chrome/browser/sharing/sharing_sync_preference_unittest.cc b/chrome/browser/sharing/sharing_sync_preference_unittest.cc new file mode 100644 index 0000000..af638ae --- /dev/null +++ b/chrome/browser/sharing/sharing_sync_preference_unittest.cc
@@ -0,0 +1,78 @@ +// Copyright 2019 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 "chrome/browser/sharing/sharing_sync_preference.h" + +#include <memory> + +#include "components/prefs/scoped_user_pref_update.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const char kVapidKeyStr[] = "test_vapid_key"; +const std::vector<uint8_t> kVapidKey = + std::vector<uint8_t>(std::begin(kVapidKeyStr), std::end(kVapidKeyStr)); + +const char kDeviceGuid[] = "test_device"; +const char kDeviceFcmToken[] = "test_fcm_token"; +const char kDeviceAuthToken[] = "test_auth_token"; +const char kDeviceP256dh[] = "test_p256dh"; +const int kCapabilities = 1; + +class SharingSyncPreferenceTest : public testing::Test { + protected: + SharingSyncPreferenceTest() : sharing_sync_preference_(&prefs_) { + SharingSyncPreference::RegisterProfilePrefs(prefs_.registry()); + } + + void SyncDefaultDevice() { + sharing_sync_preference_.SetSyncDevice( + kDeviceGuid, + SharingSyncPreference::Device(kDeviceFcmToken, kDeviceP256dh, + kDeviceAuthToken, kCapabilities)); + } + + base::Optional<SharingSyncPreference::Device> GetDevice( + const std::string& guid) { + std::map<std::string, SharingSyncPreference::Device> synced_devices = + sharing_sync_preference_.GetSyncedDevices(); + auto it = synced_devices.find(guid); + if (it == synced_devices.end()) + return base::nullopt; + else + return std::move(it->second); + } + + sync_preferences::TestingPrefServiceSyncable prefs_; + SharingSyncPreference sharing_sync_preference_; +}; + +} // namespace + +TEST_F(SharingSyncPreferenceTest, UpdateVapidKeys) { + EXPECT_EQ(base::nullopt, sharing_sync_preference_.GetVapidKey()); + sharing_sync_preference_.SetVapidKey(kVapidKey); + EXPECT_EQ(kVapidKey, sharing_sync_preference_.GetVapidKey()); +} + +TEST_F(SharingSyncPreferenceTest, RemoveDevice) { + SyncDefaultDevice(); + EXPECT_NE(base::nullopt, GetDevice(kDeviceGuid)); + sharing_sync_preference_.RemoveDevice(kDeviceGuid); + EXPECT_EQ(base::nullopt, GetDevice(kDeviceGuid)); +} + +TEST_F(SharingSyncPreferenceTest, SyncDevice) { + EXPECT_EQ(base::nullopt, GetDevice(kDeviceGuid)); + SyncDefaultDevice(); + base::Optional<SharingSyncPreference::Device> device = GetDevice(kDeviceGuid); + + EXPECT_NE(base::nullopt, device); + EXPECT_EQ(kDeviceFcmToken, device->fcm_token); + EXPECT_EQ(kDeviceP256dh, device->p256dh); + EXPECT_EQ(kDeviceAuthToken, device->auth_secret); + EXPECT_EQ(kCapabilities, device->capabilities); +}
diff --git a/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc b/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc index 1953e6a..a0876eb 100644 --- a/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
@@ -26,6 +26,16 @@ return SyncAppListHelper::GetInstance()->AllProfilesHaveSameAppList(); } +// Returns true if sync items from |service| all have non-empty names. +bool SyncItemsHaveNames(const app_list::AppListSyncableService* service) { + for (const auto& it : service->sync_items()) { + if (it.second->item_name.empty()) { + return false; + } + } + return true; +} + // Returns true if sync items from |service1| match to sync items in |service2|. bool SyncItemsMatch(const app_list::AppListSyncableService* service1, const app_list::AppListSyncableService* service2) { @@ -123,6 +133,9 @@ apps_helper::InstallApp(verifier(), i); } + // Allow async callbacks to run, such as App Service Mojo calls. + base::RunLoop().RunUntilIdle(); + app_list::AppListSyncableService* service = app_list::AppListSyncableServiceFactory::GetForProfile(verifier()); @@ -154,9 +167,17 @@ std::vector<std::string> app_ids; for (int i = 0; i < static_cast<int>(kNumApps); ++i) { app_ids.push_back(apps_helper::InstallApp(profile, i)); - service->SetPinPosition(app_ids.back(), pin_position); + } + + // Allow async callbacks to run, such as App Service Mojo calls. + base::RunLoop().RunUntilIdle(); + + for (const std::string& app_id : app_ids) { + service->SetPinPosition(app_id, pin_position); pin_position = pin_position.CreateAfter(); } + EXPECT_TRUE(SyncItemsHaveNames(service)); + SyncAppListHelper::GetInstance()->MoveAppToFolder(profile, app_ids[2], "folder1"); SyncAppListHelper::GetInstance()->MoveAppToFolder(profile, app_ids[3],
diff --git a/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc b/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc index 353bcc8..64308f9 100644 --- a/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc
@@ -94,12 +94,8 @@ std::vector<sync_pb::SyncEntity> entities = GetFakeServer()->GetSyncEntitiesByModelType(syncer::SESSIONS); - // Two header entities and two tab entities (one of the two has been closed - // but considered "free" for future recycling, i.e. not deleted). - ASSERT_EQ(4U, entities.size()); - for (const auto& entity : entities) { - EXPECT_FALSE(entity.deleted()); - } + // Two header entities and one tab entity (the other one has been deleted). + EXPECT_EQ(3U, entities.size()); } IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, E2E_ENABLED(AllChanged)) {
diff --git a/chrome/browser/ui/android/page_info/page_info_controller_android.cc b/chrome/browser/ui/android/page_info/page_info_controller_android.cc index 774d31e..211424d 100644 --- a/chrome/browser/ui/android/page_info/page_info_controller_android.cc +++ b/chrome/browser/ui/android/page_info/page_info_controller_android.cc
@@ -127,7 +127,7 @@ user_specified_settings_to_display; for (const auto& permission : permission_info_list) { - if (base::ContainsValue(permissions_to_display, permission.type)) { + if (base::Contains(permissions_to_display, permission.type)) { base::Optional<ContentSetting> setting_to_display = GetSettingToDisplay(permission); if (setting_to_display) { @@ -138,7 +138,7 @@ } for (const auto& permission : permissions_to_display) { - if (base::ContainsKey(user_specified_settings_to_display, permission)) { + if (base::Contains(user_specified_settings_to_display, permission)) { base::string16 setting_title = PageInfoUI::PermissionTypeToUIString(permission);
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.cc b/chrome/browser/ui/app_list/app_list_syncable_service.cc index 25e58d14..f810ee8 100644 --- a/chrome/browser/ui/app_list/app_list_syncable_service.cc +++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -789,7 +789,7 @@ SyncItem* sync_item = (iter++)->second.get(); if (sync_item->item_type != sync_pb::AppListSpecifics::TYPE_FOLDER) continue; - if (!base::ContainsKey(parent_ids, sync_item->item_id)) + if (!base::Contains(parent_ids, sync_item->item_id)) DeleteSyncItem(sync_item->item_id); } } @@ -1143,11 +1143,11 @@ AppListSyncableService::SyncItem* AppListSyncableService::CreateSyncItem( const std::string& item_id, sync_pb::AppListSpecifics::AppListItemType item_type) { - DCHECK(!base::ContainsKey(sync_items_, item_id)); + DCHECK(!base::Contains(sync_items_, item_id)); sync_items_[item_id] = std::make_unique<SyncItem>(item_id, item_type); // In case we have pending attributes to apply, process it asynchronously. - if (base::ContainsKey(pending_transfer_map_, item_id)) { + if (base::Contains(pending_transfer_map_, item_id)) { base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&AppListSyncableService::ApplyAppAttributes, weak_ptr_factory_.GetWeakPtr(), item_id,
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc index d39666049..cb6ae95 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -1747,7 +1747,7 @@ for (const auto& package : packages) { AddOrUpdatePackagePrefs(*package); - if (!base::ContainsKey(old_packages, package->package_name)) { + if (!base::Contains(old_packages, package->package_name)) { for (auto& observer : observer_list_) observer.OnPackageInstalled(*package); } @@ -1755,7 +1755,7 @@ } for (const auto& package_name : old_packages) { - if (!base::ContainsKey(current_packages, package_name)) { + if (!base::Contains(current_packages, package_name)) { RemovePackageFromPrefs(package_name); for (auto& observer : observer_list_) observer.OnPackageRemoved(package_name, false);
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc index d70e101..bdc29dd 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -328,7 +328,7 @@ // In principle, order of items is not defined. for (const auto& app : apps) { const std::string id = ArcAppTest::GetAppId(app); - EXPECT_TRUE(base::ContainsValue(ids, id)); + EXPECT_TRUE(base::Contains(ids, id)); std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(id); ASSERT_NE(nullptr, app_info.get()); EXPECT_EQ(app.name, app_info->name); @@ -342,7 +342,7 @@ for (auto& shortcut : shortcuts) { const std::string id = ArcAppTest::GetAppId(shortcut); - EXPECT_TRUE(base::ContainsValue(ids, id)); + EXPECT_TRUE(base::Contains(ids, id)); std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(id); ASSERT_NE(nullptr, app_info.get()); EXPECT_EQ(shortcut.name, app_info->name);
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc index fb619871..9d8822cda 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -664,7 +664,7 @@ } bool Intent::HasExtraParam(const std::string& extra_param) const { - return base::ContainsValue(extra_params_, extra_param); + return base::Contains(extra_params_, extra_param); } } // namespace arc
diff --git a/chrome/browser/ui/app_list/arc/arc_package_syncable_service.cc b/chrome/browser/ui/app_list/arc/arc_package_syncable_service.cc index 4f6b27a..f4631dd 100644 --- a/chrome/browser/ui/app_list/arc/arc_package_syncable_service.cc +++ b/chrome/browser/ui/app_list/arc/arc_package_syncable_service.cc
@@ -159,7 +159,7 @@ std::unique_ptr<ArcSyncItem> sync_item( CreateSyncItemFromSyncData(sync_data)); const std::string& package_name = sync_item->package_name; - if (!base::ContainsKey(local_package_set, package_name)) { + if (!base::Contains(local_package_set, package_name)) { pending_install_items_[package_name] = std::move(sync_item); InstallPackage(pending_install_items_[package_name].get()); } else { @@ -171,7 +171,7 @@ // Creates sync items for local unsynced packages. syncer::SyncChangeList change_list; for (const auto& local_package_name : local_packages) { - if (base::ContainsKey(sync_items_, local_package_name)) + if (base::Contains(sync_items_, local_package_name)) continue; if (!ShouldSyncPackage(local_package_name))
diff --git a/chrome/browser/ui/app_list/page_break_constants.cc b/chrome/browser/ui/app_list/page_break_constants.cc index de876e3..b4863a3 100644 --- a/chrome/browser/ui/app_list/page_break_constants.cc +++ b/chrome/browser/ui/app_list/page_break_constants.cc
@@ -21,7 +21,7 @@ // Returns true if |item_id| is of a default-installed page break item. bool IsDefaultPageBreakItem(const std::string& item_id) { - return base::ContainsValue(kDefaultPageBreakAppIds, item_id); + return base::Contains(kDefaultPageBreakAppIds, item_id); } } // namespace app_list
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc index 5dfe9fff..616c0c54 100644 --- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc +++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc
@@ -182,7 +182,7 @@ bool ChromeKeyboardControllerClient::IsEnableFlagSet( const keyboard::KeyboardEnableFlag& flag) { - return base::ContainsKey(keyboard_enable_flags_, flag); + return base::Contains(keyboard_enable_flags_, flag); } void ChromeKeyboardControllerClient::ReloadKeyboardIfNeeded() {
diff --git a/chrome/browser/ui/ash/launcher/internal_app_window_shelf_controller.cc b/chrome/browser/ui/ash/launcher/internal_app_window_shelf_controller.cc index 171bbb3..15fa2d1 100644 --- a/chrome/browser/ui/ash/launcher/internal_app_window_shelf_controller.cc +++ b/chrome/browser/ui/ash/launcher/internal_app_window_shelf_controller.cc
@@ -91,7 +91,7 @@ return; // Skip OnWindowVisibilityChanged for ancestors/descendants. - if (!base::ContainsValue(observed_windows_, window)) + if (!base::Contains(observed_windows_, window)) return; ash::ShelfID shelf_id =
diff --git a/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc b/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc index dbd3aa2..e736894 100644 --- a/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc +++ b/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc
@@ -69,7 +69,7 @@ void MultiProfileBrowserStatusMonitor::AddV1AppToShelf(Browser* browser) { DCHECK(browser->is_type_popup() && browser->is_app()); - DCHECK(!base::ContainsValue(app_list_, browser)); + DCHECK(!base::Contains(app_list_, browser)); app_list_.push_back(browser); if (multi_user_util::IsProfileFromActiveUser(browser->profile())) { BrowserStatusMonitor::AddV1AppToShelf(browser);
diff --git a/chrome/browser/ui/ash/media_client_impl.cc b/chrome/browser/ui/ash/media_client_impl.cc index 5c0c0b5..f497e38 100644 --- a/chrome/browser/ui/ash/media_client_impl.cc +++ b/chrome/browser/ui/ash/media_client_impl.cc
@@ -226,7 +226,7 @@ ui::MediaKeysListener::Delegate* delegate) { auto it = media_key_delegates_.find(context); - DCHECK(!base::ContainsKey(media_key_delegates_, context) || + DCHECK(!base::Contains(media_key_delegates_, context) || it->second == delegate); media_key_delegates_.emplace(context, delegate); @@ -237,7 +237,7 @@ void MediaClientImpl::DisableCustomMediaKeyHandler( content::BrowserContext* context, ui::MediaKeysListener::Delegate* delegate) { - if (!base::ContainsKey(media_key_delegates_, context)) + if (!base::Contains(media_key_delegates_, context)) return; auto it = media_key_delegates_.find(context);
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc index a208623e..eec89eba 100644 --- a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc +++ b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
@@ -341,7 +341,7 @@ tester.ExpectTotalCount(kClickThroughPosition, 4); // Requests to show popups not on the list should do nothing. - EXPECT_FALSE(base::ContainsValue(ids, 5)); + EXPECT_FALSE(base::Contains(ids, 5)); popup_blocker->ShowBlockedPopup(5, disposition); tester.ExpectTotalCount(kClickThroughPosition, 4); }
diff --git a/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc index 24299709..6ff5ccd3 100644 --- a/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc +++ b/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc
@@ -80,7 +80,7 @@ #if defined(OS_ANDROID) return false; #else - return base::ContainsValue( + return base::Contains( FramebustBlockTabHelper::FromWebContents(web_contents)->blocked_urls(), url); #endif
diff --git a/chrome/browser/ui/content_settings/framebust_block_browsertest.cc b/chrome/browser/ui/content_settings/framebust_block_browsertest.cc index a50e70f..1965154 100644 --- a/chrome/browser/ui/content_settings/framebust_block_browsertest.cc +++ b/chrome/browser/ui/content_settings/framebust_block_browsertest.cc
@@ -261,8 +261,8 @@ redirect_url.spec().c_str())), base::NullCallback()); block_waiter.Run(); - EXPECT_TRUE(base::ContainsValue(GetFramebustTabHelper()->blocked_urls(), - redirect_url)); + EXPECT_TRUE( + base::Contains(GetFramebustTabHelper()->blocked_urls(), redirect_url)); } IN_PROC_BROWSER_TEST_F(FramebustBlockBrowserTest, @@ -351,8 +351,8 @@ redirect_url.spec().c_str())), base::NullCallback()); block_waiter.Run(); - EXPECT_TRUE(base::ContainsValue(GetFramebustTabHelper()->blocked_urls(), - redirect_url)); + EXPECT_TRUE( + base::Contains(GetFramebustTabHelper()->blocked_urls(), redirect_url)); // Now, navigate away and check that the UI went away. ui_test_utils::NavigateToURL(browser(),
diff --git a/chrome/browser/ui/input_method/input_method_engine.cc b/chrome/browser/ui/input_method/input_method_engine.cc index 5ab21b2d..9a9d314 100644 --- a/chrome/browser/ui/input_method/input_method_engine.cc +++ b/chrome/browser/ui/input_method/input_method_engine.cc
@@ -286,14 +286,13 @@ ui::VKEY_RETURN}; if (ui_event->GetDomKey().IsCharacter() && !ui_event->IsControlDown() && !ui_event->IsCommandDown()) { - return !base::ContainsValue(invalid_character_keycodes, - ui_event->key_code()); + return !base::Contains(invalid_character_keycodes, ui_event->key_code()); } // Whitelists Backspace key and arrow keys. std::vector<ui::KeyboardCode> whitelist_keycodes{ ui::VKEY_BACK, ui::VKEY_LEFT, ui::VKEY_RIGHT, ui::VKEY_UP, ui::VKEY_DOWN}; - return base::ContainsValue(whitelist_keycodes, ui_event->key_code()); + return base::Contains(whitelist_keycodes, ui_event->key_code()); } } // namespace input_method
diff --git a/chrome/browser/ui/login/login_handler_test_utils.cc b/chrome/browser/ui/login/login_handler_test_utils.cc index 097a9c6..cb91b01b5 100644 --- a/chrome/browser/ui/login/login_handler_test_utils.cc +++ b/chrome/browser/ui/login/login_handler_test_utils.cc
@@ -33,7 +33,7 @@ } void LoginPromptBrowserTestObserver::AddHandler(LoginHandler* handler) { - ASSERT_FALSE(base::ContainsValue(handlers_, handler)); + ASSERT_FALSE(base::Contains(handlers_, handler)); handlers_.push_back(handler); }
diff --git a/chrome/browser/ui/media_router/cast_modes_with_media_sources.cc b/chrome/browser/ui/media_router/cast_modes_with_media_sources.cc index 686173b0..12308fa6 100644 --- a/chrome/browser/ui/media_router/cast_modes_with_media_sources.cc +++ b/chrome/browser/ui/media_router/cast_modes_with_media_sources.cc
@@ -31,8 +31,8 @@ bool CastModesWithMediaSources::HasSource(MediaCastMode cast_mode, const MediaSource& source) const { - return base::ContainsKey(cast_modes_, cast_mode) - ? base::ContainsKey(cast_modes_.at(cast_mode), source) + return base::Contains(cast_modes_, cast_mode) + ? base::Contains(cast_modes_.at(cast_mode), source) : false; }
diff --git a/chrome/browser/ui/media_router/media_router_ui_base.cc b/chrome/browser/ui/media_router/media_router_ui_base.cc index 1abc6fee..b500b88 100644 --- a/chrome/browser/ui/media_router/media_router_ui_base.cc +++ b/chrome/browser/ui/media_router/media_router_ui_base.cc
@@ -184,8 +184,7 @@ if (start_presentation_context_) { bool presentation_sinks_available = std::any_of( sinks_.begin(), sinks_.end(), [](const MediaSinkWithCastModes& sink) { - return base::ContainsKey(sink.cast_modes, - MediaCastMode::PRESENTATION); + return base::Contains(sink.cast_modes, MediaCastMode::PRESENTATION); }); if (presentation_sinks_available) { start_presentation_context_->InvokeErrorCallback(
diff --git a/chrome/browser/ui/media_router/query_result_manager.cc b/chrome/browser/ui/media_router/query_result_manager.cc index f8630f9a..b42a786 100644 --- a/chrome/browser/ui/media_router/query_result_manager.cc +++ b/chrome/browser/ui/media_router/query_result_manager.cc
@@ -165,7 +165,7 @@ return; for (const MediaSource& source : cast_mode_it->second) { - if (!base::ContainsValue(new_sources, source)) { + if (!base::Contains(new_sources, source)) { sinks_observers_.erase(source); SetSinksCompatibleWithSource(cast_mode, source, std::vector<MediaSink>()); } @@ -177,7 +177,7 @@ const std::vector<MediaSource>& sources, const url::Origin& origin) { for (const MediaSource& source : sources) { - if (!base::ContainsKey(sinks_observers_, source)) { + if (!base::Contains(sinks_observers_, source)) { auto observer = std::make_unique<MediaSourceMediaSinksObserver>( cast_mode, source, origin, router_, this); observer->Init(); @@ -200,7 +200,7 @@ /* no-op */) { const MediaSink::Id& sink_id = it->first; CastModesWithMediaSources& sources_for_sink = it->second; - if (!base::ContainsKey(new_sink_ids, sink_id)) + if (!base::Contains(new_sink_ids, sink_id)) sources_for_sink.RemoveSource(cast_mode, source); if (sources_for_sink.IsEmpty()) { sinks_with_sources_.erase(it++); @@ -249,12 +249,12 @@ bool has_cast_mode = cast_mode_it != cast_mode_sources_.end(); // If a source has already been registered, then it must be associated with // |cast_mode|. - return std::find_if( - sources.begin(), sources.end(), [=](const MediaSource& source) { - return base::ContainsKey(sinks_observers_, source) && - (!has_cast_mode || - !base::ContainsValue(cast_mode_it->second, source)); - }) == sources.end(); + return std::find_if(sources.begin(), sources.end(), + [=](const MediaSource& source) { + return base::Contains(sinks_observers_, source) && + (!has_cast_mode || + !base::Contains(cast_mode_it->second, source)); + }) == sources.end(); } void QueryResultManager::NotifyOnResultsUpdated() { @@ -265,7 +265,7 @@ sinks.push_back(sink_with_cast_modes); } for (const auto& sink : all_sinks_) { - if (!base::ContainsKey(sinks_with_sources_, sink.id())) + if (!base::Contains(sinks_with_sources_, sink.id())) sinks.push_back(MediaSinkWithCastModes(sink)); } for (QueryResultManager::Observer& observer : observers_)
diff --git a/chrome/browser/ui/media_router/query_result_manager_unittest.cc b/chrome/browser/ui/media_router/query_result_manager_unittest.cc index 7a960ef..8bd1b592 100644 --- a/chrome/browser/ui/media_router/query_result_manager_unittest.cc +++ b/chrome/browser/ui/media_router/query_result_manager_unittest.cc
@@ -81,7 +81,7 @@ return false; for (size_t i = 0; i < expected.size(); ++i) { - if (!base::ContainsValue(arg, expected[i])) + if (!base::Contains(arg, expected[i])) return false; } return true; @@ -121,7 +121,7 @@ cast_modes = query_result_manager_.GetSupportedCastModes(); EXPECT_EQ(1u, cast_modes.size()); - EXPECT_TRUE(base::ContainsKey(cast_modes, MediaCastMode::PRESENTATION)); + EXPECT_TRUE(base::Contains(cast_modes, MediaCastMode::PRESENTATION)); actual_sources = query_result_manager_.GetSourcesForCastMode(MediaCastMode::PRESENTATION); EXPECT_EQ(1u, actual_sources.size()); @@ -139,7 +139,7 @@ cast_modes = query_result_manager_.GetSupportedCastModes(); EXPECT_EQ(1u, cast_modes.size()); - EXPECT_TRUE(base::ContainsKey(cast_modes, MediaCastMode::PRESENTATION)); + EXPECT_TRUE(base::Contains(cast_modes, MediaCastMode::PRESENTATION)); actual_sources = query_result_manager_.GetSourcesForCastMode(MediaCastMode::PRESENTATION); EXPECT_EQ(1u, actual_sources.size()); @@ -383,11 +383,10 @@ const auto& cast_mode_sources = query_result_manager_.cast_mode_sources_; const auto& presentation_sources = cast_mode_sources.at(MediaCastMode::PRESENTATION); - EXPECT_TRUE( - base::ContainsKey(cast_mode_sources, MediaCastMode::PRESENTATION)); + EXPECT_TRUE(base::Contains(cast_mode_sources, MediaCastMode::PRESENTATION)); EXPECT_EQ(presentation_sources.size(), 1u); EXPECT_EQ(presentation_sources.at(0), source); - EXPECT_FALSE(base::ContainsKey(cast_mode_sources, MediaCastMode::TAB_MIRROR)); + EXPECT_FALSE(base::Contains(cast_mode_sources, MediaCastMode::TAB_MIRROR)); } } // namespace media_router
diff --git a/chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.cc b/chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.cc index 87032049..8bb4fa5 100644 --- a/chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.cc +++ b/chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.cc
@@ -70,11 +70,11 @@ } bool MockPermissionPromptFactory::RequestTypeSeen(PermissionRequestType type) { - return base::ContainsValue(request_types_seen_, type); + return base::Contains(request_types_seen_, type); } bool MockPermissionPromptFactory::RequestOriginSeen(const GURL& origin) { - return base::ContainsValue(request_origins_seen_, origin); + return base::Contains(request_origins_seen_, origin); } void MockPermissionPromptFactory::WaitForPermissionBubble() {
diff --git a/chrome/browser/ui/search_engines/template_url_table_model.cc b/chrome/browser/ui/search_engines/template_url_table_model.cc index e08c44b..bbc62ed 100644 --- a/chrome/browser/ui/search_engines/template_url_table_model.cc +++ b/chrome/browser/ui/search_engines/template_url_table_model.cc
@@ -127,8 +127,8 @@ // Sanity checks for https://crbug.com/781703. CHECK_GE(index, 0); CHECK_LT(static_cast<size_t>(index), entries_.size()); - CHECK(base::ContainsValue(template_url_service_->GetTemplateURLs(), - entries_[index])) + CHECK( + base::Contains(template_url_service_->GetTemplateURLs(), entries_[index])) << "TemplateURLTableModel is returning a pointer to a TemplateURL " "that has already been freed by TemplateURLService.";
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index c4d3551..d283a39 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -778,7 +778,7 @@ } const TabGroupData* TabStripModel::GetDataForGroup(TabGroupId group) const { - DCHECK(base::ContainsKey(group_data_, group)); + DCHECK(base::Contains(group_data_, group)); return group_data_.at(group).get(); }
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.cc b/chrome/browser/ui/toolbar/toolbar_actions_model.cc index 19bfb20..0e44b87f 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
@@ -320,8 +320,7 @@ CHECK(actions_initialized_); // See if we have a last known good position for this extension. - bool is_new_extension = - !base::ContainsValue(last_known_positions_, action_id); + bool is_new_extension = !base::Contains(last_known_positions_, action_id); // New extensions go at the right (end) of the visible extensions. Other // extensions go at their previous position. @@ -437,7 +436,7 @@ bool ToolbarActionsModel::IsActionPinned(const ActionId& action_id) const { DCHECK(base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)); - return base::ContainsValue(pinned_action_ids_, action_id); + return base::Contains(pinned_action_ids_, action_id); } void ToolbarActionsModel::RemoveExtension( @@ -590,7 +589,7 @@ } bool ToolbarActionsModel::HasAction(const ActionId& action_id) const { - return base::ContainsValue(action_ids_, action_id); + return base::Contains(action_ids_, action_id); } void ToolbarActionsModel::IncognitoPopulate() { @@ -689,7 +688,7 @@ std::vector<ActionId> pref_positions = extension_prefs_->GetToolbarOrder(); size_t pref_position_size = pref_positions.size(); for (size_t i = 0; i < last_known_positions_.size(); ++i) { - if (!base::ContainsValue(pref_positions, last_known_positions_[i])) { + if (!base::Contains(pref_positions, last_known_positions_[i])) { pref_positions.push_back(last_known_positions_[i]); } }
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view.cc b/chrome/browser/ui/views/media_router/cast_dialog_view.cc index 9c87c42f2..f2eae8a 100644 --- a/chrome/browser/ui/views/media_router/cast_dialog_view.cc +++ b/chrome/browser/ui/views/media_router/cast_dialog_view.cc
@@ -434,17 +434,17 @@ // supported and selected. switch (selected_source_) { case SourceType::kTab: - if (base::ContainsKey(sink.cast_modes, PRESENTATION)) + if (base::Contains(sink.cast_modes, PRESENTATION)) return base::make_optional<MediaCastMode>(PRESENTATION); - if (base::ContainsKey(sink.cast_modes, TAB_MIRROR)) + if (base::Contains(sink.cast_modes, TAB_MIRROR)) return base::make_optional<MediaCastMode>(TAB_MIRROR); break; case SourceType::kDesktop: - if (base::ContainsKey(sink.cast_modes, DESKTOP_MIRROR)) + if (base::Contains(sink.cast_modes, DESKTOP_MIRROR)) return base::make_optional<MediaCastMode>(DESKTOP_MIRROR); break; case SourceType::kLocalFile: - if (base::ContainsKey(sink.cast_modes, LOCAL_FILE)) + if (base::Contains(sink.cast_modes, LOCAL_FILE)) return base::make_optional<MediaCastMode>(LOCAL_FILE); break; }
diff --git a/chrome/browser/ui/views/media_router/media_router_views_ui_unittest.cc b/chrome/browser/ui/views/media_router/media_router_views_ui_unittest.cc index 320289d..43b53f9b 100644 --- a/chrome/browser/ui/views/media_router/media_router_views_ui_unittest.cc +++ b/chrome/browser/ui/views/media_router/media_router_views_ui_unittest.cc
@@ -110,7 +110,7 @@ EXPECT_EQ(base::UTF8ToUTF16(sink.name()), ui_sink.friendly_name); EXPECT_EQ(UIMediaSinkState::AVAILABLE, ui_sink.state); EXPECT_TRUE( - base::ContainsKey(ui_sink.cast_modes, MediaCastMode::TAB_MIRROR)); + base::Contains(ui_sink.cast_modes, MediaCastMode::TAB_MIRROR)); EXPECT_EQ(sink.icon_type(), ui_sink.icon_type); }))); ui_->OnResultsUpdated({sink_with_cast_modes});
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 7b9fdfa..6d82690 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -12,9 +12,7 @@ #include "base/auto_reset.h" #include "base/bind.h" #include "base/callback.h" -#include "base/feature_list.h" #include "base/i18n/rtl.h" -#include "base/logging.h" #include "base/macros.h" #include "base/numerics/ranges.h" #include "base/stl_util.h" @@ -28,7 +26,6 @@ #include "chrome/browser/ui/sad_tab_helper.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" -#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" @@ -435,7 +432,7 @@ MoveBehavior move_behavior, EventSource event_source) { DCHECK(!tabs.empty()); - DCHECK(base::ContainsValue(tabs, source_tab)); + DCHECK(base::Contains(tabs, source_tab)); source_context_ = source_context; was_source_maximized_ = source_context->AsView()->GetWidget()->IsMaximized(); was_source_fullscreen_ = @@ -476,9 +473,9 @@ source_context_->AsView()->GetWidget()->GetNativeWindow()); if (source_tab->width() > 0) { - offset_to_width_ratio_ = - float{source_tab->GetMirroredXInView(source_tab_offset)} / - float{source_tab->width()}; + offset_to_width_ratio_ = static_cast<float>( + source_tab->GetMirroredXInView(source_tab_offset)) / + static_cast<float>(source_tab->width()); } InitWindowCreatePoint(); initial_selection_model_ = std::move(initial_selection_model); @@ -546,7 +543,7 @@ } current_state_ = DragState::kDraggingTabs; Attach(source_context_, gfx::Point()); - if (int{drag_data_.size()} == + if (static_cast<int>(drag_data_.size()) == source_context_->GetTabStripModel()->count()) { views::Widget* widget = GetAttachedBrowserWidget(); gfx::Rect new_bounds; @@ -754,8 +751,8 @@ static const int kMinimumDragDistance = 10; int x_offset = abs(point_in_screen.x() - start_point_in_screen_.x()); int y_offset = abs(point_in_screen.y() - start_point_in_screen_.y()); - return sqrt(pow(float{x_offset}, 2) + pow(float{y_offset}, 2)) > - kMinimumDragDistance; + return sqrt(pow(static_cast<float>(x_offset), 2) + + pow(static_cast<float>(y_offset), 2)) > kMinimumDragDistance; } TabDragController::Liveness TabDragController::ContinueDragging( @@ -909,7 +906,8 @@ void TabDragController::DragActiveTabStacked( const gfx::Point& point_in_screen) { - if (attached_context_->GetTabCount() != int{initial_tab_positions_.size()}) + if (attached_context_->GetTabCount() != + static_cast<int>(initial_tab_positions_.size())) return; // TODO: should cancel drag if this happens. int delta = point_in_screen.x() - start_point_in_screen_.x(); @@ -959,7 +957,7 @@ TabStripModel* attached_model = attached_context_->GetTabStripModel(); int to_index = attached_context_->GetInsertionIndexForDraggedBounds( GetDraggedViewTabStripBounds(dragged_view_point), false, - int{drag_data_.size()}, mouse_has_ever_moved_left_, + static_cast<int>(drag_data_.size()), mouse_has_ever_moved_left_, mouse_has_ever_moved_right_); bool do_move = true; // While dragging within a tabstrip the expectation is the insertion index @@ -1001,9 +999,6 @@ initial_move_); did_layout = true; } - if (base::FeatureList::IsEnabled(features::kDragToPinTabs)) { - UpdatePinnednessOfDraggedTab(to_index); - } attached_model->MoveSelectedTabsTo(to_index); // Move may do nothing in certain situations (such as when dragging pinned @@ -1160,7 +1155,6 @@ std::vector<Tab*> tabs = GetTabsMatchingDraggedContents(attached_context_); - TabStripModel* attached_model = attached_context_->GetTabStripModel(); if (tabs.empty()) { // Transitioning from detached to attached to a new context. Add tabs to // the new model. @@ -1184,7 +1178,7 @@ tab_strip_point.Offset(0, -mouse_offset_.y()); int index = attached_context_->GetInsertionIndexForDraggedBounds( GetDraggedViewTabStripBounds(tab_strip_point), true, - int{drag_data_.size()}, mouse_has_ever_moved_left_, + static_cast<int>(drag_data_.size()), mouse_has_ever_moved_left_, mouse_has_ever_moved_right_); attach_index_ = index; attach_x_ = tab_strip_point.x(); @@ -1197,26 +1191,10 @@ DCHECK_EQ(1u, drag_data_.size()); add_types |= TabStripModel::ADD_ACTIVE; } - const int target_index = index + i; - - if (base::FeatureList::IsEnabled(features::kDragToPinTabs)) { - if (drag_data_[i].pinned) { - // Attaching a tab is effectively an insertion at the target index. A - // pinned tab will only need to unpin if the previous tab is unpinned. - drag_data_[i].pinned = !CheckValidPinnedness( - target_index - 1, TabAnimationState::TabPinnedness::kUnpinned); - } else { - // An unpinned tab will only need to be pinned if the tab to the right - // of it is is pinned. - drag_data_[i].pinned = CheckValidPinnedness( - target_index, TabAnimationState::TabPinnedness::kPinned); - } - } if (drag_data_[i].pinned) add_types |= TabStripModel::ADD_PINNED; - - attached_model->InsertWebContentsAt( - target_index, std::move(drag_data_[i].owned_contents), add_types); + attached_context_->GetTabStripModel()->InsertWebContentsAt( + index + i, std::move(drag_data_[i].owned_contents), add_types); // If a sad tab is showing, the SadTabView needs to be updated. SadTabHelper* sad_tab_helper = @@ -1224,13 +1202,14 @@ if (sad_tab_helper) sad_tab_helper->ReinstallInWebView(); } + tabs = GetTabsMatchingDraggedContents(attached_context_); } DCHECK_EQ(tabs.size(), drag_data_.size()); for (size_t i = 0; i < drag_data_.size(); ++i) drag_data_[i].attached_tab = tabs[i]; - ResetSelection(attached_model); + ResetSelection(attached_context_->GetTabStripModel()); // This should be called after ResetSelection() in order to generate // bounds correctly. http://crbug.com/836004 @@ -1255,7 +1234,8 @@ attached_context_->OwnDragController(this); SetTabDraggingInfo(); attached_context_tabs_closed_tracker_ = - std::make_unique<DraggedTabsClosedTracker>(attached_model, this); + std::make_unique<DraggedTabsClosedTracker>( + attached_context_->GetTabStripModel(), this); } void TabDragController::Detach(ReleaseCapture release_capture) { @@ -1317,7 +1297,7 @@ void TabDragController::DetachIntoNewBrowserAndRunMoveLoop( const gfx::Point& point_in_screen) { if (attached_context_->GetTabStripModel()->count() == - int{drag_data_.size()}) { + static_cast<int>(drag_data_.size())) { // All the tabs in a browser are being dragged but all the tabs weren't // initially being dragged. For this to happen the user would have to // start dragging a set of tabs, the other tabs close, then detach. @@ -1940,12 +1920,12 @@ // If the new tabstrip is smaller than the old resize the tabs. if (dragged_context_width < tab_area_width) { const float leading_ratio = - drag_bounds->front().x() / float{tab_area_width}; + drag_bounds->front().x() / static_cast<float>(tab_area_width); *drag_bounds = CalculateBoundsForDraggedTabs(); if (drag_bounds->back().right() < dragged_context_width) { const int delta_x = std::min( - int{leading_ratio * dragged_context_width}, + static_cast<int>(leading_ratio * dragged_context_width), dragged_context_width - (drag_bounds->back().right() - drag_bounds->front().x())); OffsetX(delta_x, drag_bounds); @@ -2111,49 +2091,6 @@ #endif } -void TabDragController::UpdatePinnednessOfDraggedTab(int to_index) { - TabStripModel* attached_model = attached_context_->GetTabStripModel(); - const int selected_count = - int{attached_model->selection_model().selected_indices().size()}; - for (int i = 0; i < selected_count; i++) { - const int current_index = - attached_model->selection_model().selected_indices()[i]; - const int target_index = to_index + i; - if (current_index != target_index) { - // When dragging a tab to the target index, the tab is effectively - // swapping places with the tab at its target index.This means that - // if the current tab is pinned but the tab it is swapping with is - // not, the current tab will need to be unpinned. The opposite is - // true when moving an unpinned tab. - if (attached_model->IsTabPinned(current_index) && - CheckValidPinnedness(target_index, - TabAnimationState::TabPinnedness::kUnpinned)) { - attached_model->SetTabPinned(current_index, false); - } else if (!attached_model->IsTabPinned(current_index) && - CheckValidPinnedness( - target_index, TabAnimationState::TabPinnedness::kPinned)) { - attached_model->SetTabPinned(current_index, true); - } - } - } -} - -bool TabDragController::CheckValidPinnedness( - int index, - TabAnimationState::TabPinnedness expected_pinnedness) { - TabStripModel* attached_model = attached_context_->GetTabStripModel(); - - if (!attached_model->ContainsIndex(index)) - return false; - - TabAnimationState::TabPinnedness pinnedness = - attached_model->IsTabPinned(index) - ? TabAnimationState::TabPinnedness::kPinned - : TabAnimationState::TabPinnedness::kUnpinned; - - return expected_pinnedness == pinnedness; -} - void TabDragController::SetDeferredTargetTabstrip( TabDragContext* deferred_target_context) { #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.h b/chrome/browser/ui/views/tabs/tab_drag_controller.h index 4e7846b..653d681 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.h +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.h
@@ -14,7 +14,6 @@ #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" -#include "chrome/browser/ui/views/tabs/tab_animation_state.h" #include "chrome/browser/ui/views/tabs/tab_drag_context.h" #include "chrome/browser/ui/views/tabs/tab_strip_types.h" #include "ui/base/models/list_selection_model.h" @@ -495,19 +494,6 @@ // is showing a modal). bool ShouldDisallowDrag(gfx::NativeWindow window); - // Helper method for TabDragController::MoveAttached to update the pinnedness - // of the tab being moved by checking the pinnedness of the tabs being - // dragged with the pinnedness of the tab at the target dragged location. - // TODO (crbug.com/971676): This will swap and update the pinnedness of - // multi-selected tabs one at a time, which is unintended. - void UpdatePinnednessOfDraggedTab(int to_index); - - // Helper method that checks if the index is valid in the TabDragContext and - // the pin at the index has the expected pinned value. - bool CheckValidPinnedness( - int index, - TabAnimationState::TabPinnedness expected_pinnedness); - EventSource event_source_; // The TabDragContext the drag originated from. This is set to null
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index 2a9d72a..3ad4e5f 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -23,7 +23,6 @@ #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/test/bind_test_util.h" -#include "base/test/scoped_feature_list.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" @@ -32,7 +31,6 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/native_browser_frame_factory.h" #include "chrome/browser/ui/views/tabs/tab.h" @@ -423,50 +421,6 @@ #endif // OS_MACOSX } - // Set up the test environment with 4 tabs. Two pinned and two unpinned. - void SetUpDragToChangePinnednessTest() { - AddTabAndResetBrowser(browser()); - AddTabAndResetBrowser(browser()); - AddTabAndResetBrowser(browser()); - - TabStrip* tab_strip = GetTabStripForBrowser(browser()); - TabStripModel* model = browser()->tab_strip_model(); - - model->SetTabPinned(0, true); - model->SetTabPinned(1, true); - StopAnimating(tab_strip); - ASSERT_TRUE(model->IsTabPinned(0)); - ASSERT_TRUE(model->IsTabPinned(1)); - ASSERT_FALSE(model->IsTabPinned(2)); - ASSERT_FALSE(model->IsTabPinned(3)); - EXPECT_EQ("0 1 2 3", IDString(model)); - } - - // Set up the test environment another browser with two unpinned tabs. - Browser* SetUpSecondBrowserWithTwoUnpinnedTabs() { - Browser* browser2 = CreateAnotherBrowserAndResize(); - AddTabAndResetBrowser(browser2); - ResetIDs(browser2->tab_strip_model(), 100); - return browser2; - } - - void SelectIndicies(TabStrip* tabstrip, - TabStripModel* model, - std::vector<int> indicies) { - DCHECK(!indicies.empty()); - // The last tab opened will automatically be selected. Simulating a click to - // select the first index will ensure others are no longer selected. - ASSERT_TRUE(PressInput( - GetCenterInScreenCoordinates(tabstrip->tab_at(indicies.at(0))))); - ASSERT_TRUE(ReleaseInput()); - - if (indicies.size() > 1) { - for (auto it = std::next(indicies.begin()); it != indicies.end(); ++it) { - model->ToggleSelectionAt(*it); - } - } - } - InputSource input_source() const { return strstr(GetParam(), "mouse") ? INPUT_SOURCE_MOUSE : INPUT_SOURCE_TOUCH; @@ -641,23 +595,6 @@ Browser* browser() const { return InProcessBrowserTest::browser(); } - void DragToSeparateWindowBeforeFirstTab(TabStrip* tabstrip_to) { - gfx::Point tab_left_center = - tabstrip_to->tab_at(0)->GetLocalBounds().left_center(); - views::View::ConvertPointToScreen(tabstrip_to->tab_at(0), &tab_left_center); - ASSERT_TRUE(DragInputToAsync(tab_left_center)); - } - - void DragToSeparateWindowAfterFirstTab(TabStrip* tabstrip_to) { - gfx::Point tab_right_center = - tabstrip_to->tab_at(0)->GetLocalBounds().right_center(); - views::View::ConvertPointToScreen(tabstrip_to->tab_at(0), - &tab_right_center); - ASSERT_TRUE(DragInputToAsync(tab_right_center)); - } - - base::test::ScopedFeatureList scoped_feature_list_; - private: #if defined(OS_CHROMEOS) // The root window for the event generator. @@ -669,6 +606,12 @@ // Creates a browser with two tabs, drags the second to the first. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, DragInSameWindow) { + // TODO(sky): this won't work with touch as it requires a long press. + if (input_source() == INPUT_SOURCE_TOUCH) { + VLOG(1) << "Test is DISABLED for touch input."; + return; + } + AddTabAndResetBrowser(browser()); TabStrip* tab_strip = GetTabStripForBrowser(browser()); @@ -690,160 +633,6 @@ EXPECT_FALSE(tab_strip->GetWidget()->HasCapture()); } -// Creates a browser with four tabs two pinned two unpinned. With the -// kDragToPinTabs flag off, dragging tabs between pinned and unpinned will have -// no effect -IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - DragInSameWindow_CannotDragBetweenPinnedness) { - scoped_feature_list_.InitAndDisableFeature(features::kDragToPinTabs); - SetUpDragToChangePinnednessTest(); - - TabStrip* tab_strip = GetTabStripForBrowser(browser()); - TabStripModel* model = browser()->tab_strip_model(); - - // Dragging an unpinned tab before a pinned tab will have no effect. - ASSERT_TRUE(PressInput(GetCenterInScreenCoordinates(tab_strip->tab_at(2)))); - ASSERT_TRUE(DragInputTo(GetCenterInScreenCoordinates(tab_strip->tab_at(1)))); - ASSERT_TRUE(ReleaseInput()); - EXPECT_EQ("0 1 2 3", IDString(model)); - EXPECT_TRUE(model->IsTabPinned(0)); - EXPECT_TRUE(model->IsTabPinned(1)); - EXPECT_FALSE(model->IsTabPinned(2)); - EXPECT_FALSE(model->IsTabPinned(3)); - - // Dragging a pinned tab after an unpinned tab will have no effect. - ASSERT_TRUE(PressInput(GetCenterInScreenCoordinates(tab_strip->tab_at(1)))); - ASSERT_TRUE(DragInputTo(GetCenterInScreenCoordinates(tab_strip->tab_at(2)))); - ASSERT_TRUE(ReleaseInput()); - EXPECT_EQ("0 1 2 3", IDString(model)); - EXPECT_TRUE(model->IsTabPinned(0)); - EXPECT_TRUE(model->IsTabPinned(1)); - EXPECT_FALSE(model->IsTabPinned(2)); - EXPECT_FALSE(model->IsTabPinned(3)); -} - -// Creates a browser with four tabs two pinned two unpinned. With the -// kDragToPinTabs flag on, dragging unpinned tabs before a pinned tab will -// pin the unpinned tab. -IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - DragInSameWindow_DragUnpinnedBeforePinned) { - scoped_feature_list_.InitAndEnableFeature(features::kDragToPinTabs); - SetUpDragToChangePinnednessTest(); - - TabStrip* tab_strip = GetTabStripForBrowser(browser()); - TabStripModel* model = browser()->tab_strip_model(); - - SelectIndicies(tab_strip, model, std::vector<int>{2, 3}); - ASSERT_TRUE(PressInput(GetCenterInScreenCoordinates(tab_strip->tab_at(2)))); - ASSERT_TRUE(DragInputTo(GetCenterInScreenCoordinates(tab_strip->tab_at(0)))); - ASSERT_TRUE(ReleaseInput()); - StopAnimating(tab_strip); - EXPECT_EQ("2 3 0 1", IDString(model)); - EXPECT_TRUE(model->IsTabPinned(0)); - EXPECT_TRUE(model->IsTabPinned(1)); - EXPECT_TRUE(model->IsTabPinned(2)); - EXPECT_TRUE(model->IsTabPinned(3)); -} - -// Creates a browser with four tabs two pinned two unpinned. With the -// kDragToPinTabs flag on, dragging pinned tabs after the unpinned tab will -// unpin the pinned tab. -IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - DragInSameWindow_DragPinnedAfterUnpinned) { - scoped_feature_list_.InitAndEnableFeature(features::kDragToPinTabs); - SetUpDragToChangePinnednessTest(); - - TabStrip* tab_strip = GetTabStripForBrowser(browser()); - TabStripModel* model = browser()->tab_strip_model(); - - SelectIndicies(tab_strip, model, std::vector<int>{0, 1}); - - // TODO (crbug.com/965681): Investigate and fix the dragging case for dragging - // pinned tabs to after unpinned tabs. - gfx::Point tab_2 = GetCenterInScreenCoordinates(tab_strip->tab_at(2)); - gfx::Point tab_2_left_center = - tab_strip->tab_at(2)->GetLocalBounds().left_center(); - views::View::ConvertPointToScreen(tab_strip->tab_at(2), &tab_2_left_center); - ASSERT_TRUE(PressInput(GetCenterInScreenCoordinates(tab_strip->tab_at(0)))); - ASSERT_TRUE(DragInputTo(tab_2_left_center)); - ASSERT_TRUE(DragInputTo(tab_2)); - ASSERT_TRUE(ReleaseInput()); - StopAnimating(tab_strip); - EXPECT_FALSE(model->IsTabPinned(0)); - EXPECT_FALSE(model->IsTabPinned(1)); - EXPECT_FALSE(model->IsTabPinned(2)); - EXPECT_FALSE(model->IsTabPinned(3)); -} - -// Creates one browser with a single pinned tab as well as another browser -// (browser2) with one pinned tab and one unpinned tab. With the kDragToPinTabs -// flag on, dragging a both tabs from browser2 to the other browser to the left -// of the first pinned tab will pin both tabs dragged. -IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - DragToPinInNewWindow) { - scoped_feature_list_.InitAndEnableFeature(features::kDragToPinTabs); - - TabStrip* tab_strip = GetTabStripForBrowser(browser()); - TabStripModel* model = browser()->tab_strip_model(); - model->SetTabPinned(0, true); - StopAnimating(tab_strip); - - // Create another browser. - Browser* browser2 = SetUpSecondBrowserWithTwoUnpinnedTabs(); - TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); - browser2->tab_strip_model()->SetTabPinned(0, true); - StopAnimating(tab_strip2); - - SelectIndicies(tab_strip2, browser2->tab_strip_model(), - std::vector<int>{0, 1}); - - // This should be moving the entire window. - DragTabAndNotify(tab_strip2, - base::BindOnce(&DetachToBrowserTabDragControllerTest:: - DragToSeparateWindowBeforeFirstTab, - base::Unretained(this), tab_strip)); - ASSERT_TRUE(ReleaseInput()); - - EXPECT_EQ(3, model->count()); - EXPECT_TRUE(model->IsTabPinned(0)); - EXPECT_TRUE(model->IsTabPinned(1)); - EXPECT_TRUE(model->IsTabPinned(2)); -} - -// Creates one browser with a single unpinned tab as well as another browser -// (browser2) with one pinned tab and one unpinned tab. With the kDragToPinTabs -// flag on, dragging a both tabs from browser2 to the other browser to the right -// of the unpinned tab will unpin both tabs dragged. -IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - DragToPinEnabled_DragToUnpinInNewWindow) { - scoped_feature_list_.InitAndEnableFeature(features::kDragToPinTabs); - - TabStrip* tab_strip = GetTabStripForBrowser(browser()); - TabStripModel* model = browser()->tab_strip_model(); - - // Create another browser. - Browser* browser2 = SetUpSecondBrowserWithTwoUnpinnedTabs(); - TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); - browser2->tab_strip_model()->SetTabPinned(0, true); - StopAnimating(tab_strip2); - - SelectIndicies(tab_strip2, browser2->tab_strip_model(), - std::vector<int>{0, 1}); - - // This should be moving the entire window. - DragTabAndNotify(tab_strip2, - base::BindOnce(&DetachToBrowserTabDragControllerTest:: - DragToSeparateWindowAfterFirstTab, - base::Unretained(this), tab_strip)); - - ASSERT_TRUE(ReleaseInput()); - - EXPECT_EQ(3, model->count()); - EXPECT_FALSE(model->IsTabPinned(0)); - EXPECT_FALSE(model->IsTabPinned(1)); - EXPECT_FALSE(model->IsTabPinned(2)); -} - #if defined(USE_AURA) bool SubtreeShouldBeExplored(aura::Window* window, const gfx::Point& local_point) {
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index d8dcf65..4be7369 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -18,6 +18,7 @@ #include "base/containers/flat_map.h" #include "base/feature_list.h" #include "base/macros.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "base/no_destructor.h" @@ -341,7 +342,7 @@ } } DCHECK(!tabs.empty()); - DCHECK(base::ContainsValue(tabs, tab)); + DCHECK(base::Contains(tabs, tab)); ui::ListSelectionModel selection_model; if (!original_selection.IsSelected(model_index)) selection_model = original_selection; @@ -1029,6 +1030,14 @@ // model and tabstrip are in sync. if (!drag_context_->IsMutating() && drag_context_->IsDraggingWindow()) EndDrag(END_DRAG_COMPLETE); + + Profile* profile = controller()->GetProfile(); + if (profile) { + if (profile->IsGuestSession()) + base::UmaHistogramCounts100("Tab.Count.Guest", tab_count()); + else if (profile->IsIncognitoProfile()) + base::UmaHistogramCounts100("Tab.Count.Incognito", tab_count()); + } } void TabStrip::MoveTab(int from_model_index,
diff --git a/chrome/browser/ui/views/tabs/tab_strip_layout_helper.cc b/chrome/browser/ui/views/tabs/tab_strip_layout_helper.cc index 2f36aef..20c43fe 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_layout_helper.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_layout_helper.cc
@@ -124,7 +124,7 @@ const bool pinned = i < num_pinned_tabs; base::Optional<TabGroupId> group = tab_to_group_mapping[i]; if (group.has_value() && - !base::ContainsKey(headers_already_added, group.value())) { + !base::Contains(headers_already_added, group.value())) { // Start of a group. slots.push_back(TabSlot::CreateForGroupHeader(group.value(), pinned)); headers_already_added.insert(group.value());
diff --git a/chrome/browser/ui/views/tabs/window_finder_ozone.cc b/chrome/browser/ui/views/tabs/window_finder_ozone.cc index f290223..267c889 100644 --- a/chrome/browser/ui/views/tabs/window_finder_ozone.cc +++ b/chrome/browser/ui/views/tabs/window_finder_ozone.cc
@@ -18,5 +18,5 @@ if (views::Widget::GetWidgetForNativeWindow(window)) break; } - return (window && !base::ContainsKey(ignore, window)) ? window : nullptr; + return (window && !base::Contains(ignore, window)) ? window : nullptr; }
diff --git a/chrome/browser/ui/views/webauthn/hover_list_view.cc b/chrome/browser/ui/views/webauthn/hover_list_view.cc index 14a48c60..3bc805be 100644 --- a/chrome/browser/ui/views/webauthn/hover_list_view.cc +++ b/chrome/browser/ui/views/webauthn/hover_list_view.cc
@@ -222,7 +222,7 @@ } void HoverListView::AddListItemView(int item_tag) { - CHECK(!base::ContainsKey(tags_to_list_item_views_, item_tag)); + CHECK(!base::Contains(tags_to_list_item_views_, item_tag)); if (placeholder_list_item_view_) { RemoveListItemView(*placeholder_list_item_view_); placeholder_list_item_view_.reset();
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index 15e03543..40d1619 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -184,7 +184,7 @@ if (input_method.empty()) return; - if (!base::ContainsValue(*input_methods, input_method)) + if (!base::Contains(*input_methods, input_method)) input_methods->insert(input_methods->begin(), input_method); }
diff --git a/chrome/browser/ui/webui/chromeos/login/l10n_util.cc b/chrome/browser/ui/webui/chromeos/login/l10n_util.cc index 69825fc..c3dbe6c 100644 --- a/chrome/browser/ui/webui/chromeos/login/l10n_util.cc +++ b/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
@@ -155,7 +155,7 @@ if (lang.empty() || lang == language_id) continue; - if (base::ContainsValue(base_language_codes, language_id)) { + if (base::Contains(base_language_codes, language_id)) { // Language is supported. No need to replace continue; } @@ -163,7 +163,7 @@ if (!l10n_util::CheckAndResolveLocale(language_id, &resolved_locale)) continue; - if (!base::ContainsValue(base_language_codes, resolved_locale)) { + if (!base::Contains(base_language_codes, resolved_locale)) { // Resolved locale is not supported. continue; } @@ -186,7 +186,7 @@ it != language_codes.end(); ++it) { // Exclude the language which is not in |base_langauge_codes| even it has // input methods. - if (!base::ContainsValue(base_language_codes, *it)) + if (!base::Contains(base_language_codes, *it)) continue; const base::string16 display_name =
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc index a0e563f..dd76b24 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
@@ -37,7 +37,7 @@ // Returns true if |vendor_id| is a valid vendor id that may be made the primary // display. bool IsWhiteListedVendorId(uint16_t vendor_id) { - return base::ContainsValue(kDeviceIds, vendor_id); + return base::Contains(kDeviceIds, vendor_id); } } // namespace
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index 691f668..c83c559 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -271,7 +271,7 @@ std::string GetDisplayType(const GURL& url) { std::string path = url.path().size() ? url.path().substr(1) : ""; - if (!base::ContainsValue(kKnownDisplayTypes, path)) { + if (!base::Contains(kKnownDisplayTypes, path)) { LOG(ERROR) << "Unknown display type '" << path << "'. Setting default."; return OobeUI::kLoginDisplay; }
diff --git a/chrome/browser/ui/webui/cookies_tree_model_util.cc b/chrome/browser/ui/webui/cookies_tree_model_util.cc index 495e6b7..799d6fb 100644 --- a/chrome/browser/ui/webui/cookies_tree_model_util.cc +++ b/chrome/browser/ui/webui/cookies_tree_model_util.cc
@@ -185,13 +185,13 @@ dict->SetString(kKeyOrigin, file_system_info.origin.Serialize()); dict->SetString( kKeyPersistent, - base::ContainsKey(file_system_info.usage_map, kPerm) + base::Contains(file_system_info.usage_map, kPerm) ? base::UTF16ToUTF8(ui::FormatBytes( file_system_info.usage_map.find(kPerm)->second)) : l10n_util::GetStringUTF8(IDS_COOKIES_FILE_SYSTEM_USAGE_NONE)); dict->SetString( kKeyTemporary, - base::ContainsKey(file_system_info.usage_map, kTemp) + base::Contains(file_system_info.usage_map, kTemp) ? base::UTF16ToUTF8(ui::FormatBytes( file_system_info.usage_map.find(kTemp)->second)) : l10n_util::GetStringUTF8(IDS_COOKIES_FILE_SYSTEM_USAGE_NONE));
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc index fe9a0f7..98817b8 100644 --- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc +++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
@@ -501,9 +501,9 @@ })); EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("registerBegin")); run_loop.Run(); - EXPECT_TRUE(base::ContainsKey(served_urls, GURL(kURLInfo))); - EXPECT_TRUE(base::ContainsKey(served_urls, GURL(kURLRegisterStart))); - EXPECT_TRUE(base::ContainsKey(served_urls, GURL(kURLRegisterClaimToken))); + EXPECT_TRUE(base::Contains(served_urls, GURL(kURLInfo))); + EXPECT_TRUE(base::Contains(served_urls, GURL(kURLRegisterStart))); + EXPECT_TRUE(base::Contains(served_urls, GURL(kURLRegisterClaimToken))); test_url_loader_factory()->SetInterceptor(base::NullCallback()); } @@ -523,10 +523,10 @@ run_loop.Quit(); })); run_loop.Run(); - EXPECT_TRUE(base::ContainsKey(served_urls, GURL(kURLRegisterClaimToken))); - EXPECT_TRUE(base::ContainsKey(served_urls, GURL(kURLCloudPrintConfirm))); - EXPECT_TRUE(base::ContainsKey(served_urls, GURL(kURLRegisterComplete))); - EXPECT_TRUE(base::ContainsKey(served_urls, GURL(kURLInfo))); + EXPECT_TRUE(base::Contains(served_urls, GURL(kURLRegisterClaimToken))); + EXPECT_TRUE(base::Contains(served_urls, GURL(kURLCloudPrintConfirm))); + EXPECT_TRUE(base::Contains(served_urls, GURL(kURLRegisterComplete))); + EXPECT_TRUE(base::Contains(served_urls, GURL(kURLInfo))); test_url_loader_factory()->SetInterceptor(base::NullCallback()); }
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc index ae9fae4..bc4fe32 100644 --- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc +++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
@@ -79,13 +79,13 @@ const std::set<std::string>& local_ids, base::ListValue* devices_list) { for (const auto& i : devices) { - if (base::ContainsKey(local_ids, i.id)) { + if (base::Contains(local_ids, i.id)) { devices_list->Append(CreateDeviceInfo(i)); } } for (const auto& i : devices) { - if (!base::ContainsKey(local_ids, i.id)) { + if (!base::Contains(local_ids, i.id)) { devices_list->Append(CreateDeviceInfo(i)); } } @@ -300,8 +300,7 @@ const GURL& url) { web_ui()->CallJavascriptFunctionUnsafe( "local_discovery.onRegistrationConfirmedOnPrinter"); - if (!base::ContainsKey(device_descriptions_, - current_http_client_->GetName())) { + if (!base::Contains(device_descriptions_, current_http_client_->GetName())) { SendRegisterError(); return; }
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.cc b/chrome/browser/ui/webui/media_router/media_router_ui.cc index 11d65b67..04bf7f8c 100644 --- a/chrome/browser/ui/webui/media_router/media_router_ui.cc +++ b/chrome/browser/ui/webui/media_router/media_router_ui.cc
@@ -292,7 +292,7 @@ for (const MediaRoute& route : routes) { if (route.for_display() && - base::ContainsValue(joinable_route_ids, route.media_route_id())) { + base::Contains(joinable_route_ids, route.media_route_id())) { joinable_route_ids_.push_back(route.media_route_id()); } }
diff --git a/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc b/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc index b6b9fe2e..6ec7418 100644 --- a/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc +++ b/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc
@@ -551,7 +551,7 @@ // that should be the cast mode initially selected in the dialog. Otherwise // the initial cast mode should be chosen automatically by the dialog. bool use_tab_mirroring = - base::ContainsKey(cast_modes, MediaCastMode::TAB_MIRROR) && + base::Contains(cast_modes, MediaCastMode::TAB_MIRROR) && media_router_ui_->UserSelectedTabMirroringForCurrentOrigin(); initial_data.SetBoolean("useTabMirroring", use_tab_mirroring); @@ -1146,8 +1146,7 @@ auto value = std::make_unique<base::ListValue>(); for (const MediaRoute& route : routes) { - bool can_join = - base::ContainsValue(joinable_route_ids, route.media_route_id()); + bool can_join = base::Contains(joinable_route_ids, route.media_route_id()); int current_cast_mode = CurrentCastModeForRouteId(route.media_route_id(), current_cast_modes); std::unique_ptr<base::DictionaryValue> route_val(
diff --git a/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui.cc b/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui.cc index 64c6734..8bd114b 100644 --- a/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui.cc +++ b/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui.cc
@@ -84,7 +84,7 @@ if (url.is_valid() && url.has_query()) { std::vector<std::string> query_parameters = base::SplitString( url.query(), "&", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); - if (base::ContainsValue(query_parameters, "reset_fre")) + if (base::Contains(query_parameters, "reset_fre")) ResetAutoSignInFirstRunExperience(); } }
diff --git a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc index e0d6a90..f922611 100644 --- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc +++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
@@ -97,7 +97,7 @@ Media default_media("", "", default_media_size.width(), default_media_size.height()); if (!default_media.MatchBySize() || - !base::ContainsValue(kPdfMedia, default_media.type)) { + !base::Contains(kPdfMedia, default_media.type)) { default_media = Media(locale == "en-US" ? MediaType::NA_LETTER : MediaType::ISO_A4); }
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index a1ff2e4..260a56b 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -600,7 +600,7 @@ return false; } - if (!base::ContainsKey(preview_callbacks_, request_id)) { + if (!base::Contains(preview_callbacks_, request_id)) { BadMessageReceived(); return false; } @@ -703,7 +703,7 @@ int request_id = settings.FindIntKey(kPreviewRequestID).value(); CHECK_GT(request_id, -1); - CHECK(!base::ContainsKey(preview_callbacks_, request_id)); + CHECK(!base::Contains(preview_callbacks_, request_id)); preview_callbacks_[request_id] = callback_id; print_preview_ui()->OnPrintPreviewRequest(request_id); // Add an additional key in order to identify |print_preview_ui| later on @@ -1208,7 +1208,7 @@ // gets called, the print preview may have failed. Since the failure message // may have arrived first, check for this case and bail out instead of // thinking this may be a bad IPC message. - if (base::ContainsKey(preview_failures_, preview_request_id)) + if (base::Contains(preview_failures_, preview_request_id)) return; if (!ShouldReceiveRendererMessage(preview_request_id))
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_utils.cc b/chrome/browser/ui/webui/print_preview/print_preview_utils.cc index b5bbf38..71f576dd 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_utils.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_utils.cc
@@ -58,7 +58,7 @@ printer_info->SetBoolean( kCUPSEnterprisePrinter, - base::ContainsKey(printer.options, kCUPSEnterprisePrinter) && + base::Contains(printer.options, kCUPSEnterprisePrinter) && printer.options.at(kCUPSEnterprisePrinter) == kValueTrue); printer_info->Set(kSettingPrinterOptions, std::move(options));
diff --git a/chrome/browser/ui/webui/profile_helper_browsertest.cc b/chrome/browser/ui/webui/profile_helper_browsertest.cc index 935f029..b5c8ba75 100644 --- a/chrome/browser/ui/webui/profile_helper_browsertest.cc +++ b/chrome/browser/ui/webui/profile_helper_browsertest.cc
@@ -80,7 +80,7 @@ // Sanity checks. EXPECT_EQ(1u, browser_list->size()); - EXPECT_TRUE(base::ContainsValue(*browser_list, original_browser)); + EXPECT_TRUE(base::Contains(*browser_list, original_browser)); // Opening existing browser profile shouldn't open additional browser windows. webui::OpenNewWindowForProfile(original_profile); @@ -120,7 +120,7 @@ BrowserList* browser_list = BrowserList::GetInstance(); EXPECT_EQ(1u, browser_list->size()); - EXPECT_TRUE(base::ContainsValue(*browser_list, original_browser)); + EXPECT_TRUE(base::Contains(*browser_list, original_browser)); EXPECT_EQ(1u, storage.GetNumberOfProfiles()); // Original browser will be closed, and browser with the new profile created. @@ -135,7 +135,7 @@ close_observer.Wait(); EXPECT_EQ(1u, browser_list->size()); - EXPECT_FALSE(base::ContainsValue(*browser_list, original_browser)); + EXPECT_FALSE(base::Contains(*browser_list, original_browser)); EXPECT_EQ(1u, storage.GetNumberOfProfiles()); } @@ -147,7 +147,7 @@ BrowserList* browser_list = BrowserList::GetInstance(); EXPECT_EQ(1u, browser_list->size()); - EXPECT_TRUE(base::ContainsValue(*browser_list, original_browser)); + EXPECT_TRUE(base::Contains(*browser_list, original_browser)); EXPECT_EQ(1u, storage.GetNumberOfProfiles()); Profile* additional_profile = CreateProfile(); @@ -177,7 +177,7 @@ BrowserList* browser_list = BrowserList::GetInstance(); EXPECT_EQ(1u, browser_list->size()); - EXPECT_TRUE(base::ContainsValue(*browser_list, original_browser)); + EXPECT_TRUE(base::Contains(*browser_list, original_browser)); EXPECT_EQ(1u, storage.GetNumberOfProfiles()); Profile* additional_profile = CreateProfile(); @@ -191,6 +191,6 @@ inhibitor.ContinueToCompletion(); EXPECT_EQ(1u, browser_list->size()); - EXPECT_TRUE(base::ContainsValue(*browser_list, original_browser)); + EXPECT_TRUE(base::Contains(*browser_list, original_browser)); EXPECT_EQ(1u, storage.GetNumberOfProfiles()); }
diff --git a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc index 3a383f4..1e875bc 100644 --- a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
@@ -248,7 +248,7 @@ std::string fingerprint_name = l10n_util::GetStringFUTF8( IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME, base::NumberToString16(i)); - if (!base::ContainsValue(fingerprints_labels_, fingerprint_name)) { + if (!base::Contains(fingerprints_labels_, fingerprint_name)) { fp_service_->StartEnrollSession(user_id_, fingerprint_name); break; }
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc index 9a3ca49..36cbda3d 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -251,7 +251,7 @@ origin_object.SetKey(kNumCookies, base::Value(0)); origin_object.SetKey( kHasPermissionSettings, - base::Value(base::ContainsKey(origin_permission_set, origin))); + base::Value(base::Contains(origin_permission_set, origin))); origin_list.GetList().emplace_back(std::move(origin_object)); } site_group.SetKey(kNumCookies, base::Value(0));
diff --git a/chrome/browser/ui/webui/welcome/nux_helper.cc b/chrome/browser/ui/webui/welcome/nux_helper.cc index e984fb0..13a0118 100644 --- a/chrome/browser/ui/webui/welcome/nux_helper.cc +++ b/chrome/browser/ui/webui/welcome/nux_helper.cc
@@ -262,7 +262,7 @@ std::back_inserter(filtered_modules), [available_modules](std::string module) { return !module.empty() && - base::ContainsValue(available_modules, module); + base::Contains(available_modules, module); }); return base::JoinString(filtered_modules, ",");
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 00324b0..5d66a48 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -260,6 +260,11 @@ const base::Feature kDriveFcmInvalidations{"DriveFCMInvalidations", base::FEATURE_ENABLED_BY_DEFAULT}; +// If enabled, policies will use FCM (Firebase Cloud Messaging) for its +// invalidations. +const base::Feature kPolicyFcmInvalidations{"PolicyFCMInvalidations", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Show the number of open incognito windows besides incognito icon on the // toolbar. const base::Feature kEnableIncognitoWindowCounter{
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 19e38e6..77bcd4f 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -158,6 +158,9 @@ extern const base::Feature kDriveFcmInvalidations; COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::Feature kPolicyFcmInvalidations; + +COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kEnableIncognitoWindowCounter; #if !defined(OS_ANDROID)
diff --git a/chrome/common/instant_struct_traits.h b/chrome/common/instant_struct_traits.h index 66cf564..55260ca 100644 --- a/chrome/common/instant_struct_traits.h +++ b/chrome/common/instant_struct_traits.h
@@ -55,13 +55,6 @@ IPC_STRUCT_TRAITS_MEMBER(data_generation_time) IPC_STRUCT_TRAITS_END() -IPC_STRUCT_TRAITS_BEGIN(RGBAColor) - IPC_STRUCT_TRAITS_MEMBER(r) - IPC_STRUCT_TRAITS_MEMBER(g) - IPC_STRUCT_TRAITS_MEMBER(b) - IPC_STRUCT_TRAITS_MEMBER(a) -IPC_STRUCT_TRAITS_END() - IPC_STRUCT_TRAITS_BEGIN(ThemeBackgroundInfo) IPC_STRUCT_TRAITS_MEMBER(using_default_theme) IPC_STRUCT_TRAITS_MEMBER(using_dark_mode)
diff --git a/chrome/common/search/instant_types.cc b/chrome/common/search/instant_types.cc index 658748a..26d9a05 100644 --- a/chrome/common/search/instant_types.cc +++ b/chrome/common/search/instant_types.cc
@@ -4,26 +4,6 @@ #include "chrome/common/search/instant_types.h" -RGBAColor::RGBAColor() - : r(0), - g(0), - b(0), - a(0) { -} - -RGBAColor::RGBAColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a) - : r(r), g(g), b(b), a(a) {} - -RGBAColor::~RGBAColor() { -} - -bool RGBAColor::operator==(const RGBAColor& rhs) const { - return r == rhs.r && - g == rhs.g && - b == rhs.b && - a == rhs.a; -} - ThemeBackgroundInfo::ThemeBackgroundInfo() : using_default_theme(true), using_dark_mode(false),
diff --git a/chrome/common/search/instant_types.h b/chrome/common/search/instant_types.h index 8b4e137a..aba03392 100644 --- a/chrome/common/search/instant_types.h +++ b/chrome/common/search/instant_types.h
@@ -14,6 +14,7 @@ #include "base/time/time.h" #include "components/ntp_tiles/tile_source.h" #include "components/ntp_tiles/tile_title_source.h" +#include "third_party/skia/include/core/SkColor.h" #include "url/gurl.h" // ID used by Instant code to refer to objects (e.g. Autocomplete results, Most @@ -41,22 +42,6 @@ THEME_BKGRND_IMAGE_LAST = THEME_BKGRND_IMAGE_REPEAT, }; -// The RGBA color components for the text and links of the theme. -struct RGBAColor { - RGBAColor(); - RGBAColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a); - ~RGBAColor(); - - bool operator==(const RGBAColor& rhs) const; - - // The color in RGBA format where the R, G, B and A values - // are between 0 and 255 inclusive and always valid. - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; -}; - // Theme background settings for the NTP. struct ThemeBackgroundInfo { ThemeBackgroundInfo(); @@ -82,14 +67,14 @@ // Url to learn more info about the custom background. GURL custom_background_attribution_action_url; - // The theme background color in RGBA format always valid. - RGBAColor background_color; + // The theme background color. Always valid. + SkColor background_color; - // The theme text color in RGBA format. - RGBAColor text_color; + // The theme text color. + SkColor text_color; - // The theme text color light in RGBA format. - RGBAColor text_color_light; + // The theme text color light. + SkColor text_color_light; // The theme id for the theme background image. // Value is only valid if there's a custom theme background image.
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc index 1bce89a..abd8880 100644 --- a/chrome/renderer/searchbox/searchbox_extension.cc +++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -53,23 +53,6 @@ #include "v8/include/v8.h" namespace internal { // for testing. - -// Returns an array with the RGBA color components. -v8::Local<v8::Value> RGBAColorToArray(v8::Isolate* isolate, - const RGBAColor& color) { - v8::Local<v8::Context> context = isolate->GetCurrentContext(); - v8::Local<v8::Array> color_array = v8::Array::New(isolate, 4); - color_array->CreateDataProperty(context, 0, v8::Int32::New(isolate, color.r)) - .Check(); - color_array->CreateDataProperty(context, 1, v8::Int32::New(isolate, color.g)) - .Check(); - color_array->CreateDataProperty(context, 2, v8::Int32::New(isolate, color.b)) - .Check(); - color_array->CreateDataProperty(context, 3, v8::Int32::New(isolate, color.a)) - .Check(); - return color_array; -} - // Whether NTP background should be considered dark, so the colors of various // UI elements can be adjusted. Light text implies dark theme. bool IsNtpBackgroundDark(SkColor ntp_text) { @@ -97,13 +80,6 @@ return bg_color; } -// TODO(gayane): Consider removing RGBAColor struct and replacing it with -// SkColor. -// Converts RGBAColor to SkColor. -SkColor RGBAColorToSkColor(const RGBAColor& color) { - return SkColorSetARGB(color.a, color.r, color.g, color.b); -} - // Use dark icon when in dark mode and no background. Otherwise, use // light icon for NTPs with images, and themed icon for NTPs with solid color. SkColor GetIconColor(const ThemeBackgroundInfo& theme_info) { @@ -116,7 +92,7 @@ if (theme_info.using_dark_mode && theme_info.using_default_theme) return gfx::kGoogleGrey900; - SkColor bg_color = RGBAColorToSkColor(theme_info.background_color); + SkColor bg_color = theme_info.background_color; SkColor icon_color = gfx::kGoogleGrey100; if (!theme_info.using_default_theme && bg_color != SK_ColorWHITE) icon_color = CalculateIconColor(bg_color); @@ -248,14 +224,28 @@ return maybe_int.ToLocalChecked()->Value(); } -// Converts SkColor to RGBAColor -RGBAColor SkColorToRGBAColor(const SkColor& sKColor) { - RGBAColor color; - color.r = SkColorGetR(sKColor); - color.g = SkColorGetG(sKColor); - color.b = SkColorGetB(sKColor); - color.a = SkColorGetA(sKColor); - return color; +// Returns an array with the RGBA color components. +v8::Local<v8::Value> SkColorToArray(v8::Isolate* isolate, + const SkColor& color) { + v8::Local<v8::Context> context = isolate->GetCurrentContext(); + v8::Local<v8::Array> color_array = v8::Array::New(isolate, 4); + color_array + ->CreateDataProperty(context, 0, + v8::Int32::New(isolate, SkColorGetR(color))) + .Check(); + color_array + ->CreateDataProperty(context, 1, + v8::Int32::New(isolate, SkColorGetG(color))) + .Check(); + color_array + ->CreateDataProperty(context, 2, + v8::Int32::New(isolate, SkColorGetB(color))) + .Check(); + color_array + ->CreateDataProperty(context, 3, + v8::Int32::New(isolate, SkColorGetA(color))) + .Check(); + return color_array; } v8::Local<v8::Object> GenerateThemeBackgroundInfo( @@ -275,12 +265,12 @@ // Theme color for background as an array with the RGBA components in order. // Value is always valid. builder.Set("backgroundColorRgba", - internal::RGBAColorToArray(isolate, theme_info.background_color)); + SkColorToArray(isolate, theme_info.background_color)); // Theme color for light text as an array with the RGBA components in order. // Value is always valid. builder.Set("textColorLightRgba", - internal::RGBAColorToArray(isolate, theme_info.text_color_light)); + SkColorToArray(isolate, theme_info.text_color_light)); // The theme alternate logo value indicates a white logo when TRUE and a // colorful one when FALSE. @@ -357,12 +347,12 @@ // Assume that a custom background has not been configured and then // override based on the condition below. builder.Set("customBackgroundConfigured", false); - RGBAColor ntp_text = theme_info.text_color; + SkColor ntp_text = theme_info.text_color; // If a custom background has been set provide the relevant information to the // page. if (!theme_info.custom_background_url.is_empty()) { - ntp_text = RGBAColor{248, 249, 250, 255}; // GG050 + ntp_text = SkColorSetARGB(255, 248, 249, 250); // GG050 builder.Set("alternateLogo", true); builder.Set("customBackgroundConfigured", true); builder.Set("imageUrl", theme_info.custom_background_url.spec()); @@ -379,19 +369,15 @@ // Theme color for text as an array with the RGBA components in order. // Value is always valid. - builder.Set("textColorRgba", internal::RGBAColorToArray(isolate, ntp_text)); + builder.Set("textColorRgba", SkColorToArray(isolate, ntp_text)); // Generate fields for themeing NTP elements. - builder.Set( - "isNtpBackgroundDark", - internal::IsNtpBackgroundDark(internal::RGBAColorToSkColor(ntp_text))); + builder.Set("isNtpBackgroundDark", internal::IsNtpBackgroundDark(ntp_text)); builder.Set("useTitleContainer", crx_file::id_util::IdIsValid(theme_info.theme_id)); SkColor icon_color = internal::GetIconColor(theme_info); - builder.Set( - "iconBackgroundColor", - internal::RGBAColorToArray(isolate, SkColorToRGBAColor(icon_color))); + builder.Set("iconBackgroundColor", SkColorToArray(isolate, icon_color)); builder.Set("useWhiteAddIcon", color_utils::IsDark(icon_color)); return builder.Build();
diff --git a/chrome/renderer/searchbox/searchbox_extension_unittest.cc b/chrome/renderer/searchbox/searchbox_extension_unittest.cc index bec21b97..4317167 100644 --- a/chrome/renderer/searchbox/searchbox_extension_unittest.cc +++ b/chrome/renderer/searchbox/searchbox_extension_unittest.cc
@@ -55,7 +55,7 @@ ThemeBackgroundInfo theme_info; theme_info.using_default_theme = true; theme_info.using_dark_mode = false; - theme_info.background_color = RGBAColor(255, 0, 0, 255); // red + theme_info.background_color = SK_ColorRED; // // Default theme in light mode. EXPECT_EQ(kLightIconColor, GetIconColor(theme_info));
diff --git a/chrome/service/cloud_print/cloud_print_connector.cc b/chrome/service/cloud_print/cloud_print_connector.cc index 71cf5cf..b03bac3 100644 --- a/chrome/service/cloud_print/cloud_print_connector.cc +++ b/chrome/service/cloud_print/cloud_print_connector.cc
@@ -574,8 +574,8 @@ // continue in OnReceivePrinterCaps. print_system_->GetPrinterCapsAndDefaults( info.printer_name.c_str(), - base::Bind(&CloudPrintConnector::OnReceivePrinterCaps, - base::Unretained(this))); + base::BindOnce(&CloudPrintConnector::OnReceivePrinterCaps, + base::Unretained(this))); } void CloudPrintConnector::OnPrinterDelete(const std::string& printer_id) {
diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.cc b/chrome/service/cloud_print/cloud_print_proxy_backend.cc index 51b9079..05c1ed7 100644 --- a/chrome/service/cloud_print/cloud_print_proxy_backend.cc +++ b/chrome/service/cloud_print/cloud_print_proxy_backend.cc
@@ -129,7 +129,7 @@ CloudPrintProxyFrontend* frontend() { return backend_->frontend_; } bool PostFrontendTask(const base::Location& from_here, - const base::Closure& task); + base::OnceClosure task); bool CurrentlyOnFrontendThread() const; bool CurrentlyOnCoreThread() const; @@ -240,9 +240,10 @@ const std::string& cloud_print_token) { if (!core_thread_.Start()) return false; - PostCoreTask(FROM_HERE, - base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithToken, - core_, cloud_print_token)); + PostCoreTask( + FROM_HERE, + base::BindOnce(&CloudPrintProxyBackend::Core::DoInitializeWithToken, + core_, cloud_print_token)); return true; } @@ -253,8 +254,8 @@ return false; PostCoreTask( FROM_HERE, - base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithRobotToken, - core_, robot_oauth_refresh_token, robot_email)); + base::BindOnce(&CloudPrintProxyBackend::Core::DoInitializeWithRobotToken, + core_, robot_oauth_refresh_token, robot_email)); return true; } @@ -263,29 +264,30 @@ const std::string& robot_email) { if (!core_thread_.Start()) return false; - PostCoreTask( - FROM_HERE, - base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithRobotAuthCode, - core_, robot_oauth_auth_code, robot_email)); + PostCoreTask(FROM_HERE, + base::BindOnce( + &CloudPrintProxyBackend::Core::DoInitializeWithRobotAuthCode, + core_, robot_oauth_auth_code, robot_email)); return true; } void CloudPrintProxyBackend::Shutdown() { - PostCoreTask(FROM_HERE, base::Bind(&CloudPrintProxyBackend::Core::DoShutdown, - core_)); + PostCoreTask( + FROM_HERE, + base::BindOnce(&CloudPrintProxyBackend::Core::DoShutdown, core_)); core_thread_.Stop(); core_ = nullptr; // Releases reference to |core_|. } void CloudPrintProxyBackend::UnregisterPrinters() { PostCoreTask(FROM_HERE, - base::Bind(&CloudPrintProxyBackend::Core::DoUnregisterPrinters, - core_)); + base::BindOnce( + &CloudPrintProxyBackend::Core::DoUnregisterPrinters, core_)); } bool CloudPrintProxyBackend::PostCoreTask(const base::Location& from_here, - const base::Closure& task) { - return core_thread_.task_runner()->PostTask(from_here, task); + base::OnceClosure task) { + return core_thread_.task_runner()->PostTask(from_here, std::move(task)); } CloudPrintProxyBackend::Core::Core( @@ -308,8 +310,8 @@ bool CloudPrintProxyBackend::Core::PostFrontendTask( const base::Location& from_here, - const base::Closure& task) { - return backend_->frontend_task_runner_->PostTask(from_here, task); + base::OnceClosure task) { + return backend_->frontend_task_runner_->PostTask(from_here, std::move(task)); } bool CloudPrintProxyBackend::Core::CurrentlyOnFrontendThread() const { @@ -380,9 +382,9 @@ token_store->SetToken(access_token); robot_email_ = robot_email; // Let the frontend know that we have authenticated. - PostFrontendTask(FROM_HERE, base::Bind(&Core::NotifyAuthenticated, this, - robot_oauth_refresh_token, robot_email, - user_email)); + PostFrontendTask(FROM_HERE, base::BindOnce(&Core::NotifyAuthenticated, this, + robot_oauth_refresh_token, + robot_email, user_email)); if (first_time) { InitNotifications(robot_email, access_token); } else { @@ -397,8 +399,8 @@ if (!connector_->IsRunning()) { if (!connector_->Start()) { // Let the frontend know that we do not have a print system. - PostFrontendTask(FROM_HERE, - base::Bind(&Core::NotifyPrintSystemUnavailable, this)); + PostFrontendTask( + FROM_HERE, base::BindOnce(&Core::NotifyPrintSystemUnavailable, this)); } } } @@ -407,7 +409,7 @@ DCHECK(CurrentlyOnCoreThread()); VLOG(1) << "CP_CONNECTOR: Auth Error"; PostFrontendTask(FROM_HERE, - base::Bind(&Core::NotifyAuthenticationFailed, this)); + base::BindOnce(&Core::NotifyAuthenticationFailed, this)); } scoped_refptr<network::SharedURLLoaderFactory> @@ -435,8 +437,8 @@ void CloudPrintProxyBackend::Core::OnXmppPingUpdated(int ping_timeout) { settings_.SetXmppPingTimeoutSec(ping_timeout); - PostFrontendTask( - FROM_HERE, base::Bind(&Core::NotifyXmppPingUpdated, this, ping_timeout)); + PostFrontendTask(FROM_HERE, base::BindOnce(&Core::NotifyXmppPingUpdated, this, + ping_timeout)); } void CloudPrintProxyBackend::Core::InitNotifications( @@ -497,8 +499,8 @@ std::string access_token = GetTokenStore()->token(); std::list<std::string> printer_ids = connector_->GetPrinterIds(); - PostFrontendTask(FROM_HERE, base::Bind(&Core::NotifyUnregisterPrinters, this, - access_token, printer_ids)); + PostFrontendTask(FROM_HERE, base::BindOnce(&Core::NotifyUnregisterPrinters, + this, access_token, printer_ids)); } void CloudPrintProxyBackend::Core::HandlePrinterNotification(
diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.h b/chrome/service/cloud_print/cloud_print_proxy_backend.h index 845d5b65..4cc863a 100644 --- a/chrome/service/cloud_print/cloud_print_proxy_backend.h +++ b/chrome/service/cloud_print/cloud_print_proxy_backend.h
@@ -82,7 +82,7 @@ void UnregisterPrinters(); private: - bool PostCoreTask(const base::Location& from_here, const base::Closure& task); + bool PostCoreTask(const base::Location& from_here, base::OnceClosure task); // The real guts of CloudPrintProxyBackend, to keep the public client API // clean.
diff --git a/chrome/service/cloud_print/print_system.h b/chrome/service/cloud_print/print_system.h index 6e06bae1..33119bf 100644 --- a/chrome/service/cloud_print/print_system.h +++ b/chrome/service/cloud_print/print_system.h
@@ -156,10 +156,8 @@ std::string message_; }; - typedef base::Callback<void(bool, - const std::string&, - const printing::PrinterCapsAndDefaults&)> - PrinterCapsAndDefaultsCallback; + using PrinterCapsAndDefaultsCallback = base::OnceCallback< + void(bool, const std::string&, const printing::PrinterCapsAndDefaults&)>; // Initialize print system. This need to be called before any other function // of PrintSystem. @@ -172,7 +170,7 @@ // Gets the capabilities and defaults for a specific printer asynchronously. virtual void GetPrinterCapsAndDefaults( const std::string& printer_name, - const PrinterCapsAndDefaultsCallback& callback) = 0; + PrinterCapsAndDefaultsCallback callback) = 0; // Returns true if printer_name points to a valid printer. virtual bool IsValidPrinter(const std::string& printer_name) = 0;
diff --git a/chrome/service/cloud_print/print_system_cups.cc b/chrome/service/cloud_print/print_system_cups.cc index d38f5b1..a4d2bee 100644 --- a/chrome/service/cloud_print/print_system_cups.cc +++ b/chrome/service/cloud_print/print_system_cups.cc
@@ -86,7 +86,7 @@ printing::PrinterList* printer_list) override; void GetPrinterCapsAndDefaults( const std::string& printer_name, - const PrinterCapsAndDefaultsCallback& callback) override; + PrinterCapsAndDefaultsCallback callback) override; bool IsValidPrinter(const std::string& printer_name) override; bool ValidatePrintTicket(const std::string& printer_name, const std::string& print_ticket_data, @@ -164,7 +164,7 @@ // Helper method to invoke a PrinterCapsAndDefaultsCallback. static void RunCapsCallback( - const PrinterCapsAndDefaultsCallback& callback, + PrinterCapsAndDefaultsCallback callback, bool succeeded, const std::string& printer_name, const printing::PrinterCapsAndDefaults& printer_info); @@ -512,12 +512,13 @@ void PrintSystemCUPS::GetPrinterCapsAndDefaults( const std::string& printer_name, - const PrinterCapsAndDefaultsCallback& callback) { + PrinterCapsAndDefaultsCallback callback) { printing::PrinterCapsAndDefaults printer_info; bool succeeded = GetPrinterCapsAndDefaults(printer_name, &printer_info); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&PrintSystemCUPS::RunCapsCallback, callback, - succeeded, printer_name, printer_info)); + FROM_HERE, + base::BindOnce(&PrintSystemCUPS::RunCapsCallback, std::move(callback), + succeeded, printer_name, printer_info)); } bool PrintSystemCUPS::IsValidPrinter(const std::string& printer_name) { @@ -852,11 +853,11 @@ } void PrintSystemCUPS::RunCapsCallback( - const PrinterCapsAndDefaultsCallback& callback, + PrinterCapsAndDefaultsCallback callback, bool succeeded, const std::string& printer_name, const printing::PrinterCapsAndDefaults& printer_info) { - callback.Run(succeeded, printer_name, printer_info); + std::move(callback).Run(succeeded, printer_name, printer_info); } } // namespace cloud_print
diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc index 580982c..3274b13 100644 --- a/chrome/service/cloud_print/print_system_win.cc +++ b/chrome/service/cloud_print/print_system_win.cc
@@ -538,11 +538,9 @@ // request to fetch printer capabilities and defaults. class PrinterCapsHandler : public ServiceUtilityProcessHost::Client { public: - PrinterCapsHandler( - const std::string& printer_name, - const PrintSystem::PrinterCapsAndDefaultsCallback& callback) - : printer_name_(printer_name), callback_(callback) { - } + PrinterCapsHandler(const std::string& printer_name, + PrintSystem::PrinterCapsAndDefaultsCallback callback) + : printer_name_(printer_name), callback_(std::move(callback)) {} // ServiceUtilityProcessHost::Client implementation. void OnChildDied() override { @@ -554,8 +552,7 @@ bool succeeded, const std::string& printer_name, const printing::PrinterCapsAndDefaults& caps_and_defaults) override { - callback_.Run(succeeded, printer_name, caps_and_defaults); - callback_.Reset(); + std::move(callback_).Run(succeeded, printer_name, caps_and_defaults); Release(); } @@ -571,8 +568,7 @@ base::JSONWriter::OPTIONS_PRETTY_PRINT, &printer_info.printer_capabilities); } - callback_.Run(succeeded, printer_name, printer_info); - callback_.Reset(); + std::move(callback_).Run(succeeded, printer_name, printer_info); Release(); } @@ -595,7 +591,7 @@ ~PrinterCapsHandler() override {} void GetPrinterCapsAndDefaultsImpl( - const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner) { + scoped_refptr<base::SingleThreadTaskRunner> client_task_runner) { DCHECK(CurrentlyOnServiceIOThread()); auto utility_host = std::make_unique<ServiceUtilityProcessHost>( this, client_task_runner.get()); @@ -609,7 +605,7 @@ } void GetPrinterSemanticCapsAndDefaultsImpl( - const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner) { + scoped_refptr<base::SingleThreadTaskRunner> client_task_runner) { DCHECK(CurrentlyOnServiceIOThread()); auto utility_host = std::make_unique<ServiceUtilityProcessHost>( this, client_task_runner.get()); @@ -636,7 +632,7 @@ printing::PrinterList* printer_list) override; void GetPrinterCapsAndDefaults( const std::string& printer_name, - const PrinterCapsAndDefaultsCallback& callback) override; + PrinterCapsAndDefaultsCallback callback) override; bool IsValidPrinter(const std::string& printer_name) override; bool ValidatePrintTicket( const std::string& printer_name, @@ -692,11 +688,12 @@ void PrintSystemWin::GetPrinterCapsAndDefaults( const std::string& printer_name, - const PrinterCapsAndDefaultsCallback& callback) { + PrinterCapsAndDefaultsCallback callback) { // Launch as child process to retrieve the capabilities and defaults because // this involves invoking a printer driver DLL and crashes have been known to // occur. - PrinterCapsHandler* handler = new PrinterCapsHandler(printer_name, callback); + PrinterCapsHandler* handler = + new PrinterCapsHandler(printer_name, std::move(callback)); handler->AddRef(); if (use_cdd_) handler->StartGetPrinterSemanticCapsAndDefaults();
diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc index adae1ca..cebf58c08 100644 --- a/chrome/service/cloud_print/printer_job_handler.cc +++ b/chrome/service/cloud_print/printer_job_handler.cc
@@ -652,8 +652,8 @@ // continue in OnReceivePrinterCaps. print_system_->GetPrinterCapsAndDefaults( printer_info.printer_name, - base::Bind(&PrinterJobHandler::OnReceivePrinterCaps, - weak_ptr_factory_.GetWeakPtr())); + base::BindOnce(&PrinterJobHandler::OnReceivePrinterCaps, + weak_ptr_factory_.GetWeakPtr())); // While we are waiting for the data, pretend we have work to do and return // true.
diff --git a/chrome/service/cloud_print/printer_job_handler_unittest.cc b/chrome/service/cloud_print/printer_job_handler_unittest.cc index 814e686..15160ca 100644 --- a/chrome/service/cloud_print/printer_job_handler_unittest.cc +++ b/chrome/service/cloud_print/printer_job_handler_unittest.cc
@@ -410,10 +410,9 @@ MOCK_METHOD1(EnumeratePrinters, PrintSystem::PrintSystemResult( printing::PrinterList* printer_list)); - MOCK_METHOD2( - GetPrinterCapsAndDefaults, - void(const std::string& printer_name, - const PrintSystem::PrinterCapsAndDefaultsCallback& callback)); + MOCK_METHOD2(GetPrinterCapsAndDefaults, + void(const std::string& printer_name, + PrintSystem::PrinterCapsAndDefaultsCallback callback)); MOCK_METHOD1(IsValidPrinter, bool(const std::string& printer_name)); @@ -456,7 +455,7 @@ bool GetPrinterInfo(printing::PrinterBasicInfo* info); void SendCapsAndDefaults( const std::string& printer_name, - const PrintSystem::PrinterCapsAndDefaultsCallback& callback); + PrintSystem::PrinterCapsAndDefaultsCallback callback); void AddMimeHeader(const GURL& url, net::FakeURLFetcher* fetcher); void AddTicketMimeHeader(const GURL& url, net::FakeURLFetcher* fetcher); bool PostSpoolSuccess(); @@ -522,9 +521,9 @@ } PrinterJobHandlerTest::PrinterJobHandlerTest() - : factory_(NULL, base::Bind(&TestURLFetcherCallback::CreateURLFetcher, - base::Unretained(&url_callback_))) { -} + : factory_(nullptr, + base::BindRepeating(&TestURLFetcherCallback::CreateURLFetcher, + base::Unretained(&url_callback_))) {} bool PrinterJobHandlerTest::PostSpoolSuccess() { base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -614,8 +613,8 @@ void PrinterJobHandlerTest::SendCapsAndDefaults( const std::string& printer_name, - const PrintSystem::PrinterCapsAndDefaultsCallback& callback) { - callback.Run(true, printer_name, caps_and_defaults_); + PrintSystem::PrinterCapsAndDefaultsCallback callback) { + std::move(callback).Run(true, printer_name, caps_and_defaults_); } bool PrinterJobHandlerTest::GetPrinterInfo(printing::PrinterBasicInfo* info) {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 2704474..ccc40be 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3051,6 +3051,7 @@ "../browser/sessions/chrome_serialized_navigation_driver_unittest.cc", "../browser/sessions/restore_on_startup_policy_handler_unittest.cc", "../browser/sessions/session_common_utils_unittest.cc", + "../browser/sharing/sharing_sync_preference_unittest.cc", "../browser/shell_integration_win_unittest.cc", "../browser/signin/account_consistency_mode_manager_unittest.cc", "../browser/signin/chrome_device_id_helper_unittest.cc",
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 45f8c1b5..07833926 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -3103,18 +3103,6 @@ ] }, - "DockedMagnifierEnabled": { - "os": ["chromeos"], - "test_policy": { "DockedMagnifierEnabled": true }, - "pref_mappings": [ - { "pref": "ash.docked_magnifier.enabled", - "indicator_tests": [ - { "policy": { "DockedMagnifierEnabled": true } } - ] - } - ] - }, - "SpokenFeedbackEnabled": { "os": ["chromeos"], "test_policy": { "SpokenFeedbackEnabled": true }, @@ -3148,7 +3136,8 @@ { "policy": { "ScreenMagnifierType": 1 } } ] }, - { "pref": "settings.a11y.screen_magnifier" } + { "pref": "settings.a11y.screen_magnifier" }, + { "pref": "ash.docked_magnifier.enabled" } ] },
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index 13f7dff8..9cf8952 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -189,20 +189,20 @@ </message> <!-- Password expiry notifications --> - <message name="IDS_PASSWORD_HAS_EXPIRED_TITLE" desc="Title for a notification that tells the user their password has expired."> - Password has expired - </message> - <message name="IDS_PASSWORD_WILL_EXPIRE_TITLE" desc="Title for a notification that tells the user their password will soon expire."> - Password will soon expire - </message> <message name="IDS_PASSWORD_EXPIRY_DAYS_BODY" desc="Message body for a notification that tells the user their password will expire in less than some number of days (where 0 days means it has expired)."> {NUM_DAYS, plural, =0 {Your current password has expired!} =1 {Your current password will expire in less than one day!} other {Your current password will expire in less than # days!}} </message> - <message name="IDS_PASSWORD_EXPIRY_CHOOSE_NEW_PASSWORD_LINK" desc="Added to the message body on a notification to explain that clicking the notification will open a dialog where a new password can be chosen."> - Click here to choose a new password + <message name="IDS_PASSWORD_EXPIRY_CALL_TO_ACTION" desc="Message body on a notification that politely requests the user to choose a new password since their old password is expiring soon"> + Please choose a new password now + </message> + <message name="IDS_PASSWORD_EXPIRY_CALL_TO_ACTION_CRITICAL" desc="Message body on a notification that *URGENTLY* requests the user to choose a new password since their old password is expiring *VERY* soon"> + Please choose a new password immediately + </message> + <message name="IDS_PASSWORD_EXPIRY_CHANGE_PASSWORD_BUTTON" desc="Text on a button that takes the user to page to change their password"> + Change password </message> <message name="IDS_IME_SERVICE_DISPLAY_NAME" desc="The display name (in the system task manager, etc) of the service process providing the input methods.">
diff --git a/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CALL_TO_ACTION.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CALL_TO_ACTION.png.sha1 new file mode 100644 index 0000000..aa7a50f --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CALL_TO_ACTION.png.sha1
@@ -0,0 +1 @@ +84a5296d18c190df2b50e6ce25a54ddbc4c5f9d4 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CALL_TO_ACTION_CRITICAL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CALL_TO_ACTION_CRITICAL.png.sha1 new file mode 100644 index 0000000..f63998d8 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CALL_TO_ACTION_CRITICAL.png.sha1
@@ -0,0 +1 @@ +0372073a130db8f34c558f2215c6832e55810802 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CHANGE_PASSWORD_BUTTON.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CHANGE_PASSWORD_BUTTON.png.sha1 new file mode 100644 index 0000000..2e432ea --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CHANGE_PASSWORD_BUTTON.png.sha1
@@ -0,0 +1 @@ +e75101e417eef40b95dcbbbe80135048c41244d8 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CHOOSE_NEW_PASSWORD_LINK.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CHOOSE_NEW_PASSWORD_LINK.png.sha1 deleted file mode 100644 index 230f66f..0000000 --- a/chromeos/chromeos_strings_grd/IDS_PASSWORD_EXPIRY_CHOOSE_NEW_PASSWORD_LINK.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -9d1f66e08d707cc3babe1c353f4417b650a71e10 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_PASSWORD_HAS_EXPIRED_TITLE.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PASSWORD_HAS_EXPIRED_TITLE.png.sha1 deleted file mode 100644 index f8ddd69..0000000 --- a/chromeos/chromeos_strings_grd/IDS_PASSWORD_HAS_EXPIRED_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -e7ea394b117193e4506f11bb87d47e88dad64a97 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_PASSWORD_WILL_EXPIRE_TITLE.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PASSWORD_WILL_EXPIRE_TITLE.png.sha1 deleted file mode 100644 index 6a2d8e0..0000000 --- a/chromeos/chromeos_strings_grd/IDS_PASSWORD_WILL_EXPIRE_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -54f9f5c62799b5a050152f23982b4eb275ee1e4c \ No newline at end of file
diff --git a/components/autofill/core/browser/geo/phone_number_i18n.cc b/components/autofill/core/browser/geo/phone_number_i18n.cc index d0ea183..3853bfe0 100644 --- a/components/autofill/core/browser/geo/phone_number_i18n.cc +++ b/components/autofill/core/browser/geo/phone_number_i18n.cc
@@ -265,7 +265,13 @@ const base::string16& number_b, const std::string& raw_region, const std::string& app_locale) { - // TODO(crbug.com/953678): Maybe return true if two empty strings are given. + if (number_a.empty() && number_b.empty()) { + return true; + } + + if (number_a.empty() || number_b.empty()) { + return false; + } // Sanitize the provided |raw_region| before trying to use it for parsing. const std::string region = SanitizeRegion(raw_region, app_locale);
diff --git a/components/autofill/core/browser/geo/phone_number_i18n_unittest.cc b/components/autofill/core/browser/geo/phone_number_i18n_unittest.cc index bb6b574..afcf07b 100644 --- a/components/autofill/core/browser/geo/phone_number_i18n_unittest.cc +++ b/components/autofill/core/browser/geo/phone_number_i18n_unittest.cc
@@ -253,6 +253,14 @@ // Different numbers don't match. EXPECT_FALSE(PhoneNumbersMatch(ASCIIToUTF16("14158889999"), ASCIIToUTF16("1415888"), "US", "en-US")); + + // Two empty numbers match. + EXPECT_TRUE( + PhoneNumbersMatch(base::string16(), base::string16(), "US", "en-US")); + + // An empty and a non-empty number do not match. + EXPECT_FALSE(PhoneNumbersMatch(base::string16(), ASCIIToUTF16("5088585123"), + "US", "en-US")); } // Tests that the phone numbers are correctly formatted for the Payment
diff --git a/components/invalidation/impl/fcm_invalidation_service.cc b/components/invalidation/impl/fcm_invalidation_service.cc index 236ffd49..78e04a86 100644 --- a/components/invalidation/impl/fcm_invalidation_service.cc +++ b/components/invalidation/impl/fcm_invalidation_service.cc
@@ -94,6 +94,15 @@ identity_provider_->AddObserver(this); } +// static +void FCMInvalidationService::RegisterPrefs(PrefRegistrySimple* registry) { + registry->RegisterStringPref( + invalidation::prefs::kFCMInvalidationClientIDCacheDeprecated, + /*default_value=*/std::string()); + registry->RegisterDictionaryPref( + invalidation::prefs::kInvalidationClientIDCache); +} + void FCMInvalidationService::InitForTest(syncer::Invalidator* invalidator) { // Here we perform the equivalent of Init() and StartInvalidator(), but with // some minor changes to account for the fact that we're injecting the
diff --git a/components/invalidation/impl/fcm_invalidation_service.h b/components/invalidation/impl/fcm_invalidation_service.h index d08dc45..484a05a 100644 --- a/components/invalidation/impl/fcm_invalidation_service.h +++ b/components/invalidation/impl/fcm_invalidation_service.h
@@ -22,6 +22,7 @@ } class PrefService; +class PrefRegistrySimple; namespace syncer { class Invalidator; @@ -50,6 +51,8 @@ void Init(); + static void RegisterPrefs(PrefRegistrySimple* registry); + // InvalidationService implementation. // It is an error to have registered handlers when the service is destroyed. void RegisterInvalidationHandler(
diff --git a/components/invalidation/impl/invalidator_registrar_with_memory.cc b/components/invalidation/impl/invalidator_registrar_with_memory.cc index 3354264..2d1b23cf 100644 --- a/components/invalidation/impl/invalidator_registrar_with_memory.cc +++ b/components/invalidation/impl/invalidator_registrar_with_memory.cc
@@ -49,6 +49,13 @@ registry->RegisterDictionaryPref(kTopicsToHandler); } +// static +void InvalidatorRegistrarWithMemory::RegisterPrefs( + PrefRegistrySimple* registry) { + registry->RegisterDictionaryPref(kTopicsToHandlerDeprecated); + registry->RegisterDictionaryPref(kTopicsToHandler); +} + InvalidatorRegistrarWithMemory::InvalidatorRegistrarWithMemory( PrefService* local_state, const std::string& sender_id,
diff --git a/components/invalidation/impl/invalidator_registrar_with_memory.h b/components/invalidation/impl/invalidator_registrar_with_memory.h index 4c3c672..61ebbcf8 100644 --- a/components/invalidation/impl/invalidator_registrar_with_memory.h +++ b/components/invalidation/impl/invalidator_registrar_with_memory.h
@@ -37,7 +37,14 @@ // It is an error to have registered handlers on destruction. ~InvalidatorRegistrarWithMemory(); + // RegisterProfilePrefs and RegisterPrefs register the same prefs, because on + // device level (sign in screen, device local account) we spin up separate + // InvalidationService and on profile level (when user signed in) we have + // another InvalidationService, and we want to keep profile data in an + // encrypted area of disk. While device data which is public can be kept in an + // unencrypted area. static void RegisterProfilePrefs(PrefRegistrySimple* registry); + static void RegisterPrefs(PrefRegistrySimple* registry); // Updates the set of topics associated with |handler|. |handler| must // not be NULL, and must already be registered. A topic must be registered
diff --git a/components/invalidation/impl/per_user_topic_registration_manager.cc b/components/invalidation/impl/per_user_topic_registration_manager.cc index 5fce914..308254f3 100644 --- a/components/invalidation/impl/per_user_topic_registration_manager.cc +++ b/components/invalidation/impl/per_user_topic_registration_manager.cc
@@ -139,6 +139,17 @@ registry->RegisterDictionaryPref(kActiveRegistrationTokens); } +// static +void PerUserTopicRegistrationManager::RegisterPrefs( + PrefRegistrySimple* registry) { + registry->RegisterDictionaryPref(kTypeRegisteredForInvalidationsDeprecated); + registry->RegisterStringPref(kActiveRegistrationTokenDeprecated, + std::string()); + + registry->RegisterDictionaryPref(kTypeRegisteredForInvalidations); + registry->RegisterDictionaryPref(kActiveRegistrationTokens); +} + struct PerUserTopicRegistrationManager::RegistrationEntry { RegistrationEntry(const Topic& id, SubscriptionFinishedCallback completion_callback,
diff --git a/components/invalidation/impl/per_user_topic_registration_manager.h b/components/invalidation/impl/per_user_topic_registration_manager.h index a47158e..2dbac6c 100644 --- a/components/invalidation/impl/per_user_topic_registration_manager.h +++ b/components/invalidation/impl/per_user_topic_registration_manager.h
@@ -60,7 +60,14 @@ virtual ~PerUserTopicRegistrationManager(); + // RegisterProfilePrefs and RegisterPrefs register the same prefs, because on + // device level (sign in screen, device local account) we spin up separate + // InvalidationService and on profile level (when user signed in) we have + // another InvalidationService, and we want to keep profile data in an + // encrypted area of disk. While device data which is public can be kept in an + // unencrypted area. static void RegisterProfilePrefs(PrefRegistrySimple* registry); + static void RegisterPrefs(PrefRegistrySimple* registry); virtual void UpdateRegisteredTopics(const Topics& ids, const std::string& token);
diff --git a/components/invalidation/public/invalidation_util.cc b/components/invalidation/public/invalidation_util.cc index 4bcfbc83..04ce11d 100644 --- a/components/invalidation/public/invalidation_util.cc +++ b/components/invalidation/public/invalidation_util.cc
@@ -22,12 +22,12 @@ const char kSourceKey[] = "source"; const char kNameKey[] = "name"; -const int kDeprecatedSource = 2000; - } // namespace namespace syncer { +const int kDeprecatedSourceForFCM = 2000; + bool ObjectIdLessThan::operator()(const invalidation::ObjectId& lhs, const invalidation::ObjectId& rhs) const { return (lhs.source() < rhs.source()) || @@ -153,19 +153,19 @@ ObjectIdSet ConvertTopicsToIds(TopicSet topics) { ObjectIdSet ids; for (const auto& topic : topics) - ids.insert(invalidation::ObjectId(kDeprecatedSource, topic)); + ids.insert(invalidation::ObjectId(kDeprecatedSourceForFCM, topic)); return ids; } ObjectIdSet ConvertTopicsToIds(Topics topics) { ObjectIdSet ids; for (const auto& topic : topics) - ids.insert(invalidation::ObjectId(kDeprecatedSource, topic.first)); + ids.insert(invalidation::ObjectId(kDeprecatedSourceForFCM, topic.first)); return ids; } invalidation::ObjectId ConvertTopicToId(const Topic& topic) { - return invalidation::ObjectId(kDeprecatedSource, topic); + return invalidation::ObjectId(kDeprecatedSourceForFCM, topic); } HandlerOwnerType OwnerNameToHandlerType(const std::string& owner_name) {
diff --git a/components/invalidation/public/invalidation_util.h b/components/invalidation/public/invalidation_util.h index b50abfb3..6baa7b6 100644 --- a/components/invalidation/public/invalidation_util.h +++ b/components/invalidation/public/invalidation_util.h
@@ -28,6 +28,14 @@ namespace syncer { +// FCMInvalidationService and deprecated TiclInvalidationService uses ObjectId +// to keep track of objects to invalidate. There are 2 fields in ObjectId: +// source and name. TiclInvalidationService expects both of them, while +// FCMInvalidationService only works with the name. So InvalidationService +// assigns the value of source to kDeprecatedSourceForFCM when FCM (Firebase +// Cloud Messaging) is enabled. +extern const int kDeprecatedSourceForFCM; + // Used by UMA histogram, so entries shouldn't be reordered or removed. enum class HandlerOwnerType { kCloud = 0,
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc index 1401a59..dbb1249 100644 --- a/components/password_manager/core/browser/login_database.cc +++ b/components/password_manager/core/browser/login_database.cc
@@ -1041,11 +1041,19 @@ return list; } -PasswordStoreChangeList LoginDatabase::UpdateLogin(const PasswordForm& form) { +PasswordStoreChangeList LoginDatabase::UpdateLogin(const PasswordForm& form, + UpdateLoginError* error) { + if (error) { + *error = UpdateLoginError::kNone; + } std::string encrypted_password; if (EncryptedString(form.password_value, &encrypted_password) != - ENCRYPTION_RESULT_SUCCESS) + ENCRYPTION_RESULT_SUCCESS) { + if (error) { + *error = UpdateLoginError::kEncrytionServiceFailure; + } return PasswordStoreChangeList(); + } #if defined(OS_IOS) DeleteEncryptedPassword(form); @@ -1093,12 +1101,19 @@ // NOTE: Add new fields here only if the field is a part of the unique key. // Otherwise, add the field above "WHERE starts here" comment. - if (!s.Run()) + if (!s.Run()) { + if (error) { + *error = UpdateLoginError::kDbError; + } return PasswordStoreChangeList(); + } PasswordStoreChangeList list; - if (db_.GetLastChangeCount()) + if (db_.GetLastChangeCount()) { list.emplace_back(PasswordStoreChange::UPDATE, form, GetPrimaryKey(form)); + } else if (error) { + *error = UpdateLoginError::kNoUpdatedRecords; + } return list; }
diff --git a/components/password_manager/core/browser/login_database.h b/components/password_manager/core/browser/login_database.h index 616818ea..fe9a72f3 100644 --- a/components/password_manager/core/browser/login_database.h +++ b/components/password_manager/core/browser/login_database.h
@@ -77,11 +77,13 @@ PasswordStoreChangeList AddBlacklistedLoginForTesting( const autofill::PasswordForm& form) WARN_UNUSED_RESULT; - // Updates existing password form. Returns the list of applied changes - // ({}, {UPDATE}). The password is looked up by the tuple {origin, - // username_element, username_value, password_element, signon_realm}. - // These columns stay intact. - PasswordStoreChangeList UpdateLogin(const autofill::PasswordForm& form) + // Updates existing password form. Returns the list of applied changes ({}, + // {UPDATE}). The password is looked up by the tuple {origin, + // username_element, username_value, password_element, signon_realm}. These + // columns stay intact. In case of error, it sets |error| if |error| isn't + // null. + PasswordStoreChangeList UpdateLogin(const autofill::PasswordForm& form, + UpdateLoginError* error = nullptr) WARN_UNUSED_RESULT; // Removes |form| from the list of remembered password forms. Returns true if
diff --git a/components/password_manager/core/browser/mock_password_store.h b/components/password_manager/core/browser/mock_password_store.h index 9f36ae10..b7d28b2 100644 --- a/components/password_manager/core/browser/mock_password_store.h +++ b/components/password_manager/core/browser/mock_password_store.h
@@ -32,8 +32,9 @@ MOCK_METHOD2(AddLoginImpl, PasswordStoreChangeList(const autofill::PasswordForm&, AddLoginError* error)); - MOCK_METHOD1(UpdateLoginImpl, - PasswordStoreChangeList(const autofill::PasswordForm&)); + MOCK_METHOD2(UpdateLoginImpl, + PasswordStoreChangeList(const autofill::PasswordForm&, + UpdateLoginError* error)); MOCK_METHOD1(RemoveLoginImpl, PasswordStoreChangeList(const autofill::PasswordForm&)); MOCK_METHOD3(RemoveLoginsByURLAndTimeImpl,
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 42fa7d6b..f38a26c 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -552,7 +552,8 @@ } PasswordStoreChangeList PasswordStore::UpdateLoginSync( - const PasswordForm& form) { + const PasswordForm& form, + UpdateLoginError* error) { if (AffiliatedMatchHelper::IsValidAndroidCredential( PasswordStore::FormDigest(form))) { // Ideally, a |form| would not be updated in any way unless it was ensured @@ -566,7 +567,7 @@ if (old_form && form.password_value != old_form->password_value) ScheduleFindAndUpdateAffiliatedWebLogins(form); } - return UpdateLoginImpl(form); + return UpdateLoginImpl(form, error); } PasswordStoreChangeList PasswordStore::RemoveLoginSync(
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h index 847e82d..e471931 100644 --- a/components/password_manager/core/browser/password_store.h +++ b/components/password_manager/core/browser/password_store.h
@@ -394,7 +394,8 @@ // Synchronous implementation provided by subclasses to update the given // login. virtual PasswordStoreChangeList UpdateLoginImpl( - const autofill::PasswordForm& form) = 0; + const autofill::PasswordForm& form, + UpdateLoginError* error = nullptr) = 0; // Synchronous implementation provided by subclasses to remove the given // login. @@ -423,8 +424,8 @@ // PasswordStoreSync: PasswordStoreChangeList AddLoginSync(const autofill::PasswordForm& form, AddLoginError* error) override; - PasswordStoreChangeList UpdateLoginSync( - const autofill::PasswordForm& form) override; + PasswordStoreChangeList UpdateLoginSync(const autofill::PasswordForm& form, + UpdateLoginError* error) override; PasswordStoreChangeList RemoveLoginSync( const autofill::PasswordForm& form) override;
diff --git a/components/password_manager/core/browser/password_store_default.cc b/components/password_manager/core/browser/password_store_default.cc index 94318ba..f7ed5ff 100644 --- a/components/password_manager/core/browser/password_store_default.cc +++ b/components/password_manager/core/browser/password_store_default.cc
@@ -68,11 +68,16 @@ } PasswordStoreChangeList PasswordStoreDefault::UpdateLoginImpl( - const PasswordForm& form) { + const PasswordForm& form, + UpdateLoginError* error) { DCHECK(background_task_runner()->RunsTasksInCurrentSequence()); - if (!login_db_) + if (!login_db_) { + if (error) { + *error = UpdateLoginError::kDbNotAvailable; + } return PasswordStoreChangeList(); - return login_db_->UpdateLogin(form); + } + return login_db_->UpdateLogin(form, error); } PasswordStoreChangeList PasswordStoreDefault::RemoveLoginImpl(
diff --git a/components/password_manager/core/browser/password_store_default.h b/components/password_manager/core/browser/password_store_default.h index e4fbb5d..20a5794 100644 --- a/components/password_manager/core/browser/password_store_default.h +++ b/components/password_manager/core/browser/password_store_default.h
@@ -48,9 +48,9 @@ void ReportMetricsImpl(const std::string& sync_username, bool custom_passphrase_sync_enabled) override; PasswordStoreChangeList AddLoginImpl(const autofill::PasswordForm& form, - AddLoginError* error = nullptr) override; - PasswordStoreChangeList UpdateLoginImpl( - const autofill::PasswordForm& form) override; + AddLoginError* error) override; + PasswordStoreChangeList UpdateLoginImpl(const autofill::PasswordForm& form, + UpdateLoginError* error) override; PasswordStoreChangeList RemoveLoginImpl( const autofill::PasswordForm& form) override; PasswordStoreChangeList RemoveLoginsByURLAndTimeImpl(
diff --git a/components/password_manager/core/browser/password_store_sync.h b/components/password_manager/core/browser/password_store_sync.h index e0455fc..0640c1c3 100644 --- a/components/password_manager/core/browser/password_store_sync.h +++ b/components/password_manager/core/browser/password_store_sync.h
@@ -68,6 +68,27 @@ kMaxValue = kDbError, }; +// Error values for updating a login in the store. +// Used in metrics: "PasswordManager.MergeSyncData.UpdateLoginSyncError" and +// "PasswordManager.ApplySyncChanges.UpdateLoginSyncError". These values are +// persisted to logs. Entries should not be renumbered and numeric values should +// never be reused. +enum class UpdateLoginError { + // Success. + kNone = 0, + // Database not available. + kDbNotAvailable = 1, + // No records were updated. + kNoUpdatedRecords = 2, + // A service-level failure (e.g., on a platform using a keyring, the keyring + // is temporarily unavailable). + kEncrytionServiceFailure = 3, + // Database error. + kDbError = 4, + + kMaxValue = kDbError, +}; + // PasswordStore interface for PasswordSyncableService. It provides access to // synchronous methods of PasswordStore which shouldn't be accessible to other // classes. These methods are to be called on the PasswordStore background @@ -114,7 +135,8 @@ // Synchronous implementation to update the given login. virtual PasswordStoreChangeList UpdateLoginSync( - const autofill::PasswordForm& form) = 0; + const autofill::PasswordForm& form, + UpdateLoginError* error = nullptr) = 0; // Synchronous implementation to remove the given login. virtual PasswordStoreChangeList RemoveLoginSync(
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc index 41cc43c..fd60f5c 100644 --- a/components/password_manager/core/browser/password_store_unittest.cc +++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -705,9 +705,9 @@ IgnoreResult(&PasswordStore::AddLoginSync), store, *expected_credentials_after_update[0], /*error=*/nullptr)); } else { - store->ScheduleTask( - base::BindOnce(IgnoreResult(&PasswordStore::UpdateLoginSync), store, - *expected_credentials_after_update[0])); + store->ScheduleTask(base::BindOnce( + IgnoreResult(&PasswordStore::UpdateLoginSync), store, + *expected_credentials_after_update[0], /*error=*/nullptr)); } WaitForPasswordStore(); store->RemoveObserver(&mock_observer);
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.cc b/components/password_manager/core/browser/sync/password_sync_bridge.cc index c2b8029..76d55a7 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge.cc +++ b/components/password_manager/core/browser/sync/password_sync_bridge.cc
@@ -392,10 +392,15 @@ std::move(local_form_entity_data), metadata_change_list.get()); } else { // The remote password is more recent, update the local model. - PasswordStoreChangeList changes = - password_store_sync_->UpdateLoginSync(PasswordFromEntityChange( - remote_entity_change, /*sync_time=*/time_now)); + UpdateLoginError update_login_error; + PasswordStoreChangeList changes = password_store_sync_->UpdateLoginSync( + PasswordFromEntityChange(remote_entity_change, + /*sync_time=*/time_now), + &update_login_error); DCHECK_LE(changes.size(), 1U); + base::UmaHistogramEnumeration( + "PasswordManager.MergeSyncData.UpdateLoginSyncError", + update_login_error); if (changes.empty()) { metrics_util::LogPasswordSyncState( metrics_util::NOT_SYNCING_FAILED_UPDATE); @@ -578,8 +583,13 @@ if (entity_change->storage_key().empty()) { continue; } + UpdateLoginError update_login_error; changes = password_store_sync_->UpdateLoginSync( - PasswordFromEntityChange(*entity_change, /*sync_time=*/time_now)); + PasswordFromEntityChange(*entity_change, /*sync_time=*/time_now), + &update_login_error); + base::UmaHistogramEnumeration( + "PasswordManager.ApplySyncChanges.UpdateLoginSyncError", + update_login_error); if (changes.empty()) { metrics_util::LogApplySyncChangesState( metrics_util::ApplySyncChangesState::kApplyUpdateFailed);
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc index 38a07ac0..726ddae 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc +++ b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
@@ -140,7 +140,11 @@ return {PasswordStoreChange(PasswordStoreChange::ADD, form, primary_key)}; } - PasswordStoreChangeList UpdateLogin(const autofill::PasswordForm& form) { + PasswordStoreChangeList UpdateLogin(const autofill::PasswordForm& form, + UpdateLoginError* error) { + if (error) { + *error = UpdateLoginError::kNone; + } int key = GetPrimaryKey(form); DCHECK_NE(-1, key); data_[key] = std::make_unique<autofill::PasswordForm>(form); @@ -205,8 +209,9 @@ MOCK_METHOD2(AddLoginSync, PasswordStoreChangeList(const autofill::PasswordForm&, AddLoginError*)); - MOCK_METHOD1(UpdateLoginSync, - PasswordStoreChangeList(const autofill::PasswordForm&)); + MOCK_METHOD2(UpdateLoginSync, + PasswordStoreChangeList(const autofill::PasswordForm&, + UpdateLoginError*)); MOCK_METHOD1(RemoveLoginSync, PasswordStoreChangeList(const autofill::PasswordForm&)); MOCK_METHOD1(NotifyLoginsChanged, void(const PasswordStoreChangeList&)); @@ -227,7 +232,7 @@ .WillByDefault(Invoke(&fake_db_, &FakeDatabase::ReadAllLogins)); ON_CALL(mock_password_store_sync_, AddLoginSync(_, _)) .WillByDefault(Invoke(&fake_db_, &FakeDatabase::AddLogin)); - ON_CALL(mock_password_store_sync_, UpdateLoginSync(_)) + ON_CALL(mock_password_store_sync_, UpdateLoginSync(_, _)) .WillByDefault(Invoke(&fake_db_, &FakeDatabase::UpdateLogin)); ON_CALL(mock_password_store_sync_, RemoveLoginByPrimaryKeySync(_)) .WillByDefault(Invoke(&fake_db_, &FakeDatabase::RemoveLogin)); @@ -443,7 +448,7 @@ testing::InSequence in_sequence; EXPECT_CALL(*mock_password_store_sync(), BeginTransaction()); EXPECT_CALL(*mock_password_store_sync(), - UpdateLoginSync(FormHasSignonRealm(kSignonRealm1))); + UpdateLoginSync(FormHasSignonRealm(kSignonRealm1), _)); EXPECT_CALL(*mock_password_store_sync(), CommitTransaction()); EXPECT_CALL(*mock_password_store_sync(), NotifyLoginsChanged( @@ -569,7 +574,7 @@ .InSequence(s2); EXPECT_CALL(*mock_password_store_sync(), - UpdateLoginSync(FormHasSignonRealm(kSignonRealm2))) + UpdateLoginSync(FormHasSignonRealm(kSignonRealm2), _)) .InSequence(s3); EXPECT_CALL(*mock_password_store_sync(), @@ -645,7 +650,7 @@ // Since the remote Form 2 is more recent, it will be updated in the password // store. EXPECT_CALL(*mock_password_store_sync(), - UpdateLoginSync(FormHasSignonRealm(kSignonRealm2))); + UpdateLoginSync(FormHasSignonRealm(kSignonRealm2), _)); syncer::EntityChangeList entity_change_list; entity_change_list.push_back(syncer::EntityChange::CreateAdd( /*storage_key=*/"", SpecificsToEntity(specifics1)));
diff --git a/components/password_manager/core/browser/sync/password_syncable_service.cc b/components/password_manager/core/browser/sync/password_syncable_service.cc index f55a7a3..e60f079 100644 --- a/components/password_manager/core/browser/sync/password_syncable_service.cc +++ b/components/password_manager/core/browser/sync/password_syncable_service.cc
@@ -385,8 +385,18 @@ for (const std::unique_ptr<autofill::PasswordForm>& form : entries.updated_entries) { + UpdateLoginError update_login_error; PasswordStoreChangeList new_changes = - password_store_->UpdateLoginSync(*form); + password_store_->UpdateLoginSync(*form, &update_login_error); + if (is_merge) { + base::UmaHistogramEnumeration( + "PasswordManager.MergeSyncData.UpdateLoginSyncError", + update_login_error); + } else { + base::UmaHistogramEnumeration( + "PasswordManager.ApplySyncChanges.UpdateLoginSyncError", + update_login_error); + } changes.insert(changes.end(), new_changes.begin(), new_changes.end()); }
diff --git a/components/password_manager/core/browser/sync/password_syncable_service_unittest.cc b/components/password_manager/core/browser/sync/password_syncable_service_unittest.cc index 0f0db98..0b0abb5a6 100644 --- a/components/password_manager/core/browser/sync/password_syncable_service_unittest.cc +++ b/components/password_manager/core/browser/sync/password_syncable_service_unittest.cc
@@ -180,8 +180,8 @@ new PasswordSyncableService(password_store_->GetSyncInterface())); ON_CALL(*password_store_, AddLoginImpl(HasDateSynced(), _)) - .WillByDefault([&](const autofill::PasswordForm& form, - password_manager::AddLoginError* error) { + .WillByDefault([](const autofill::PasswordForm& form, + password_manager::AddLoginError* error) { if (error) { *error = AddLoginError::kNone; } @@ -189,8 +189,14 @@ }); ON_CALL(*password_store_, RemoveLoginImpl(_)) .WillByDefault(Return(PasswordStoreChangeList())); - ON_CALL(*password_store_, UpdateLoginImpl(HasDateSynced())) - .WillByDefault(Return(PasswordStoreChangeList())); + ON_CALL(*password_store_, UpdateLoginImpl(HasDateSynced(), _)) + .WillByDefault([](const autofill::PasswordForm& form, + password_manager::UpdateLoginError* error) { + if (error) { + *error = UpdateLoginError::kNone; + } + return PasswordStoreChangeList(); + }); EXPECT_CALL(*password_store(), NotifyLoginsChanged(_)).Times(AnyNumber()); } @@ -330,7 +336,7 @@ EXPECT_CALL(*password_store(), FillAutofillableLogins(_)) .WillOnce(AppendForm(form1)); EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true)); - EXPECT_CALL(*password_store(), UpdateLoginImpl(PasswordIs(form2))); + EXPECT_CALL(*password_store(), UpdateLoginImpl(PasswordIs(form2), _)); EXPECT_CALL(*processor_, ProcessSyncChanges(_, IsEmpty())); service()->MergeDataAndStartSyncing( @@ -401,7 +407,7 @@ list.push_back( CreateSyncChange(deleted_form, syncer::SyncChange::ACTION_DELETE)); EXPECT_CALL(*password_store(), AddLoginImpl(PasswordIs(new_from_sync), _)); - EXPECT_CALL(*password_store(), UpdateLoginImpl(PasswordIs(updated_form))); + EXPECT_CALL(*password_store(), UpdateLoginImpl(PasswordIs(updated_form), _)); EXPECT_CALL(*password_store(), RemoveLoginImpl(PasswordIs(deleted_form))); service()->ProcessSyncChanges(FROM_HERE, list); }
diff --git a/components/password_manager/core/browser/test_password_store.cc b/components/password_manager/core/browser/test_password_store.cc index 74906fa..cdee8f1 100644 --- a/components/password_manager/core/browser/test_password_store.cc +++ b/components/password_manager/core/browser/test_password_store.cc
@@ -71,7 +71,8 @@ } PasswordStoreChangeList TestPasswordStore::UpdateLoginImpl( - const autofill::PasswordForm& form) { + const autofill::PasswordForm& form, + UpdateLoginError* error) { PasswordStoreChangeList changes; std::vector<autofill::PasswordForm>& forms = stored_passwords_[form.signon_realm];
diff --git a/components/password_manager/core/browser/test_password_store.h b/components/password_manager/core/browser/test_password_store.h index ed33d3f..1bfe5e2 100644 --- a/components/password_manager/core/browser/test_password_store.h +++ b/components/password_manager/core/browser/test_password_store.h
@@ -48,8 +48,8 @@ // PasswordStore interface PasswordStoreChangeList AddLoginImpl(const autofill::PasswordForm& form, AddLoginError* error) override; - PasswordStoreChangeList UpdateLoginImpl( - const autofill::PasswordForm& form) override; + PasswordStoreChangeList UpdateLoginImpl(const autofill::PasswordForm& form, + UpdateLoginError* error) override; PasswordStoreChangeList RemoveLoginImpl( const autofill::PasswordForm& form) override; std::vector<std::unique_ptr<autofill::PasswordForm>> FillMatchingLogins(
diff --git a/components/policy/core/common/cloud/cloud_policy_constants.cc b/components/policy/core/common/cloud/cloud_policy_constants.cc index ed899e4..b8c9377 100644 --- a/components/policy/core/common/cloud/cloud_policy_constants.cc +++ b/components/policy/core/common/cloud/cloud_policy_constants.cc
@@ -122,4 +122,6 @@ sizeof(kPolicyVerificationKey)); } +const char kPolicyFCMInvalidationSenderID[] = "1013309121859"; + } // namespace policy
diff --git a/components/policy/core/common/cloud/cloud_policy_constants.h b/components/policy/core/common/cloud/cloud_policy_constants.h index 9c5f01d..3a30c49 100644 --- a/components/policy/core/common/cloud/cloud_policy_constants.h +++ b/components/policy/core/common/cloud/cloud_policy_constants.h
@@ -173,6 +173,10 @@ ENTERPRISE, }; +// Sender ID of FCM (Firebase Cloud Messaging) +// Policy Invalidation sender coming from the Firebase console. +extern const char kPolicyFCMInvalidationSenderID[]; + } // namespace policy #endif // COMPONENTS_POLICY_CORE_COMMON_CLOUD_CLOUD_POLICY_CONSTANTS_H_
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 8297b12..7716495 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -617,7 +617,6 @@ 'HighContrastEnabled', 'VirtualKeyboardEnabled', 'StickyKeysEnabled', - 'DockedMagnifierEnabled', 'KeyboardDefaultToFunctionKeys', 'ScreenMagnifierType', 'DeviceLoginScreenDefaultLargeCursorEnabled', @@ -9359,30 +9358,6 @@ If this policy is left unset, the sticky keys is disabled initially but can be enabled by the user anytime.''' }, { - 'name': 'DockedMagnifierEnabled', - 'type': 'main', - 'schema': { 'type': 'boolean' }, - 'supported_on': ['chrome_os:76-'], - 'features': { - 'can_be_recommended': True, - 'dynamic_refresh': True, - 'per_profile': True, - }, - 'example_value': True, - 'id': 562, - 'caption': '''Enable docked magnifier''', - 'tags': [], - 'desc': '''Enable the docked magnifier accessibility feature. - - If this policy is set to true, the docked magnifier will always be enabled. - - If this policy is set to false, the docked magnifier will always be disabled. - - If you set this policy, users cannot change or override it. - - If this policy is left unset, the docked magnifier is disabled initially but can be enabled by the user anytime.''' - }, - { 'name': 'KeyboardDefaultToFunctionKeys', 'type': 'main', 'schema': { 'type': 'boolean' }, @@ -9407,7 +9382,7 @@ 'type': 'int-enum', 'schema': { 'type': 'integer', - 'enum': [ 0, 1 ], + 'enum': [ 0, 1, 2 ], }, 'items': [ { @@ -9420,6 +9395,11 @@ 'value': 1, 'caption': '''Full-screen magnifier enabled''', }, + { + 'name': 'Docked', + 'value': 2, + 'caption': '''Docked magnifier enabled''', + }, ], 'supported_on': ['chrome_os:29-'], 'features': { @@ -9534,7 +9514,7 @@ 'type': 'int-enum', 'schema': { 'type': 'integer', - 'enum': [ 0, 1 ], + 'enum': [ 0, 1, 2 ], }, 'items': [ { @@ -9547,6 +9527,11 @@ 'value': 1, 'caption': '''Full-screen magnifier enabled''', }, + { + 'name': 'Docked', + 'value': 2, + 'caption': '''Docked magnifier enabled''', + }, ], 'supported_on': ['chrome_os:29-'], 'device_only': True, @@ -16851,7 +16836,7 @@ }, ], 'placeholders': [], - 'deleted_policy_ids': [412, 546], + 'deleted_policy_ids': [412, 546, 562], 'highest_id_currently_used': 569, 'highest_atomic_group_id_currently_used': 37 }
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn index bb7a171..306c6a7b 100644 --- a/components/sync/BUILD.gn +++ b/components/sync/BUILD.gn
@@ -312,6 +312,8 @@ "model_impl/syncable_service_based_bridge.h", "nigori/cryptographer.cc", "nigori/cryptographer.h", + "nigori/forwarding_model_type_processor.cc", + "nigori/forwarding_model_type_processor.h", "nigori/keystore_keys_handler.h", "nigori/nigori.cc", "nigori/nigori.h",
diff --git a/components/sync/driver/DEPS b/components/sync/driver/DEPS index b77b306..6e0f7ed 100644 --- a/components/sync/driver/DEPS +++ b/components/sync/driver/DEPS
@@ -14,6 +14,7 @@ "-components/signin/core/browser/signin_manager_base.h", "+components/sync/base", "+components/sync/engine", + "+components/sync/engine_impl", "+components/sync/js", "+components/sync/model", "+components/sync/model_impl",
diff --git a/components/sync/driver/glue/sync_engine_backend.cc b/components/sync/driver/glue/sync_engine_backend.cc index f6cdade..e1c4640 100644 --- a/components/sync/driver/glue/sync_engine_backend.cc +++ b/components/sync/driver/glue/sync_engine_backend.cc
@@ -17,6 +17,9 @@ #include "components/invalidation/public/object_id_invalidation_map.h" #include "components/sync/base/invalidation_adapter.h" #include "components/sync/base/sync_base_switches.h" +#include "components/sync/driver/configure_context.h" +#include "components/sync/driver/model_type_controller.h" +#include "components/sync/driver/sync_driver_switches.h" #include "components/sync/engine/cycle/commit_counters.h" #include "components/sync/engine/cycle/status_counters.h" #include "components/sync/engine/cycle/sync_cycle_snapshot.h" @@ -27,6 +30,10 @@ #include "components/sync/engine/sync_backend_registrar.h" #include "components/sync/engine/sync_manager.h" #include "components/sync/engine/sync_manager_factory.h" +#include "components/sync/engine_impl/sync_encryption_handler_impl.h" +#include "components/sync/model_impl/forwarding_model_type_controller_delegate.h" +#include "components/sync/nigori/nigori_model_type_processor.h" +#include "components/sync/nigori/nigori_sync_bridge_impl.h" #include "components/sync/syncable/directory.h" #include "components/sync/syncable/user_share.h" @@ -141,6 +148,34 @@ ModelTypeSet new_control_types = registrar_->ConfigureDataTypes(ControlTypes(), ModelTypeSet()); + ModelTypeConnector* model_type_connector = + sync_manager_->GetModelTypeConnector(); + if (nigori_controller_) { + // Having non-null |nigori_controller_| means that USS implementation of + // Nigori is enabled. + // The controller for Nigori is not exposed to the UI thread or the + // DataTypeManager, so we need to start it here manually. + ConfigureContext configure_context; + configure_context.authenticated_account_id = authenticated_account_id_; + configure_context.cache_guid = sync_manager_->cache_guid(); + // TODO(crbug.com/922900): investigate whether we want to use + // STORAGE_IN_MEMORY in Butter mode. + configure_context.storage_option = STORAGE_ON_DISK; + configure_context.configuration_start_time = base::Time::Now(); + nigori_controller_->LoadModels(configure_context, base::DoNothing()); + DCHECK_EQ(nigori_controller_->state(), DataTypeController::MODEL_LOADED); + // TODO(crbug.com/922900): Do we need to call RegisterNonBlockingType() for + // Nigori? + model_type_connector->ConnectNonBlockingType( + NIGORI, nigori_controller_->ActivateManuallyForNigori()); + } else { + // Control types don't have DataTypeControllers, but they need to have + // update handlers registered in ModelTypeRegistry. + for (ModelType control_type : ControlTypes()) { + model_type_connector->RegisterDirectoryType(control_type, GROUP_PASSIVE); + } + } + ModelSafeRoutingInfo routing_info; registrar_->GetModelSafeRoutingInfo(&routing_info); SDVLOG(1) << "Control Types " << ModelTypeSetToString(new_control_types) @@ -305,10 +340,26 @@ // Load the previously persisted set of invalidation versions into memory. last_invalidation_versions_ = params.invalidation_versions; + authenticated_account_id_ = params.authenticated_account_id; + DCHECK(!registrar_); DCHECK(params.registrar); registrar_ = std::move(params.registrar); + if (base::FeatureList::IsEnabled(switches::kSyncUSSNigori)) { + auto nigori_processor = std::make_unique<NigoriModelTypeProcessor>(); + nigori_controller_ = std::make_unique<ModelTypeController>( + NIGORI, std::make_unique<ForwardingModelTypeControllerDelegate>( + nigori_processor->GetControllerDelegate().get())); + sync_encryption_handler_ = std::make_unique<NigoriSyncBridgeImpl>( + std::move(nigori_processor), &encryptor_); + } else { + sync_encryption_handler_ = std::make_unique<SyncEncryptionHandlerImpl>( + &user_share_, &encryptor_, params.restored_key_for_bootstrapping, + params.restored_keystore_key_for_bootstrapping, + base::BindRepeating(&Nigori::GenerateScryptSalt)); + } + sync_manager_ = params.sync_manager_factory->CreateSyncManager(name_); sync_manager_->AddObserver(this); @@ -329,11 +380,9 @@ args.change_delegate = registrar_.get(); // as SyncManager::ChangeDelegate args.authenticated_account_id = params.authenticated_account_id; args.invalidator_client_id = params.invalidator_client_id; - args.restored_key_for_bootstrapping = params.restored_key_for_bootstrapping; - args.restored_keystore_key_for_bootstrapping = - params.restored_keystore_key_for_bootstrapping; args.engine_components_factory = std::move(params.engine_components_factory); - args.encryptor = &encryptor_; + args.user_share = &user_share_; + args.encryption_handler = sync_encryption_handler_.get(); args.unrecoverable_error_handler = params.unrecoverable_error_handler; args.report_unrecoverable_error_function = params.report_unrecoverable_error_function; @@ -459,8 +508,11 @@ registrar_ = nullptr; - if (reason == DISABLE_SYNC) + if (reason == DISABLE_SYNC) { + // TODO(crbug.com/922900): We may want to remove Nigori data from the + // storage if USS Nigori implementation is enabled. syncable::Directory::DeleteDirectoryFiles(sync_data_folder_); + } host_.Reset(); weak_ptr_factory_.InvalidateWeakPtrs();
diff --git a/components/sync/driver/glue/sync_engine_backend.h b/components/sync/driver/glue/sync_engine_backend.h index e4ff0763b..e8183596 100644 --- a/components/sync/driver/glue/sync_engine_backend.h +++ b/components/sync/driver/glue/sync_engine_backend.h
@@ -27,10 +27,12 @@ #include "components/sync/engine/model_type_configurer.h" #include "components/sync/engine/shutdown_reason.h" #include "components/sync/engine/sync_encryption_handler.h" +#include "components/sync/syncable/user_share.h" #include "url/gurl.h" namespace syncer { +class ModelTypeController; class SyncEngineImpl; class SyncEngineBackend : public base::RefCountedThreadSafe<SyncEngineBackend>, @@ -208,9 +210,25 @@ // Our encryptor, which uses Chrome's encryption functions. SystemEncryptor encryptor_; + // We hold |user_share_| here as a dependency for |sync_encryption_handler_|. + // Should outlive |sync_encryption_handler_| and |sync_manager_|. + UserShare user_share_; + + // Points to either SyncEncryptionHandlerImpl or NigoriSyncBridgeImpl + // depending on whether USS implementation of Nigori is enabled or not. + // Should outlive |sync_manager_|. + std::unique_ptr<SyncEncryptionHandler> sync_encryption_handler_; + // The top-level syncapi entry point. Lives on the sync thread. std::unique_ptr<SyncManager> sync_manager_; + // Required for |nigori_controller_| LoadModels(). + std::string authenticated_account_id_; + + // Initialized in OnInitializationComplete() iff USS implementation of Nigori + // is enabled. + std::unique_ptr<ModelTypeController> nigori_controller_; + // Temporary holder of sync manager's initialization results. Set by // OnInitializeComplete, and consumed when we pass it via OnEngineInitialized // in the final state of HandleInitializationSuccessOnFrontendLoop.
diff --git a/components/sync/driver/model_type_controller.cc b/components/sync/driver/model_type_controller.cc index 4dab5b0..456bef1 100644 --- a/components/sync/driver/model_type_controller.cc +++ b/components/sync/driver/model_type_controller.cc
@@ -60,6 +60,17 @@ ModelTypeController::~ModelTypeController() {} +std::unique_ptr<DataTypeActivationResponse> +ModelTypeController::ActivateManuallyForNigori() { + // To avoid abuse of this temporary API, we restrict it to NIGORI. + DCHECK_EQ(NIGORI, type()); + DCHECK_EQ(MODEL_LOADED, state_); + DCHECK(activation_response_); + state_ = RUNNING; + activated_ = true; // Not relevant, but for consistency. + return std::move(activation_response_); +} + bool ModelTypeController::ShouldLoadModelBeforeConfigure() const { // USS datatypes require loading models because model controls storage where // data type context and progress marker are persisted.
diff --git a/components/sync/driver/model_type_controller.h b/components/sync/driver/model_type_controller.h index 9ba6e68..6dd17a1a 100644 --- a/components/sync/driver/model_type_controller.h +++ b/components/sync/driver/model_type_controller.h
@@ -38,6 +38,12 @@ std::unique_ptr<ModelTypeControllerDelegate> delegate_in_memory); ~ModelTypeController() override; + // Steals the activation response, only used for Nigori. + // TODO(crbug.com/967677): Once all datatypes are in USS, we should redesign + // or remove RegisterWithBackend, and expose the activation response via + // LoadModels(), which is more natural in USS. + std::unique_ptr<DataTypeActivationResponse> ActivateManuallyForNigori(); + // DataTypeController implementation. bool ShouldLoadModelBeforeConfigure() const override; void BeforeLoadModels(ModelTypeConfigurer* configurer) override;
diff --git a/components/sync/driver/non_ui_syncable_service_based_model_type_controller.cc b/components/sync/driver/non_ui_syncable_service_based_model_type_controller.cc index c480da6..b4f487a14 100644 --- a/components/sync/driver/non_ui_syncable_service_based_model_type_controller.cc +++ b/components/sync/driver/non_ui_syncable_service_based_model_type_controller.cc
@@ -17,7 +17,9 @@ namespace { // Helper object that allows constructing and destructing the -// SyncableServiceBasedBridge on the model thread. +// SyncableServiceBasedBridge on the model thread. Gets constructed on the UI +// thread, but all other operations including destruction happen on the model +// thread. class BridgeBuilder { public: BridgeBuilder( @@ -27,20 +29,21 @@ syncable_service_provider, const base::RepeatingClosure& dump_stack, scoped_refptr<base::SequencedTaskRunner> task_runner) - : task_runner_(task_runner), - bridge_(nullptr, base::OnTaskRunnerDeleter(task_runner)), - weak_ptr_factory_(this) { + : task_runner_(task_runner) { DCHECK(store_factory); DCHECK(syncable_service_provider); + // Unretained is safe because destruction also happens on |task_runner_| and + // can't overtake this task. task_runner_->PostTask( FROM_HERE, - base::BindOnce(&BridgeBuilder::BuildBridgeDelegate, - weak_ptr_factory_.GetWeakPtr(), type, - std::move(store_factory), + base::BindOnce(&BridgeBuilder::InitOnModelThread, + base::Unretained(this), type, std::move(store_factory), std::move(syncable_service_provider), dump_stack)); } + ~BridgeBuilder() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); } + base::WeakPtr<ModelTypeControllerDelegate> GetBridgeDelegate() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(bridge_); @@ -48,7 +51,7 @@ } private: - void BuildBridgeDelegate( + void InitOnModelThread( ModelType type, OnceModelTypeStoreFactory store_factory, NonUiSyncableServiceBasedModelTypeController::SyncableServiceProvider @@ -61,22 +64,37 @@ std::move(syncable_service_provider).Run(); // |syncable_service| can be null in tests. if (syncable_service) { - // std::make_unique() avoided here due to custom deleter. - bridge_.reset(new SyncableServiceBasedBridge( + bridge_ = std::make_unique<SyncableServiceBasedBridge>( type, std::move(store_factory), std::make_unique<ClientTagBasedModelTypeProcessor>(type, dump_stack), - syncable_service.get())); + syncable_service.get()); } } scoped_refptr<base::SequencedTaskRunner> task_runner_; - std::unique_ptr<ModelTypeSyncBridge, base::OnTaskRunnerDeleter> bridge_; - - base::WeakPtrFactory<BridgeBuilder> weak_ptr_factory_; + std::unique_ptr<ModelTypeSyncBridge> bridge_; DISALLOW_COPY_AND_ASSIGN(BridgeBuilder); }; +ProxyModelTypeControllerDelegate::DelegateProvider BuildDelegateProvider( + ModelType type, + OnceModelTypeStoreFactory store_factory, + NonUiSyncableServiceBasedModelTypeController::SyncableServiceProvider + syncable_service_provider, + const base::RepeatingClosure& dump_stack, + scoped_refptr<base::SequencedTaskRunner> task_runner) { + // Can't use std::make_unique or base::WrapUnique because of custom deleter. + auto bridge_builder = + std::unique_ptr<BridgeBuilder, base::OnTaskRunnerDeleter>( + new BridgeBuilder(type, std::move(store_factory), + std::move(syncable_service_provider), dump_stack, + task_runner), + base::OnTaskRunnerDeleter(task_runner)); + return base::BindRepeating(&BridgeBuilder::GetBridgeDelegate, + std::move(bridge_builder)); +} + } // namespace NonUiSyncableServiceBasedModelTypeController:: @@ -90,13 +108,11 @@ type, std::make_unique<ProxyModelTypeControllerDelegate>( task_runner, - base::BindRepeating(&BridgeBuilder::GetBridgeDelegate, - std::make_unique<BridgeBuilder>( - type, - std::move(store_factory), - std::move(syncable_service_provider), - dump_stack, - task_runner)))) {} + BuildDelegateProvider(type, + std::move(store_factory), + std::move(syncable_service_provider), + dump_stack, + task_runner))) {} NonUiSyncableServiceBasedModelTypeController:: ~NonUiSyncableServiceBasedModelTypeController() {}
diff --git a/components/sync/driver/sync_driver_switches.cc b/components/sync/driver/sync_driver_switches.cc index 6676277c..0ef33501 100644 --- a/components/sync/driver/sync_driver_switches.cc +++ b/components/sync/driver/sync_driver_switches.cc
@@ -75,6 +75,10 @@ const base::Feature kSyncUSSAutofillWalletMetadata{ "SyncUSSAutofillWalletMetadata", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enable USS implementation of Nigori datatype. +const base::Feature kSyncUSSNigori{"SyncUSSNigori", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Controls whether to enable syncing of Wi-Fi configurations. const base::Feature kSyncWifiConfigurations{"SyncWifiConfigurations", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/sync/driver/sync_driver_switches.h b/components/sync/driver/sync_driver_switches.h index 4ad8437..eff9abd9 100644 --- a/components/sync/driver/sync_driver_switches.h +++ b/components/sync/driver/sync_driver_switches.h
@@ -34,6 +34,7 @@ extern const base::Feature kSyncUSSBookmarks; extern const base::Feature kSyncUSSPasswords; extern const base::Feature kSyncUSSAutofillWalletMetadata; +extern const base::Feature kSyncUSSNigori; extern const base::Feature kSyncWifiConfigurations; } // namespace switches
diff --git a/components/sync/engine/fake_sync_manager.cc b/components/sync/engine/fake_sync_manager.cc index 0577ca8..522e0d1 100644 --- a/components/sync/engine/fake_sync_manager.cc +++ b/components/sync/engine/fake_sync_manager.cc
@@ -198,6 +198,10 @@ return test_user_share_.user_share(); } +ModelTypeConnector* FakeSyncManager::GetModelTypeConnector() { + return &fake_model_type_connector_; +} + std::unique_ptr<ModelTypeConnector> FakeSyncManager::GetModelTypeConnectorProxy() { return std::make_unique<FakeModelTypeConnector>();
diff --git a/components/sync/engine/fake_sync_manager.h b/components/sync/engine/fake_sync_manager.h index 82125b3..ac2d9fc 100644 --- a/components/sync/engine/fake_sync_manager.h +++ b/components/sync/engine/fake_sync_manager.h
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" +#include "components/sync/engine/fake_model_type_connector.h" #include "components/sync/engine/sync_manager.h" #include "components/sync/syncable/test_user_share.h" #include "components/sync/test/fake_sync_encryption_handler.h" @@ -99,6 +100,7 @@ void SaveChanges() override; void ShutdownOnSyncThread() override; UserShare* GetUserShare() override; + ModelTypeConnector* GetModelTypeConnector() override; std::unique_ptr<ModelTypeConnector> GetModelTypeConnectorProxy() override; std::string cache_guid() override; std::string birthday() override; @@ -147,6 +149,8 @@ FakeSyncEncryptionHandler fake_encryption_handler_; + FakeModelTypeConnector fake_model_type_connector_; + TestUserShare test_user_share_; // Number of invalidations received since startup.
diff --git a/components/sync/engine/model_type_processor.h b/components/sync/engine/model_type_processor.h index 671888ee..806543d 100644 --- a/components/sync/engine/model_type_processor.h +++ b/components/sync/engine/model_type_processor.h
@@ -7,6 +7,7 @@ #include <memory> +#include "base/callback_forward.h" #include "components/sync/engine/non_blocking_sync_common.h" #include "components/sync/protocol/model_type_state.pb.h"
diff --git a/components/sync/engine/sync_encryption_handler.h b/components/sync/engine/sync_encryption_handler.h index 6681818..17635ad9 100644 --- a/components/sync/engine/sync_encryption_handler.h +++ b/components/sync/engine/sync_encryption_handler.h
@@ -16,8 +16,15 @@ namespace syncer { class Cryptographer; +class KeystoreKeysHandler; enum class PassphraseType; +namespace syncable { + +class NigoriHandler; + +} // namespace syncable + // Reasons due to which Cryptographer might require a passphrase. enum PassphraseRequiredReason { REASON_PASSPHRASE_NOT_REQUIRED = 0, // Initial value. @@ -173,6 +180,24 @@ // base::Time() in case migration isn't completed. virtual base::Time GetKeystoreMigrationTime() const = 0; + // Unsafe getter. Use only if sync is not up and running and there is no risk + // of other threads calling this. Returns the original cryptographer. This + // Cryptographer will always reflect the actual state of + // SyncEncryptionHandler (no needs to call this method again in case + // cryptographer state was changed). + // TODO(crbug.com/970213): remove this method or replace with normal getter + // for const Cryptographer. + virtual Cryptographer* GetCryptographerUnsafe() = 0; + + // Returns KeystoreKeysHandler, allowing to pass new keystore keys and to + // check whether keystore keys need to be requested from the server. + virtual KeystoreKeysHandler* GetKeystoreKeysHandler() = 0; + + // Returns NigoriHandler, allowing directory-specific interaction with + // Nigori. Returns nullptr iff USS implementation of Nigori is enabled. + // TODO(crbug.com/970213): remove this method. + virtual syncable::NigoriHandler* GetNigoriHandler() = 0; + // The set of types that are always encrypted. static ModelTypeSet SensitiveTypes(); };
diff --git a/components/sync/engine/sync_engine_switches.cc b/components/sync/engine/sync_engine_switches.cc index e05efd0..d5a3c05 100644 --- a/components/sync/engine/sync_engine_switches.cc +++ b/components/sync/engine/sync_engine_switches.cc
@@ -25,8 +25,4 @@ const base::Feature kSyncUseScryptForNewCustomPassphrases{ "SyncUseScryptForNewCustomPassphrases", base::FEATURE_ENABLED_BY_DEFAULT}; -// Enable USS implementation of Nigori datatype. -const base::Feature kSyncUSSNigori{"SyncUSSNigori", - base::FEATURE_DISABLED_BY_DEFAULT}; - } // namespace switches
diff --git a/components/sync/engine/sync_engine_switches.h b/components/sync/engine/sync_engine_switches.h index 5c5eedb..6861251 100644 --- a/components/sync/engine/sync_engine_switches.h +++ b/components/sync/engine/sync_engine_switches.h
@@ -14,8 +14,6 @@ extern const base::Feature kSyncResetPollIntervalOnStart; extern const base::Feature kSyncUseScryptForNewCustomPassphrases; -extern const base::Feature kSyncUSSNigori; - } // namespace switches #endif // COMPONENTS_SYNC_ENGINE_SYNC_ENGINE_SWITCHES_H_
diff --git a/components/sync/engine/sync_manager.cc b/components/sync/engine/sync_manager.cc index 6737a4b0..12cc280 100644 --- a/components/sync/engine/sync_manager.cc +++ b/components/sync/engine/sync_manager.cc
@@ -16,7 +16,8 @@ : enable_local_sync_backend(false), extensions_activity(nullptr), change_delegate(nullptr), - encryptor(nullptr), + user_share(nullptr), + encryption_handler(nullptr), cancelation_signal(nullptr) {} SyncManager::InitArgs::~InitArgs() {}
diff --git a/components/sync/engine/sync_manager.h b/components/sync/engine/sync_manager.h index 9dbc2298..d584a07b 100644 --- a/components/sync/engine/sync_manager.h +++ b/components/sync/engine/sync_manager.h
@@ -45,7 +45,6 @@ class BaseTransaction; class CancelationSignal; class DataTypeDebugInfoListener; -class Encryptor; class EngineComponentsFactory; class ExtensionsActivity; class JsBackend; @@ -226,14 +225,13 @@ // Unqiuely identifies this client to the invalidation notification server. std::string invalidator_client_id; - // Used to boostrap the cryptographer. - std::string restored_key_for_bootstrapping; - std::string restored_keystore_key_for_bootstrapping; - std::unique_ptr<EngineComponentsFactory> engine_components_factory; // Must outlive SyncManager. - Encryptor* encryptor; + UserShare* user_share; + + // Must outlive SyncManager. + SyncEncryptionHandler* encryption_handler; WeakHandle<UnrecoverableErrorHandler> unrecoverable_error_handler; base::Closure report_unrecoverable_error_function; @@ -341,6 +339,11 @@ // May be called from any thread. virtual UserShare* GetUserShare() = 0; + // Returns non-owning pointer to ModelTypeConnector. In contrast with + // ModelTypeConnectorProxy all calls are executed synchronously, thus the + // pointer should be used on sync thread. + virtual ModelTypeConnector* GetModelTypeConnector() = 0; + // Returns an instance of the main interface for registering sync types with // sync engine. virtual std::unique_ptr<ModelTypeConnector> GetModelTypeConnectorProxy() = 0;
diff --git a/components/sync/engine_impl/sync_encryption_handler_impl.cc b/components/sync/engine_impl/sync_encryption_handler_impl.cc index 048506b6..e3dd31d 100644 --- a/components/sync/engine_impl/sync_encryption_handler_impl.cc +++ b/components/sync/engine_impl/sync_encryption_handler_impl.cc
@@ -743,6 +743,21 @@ return keystore_migration_time_; } +Cryptographer* SyncEncryptionHandlerImpl::GetCryptographerUnsafe() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return &vault_unsafe_.cryptographer; +} + +KeystoreKeysHandler* SyncEncryptionHandlerImpl::GetKeystoreKeysHandler() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return this; +} + +syncable::NigoriHandler* SyncEncryptionHandlerImpl::GetNigoriHandler() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return this; +} + // Note: this is called from within a syncable transaction, so we need to post // tasks if we want to do any work that creates a new sync_api transaction. void SyncEncryptionHandlerImpl::ApplyNigoriUpdate( @@ -867,11 +882,6 @@ return UnlockVault(trans).passphrase_type; } -Cryptographer* SyncEncryptionHandlerImpl::GetCryptographerUnsafe() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return &vault_unsafe_.cryptographer; -} - ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypesUnsafe() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return vault_unsafe_.encrypted_types;
diff --git a/components/sync/engine_impl/sync_encryption_handler_impl.h b/components/sync/engine_impl/sync_encryption_handler_impl.h index 35e6a31..fdd4e83 100644 --- a/components/sync/engine_impl/sync_encryption_handler_impl.h +++ b/components/sync/engine_impl/sync_encryption_handler_impl.h
@@ -69,6 +69,9 @@ void EnableEncryptEverything() override; bool IsEncryptEverythingEnabled() const override; base::Time GetKeystoreMigrationTime() const override; + Cryptographer* GetCryptographerUnsafe() override; + KeystoreKeysHandler* GetKeystoreKeysHandler() override; + syncable::NigoriHandler* GetNigoriHandler() override; // NigoriHandler implementation. // Note: all methods are invoked while the caller holds a transaction. @@ -89,7 +92,7 @@ // Unsafe getters. Use only if sync is not up and running and there is no risk // of other threads calling this. - Cryptographer* GetCryptographerUnsafe(); + ModelTypeSet GetEncryptedTypesUnsafe(); bool MigratedToKeystore();
diff --git a/components/sync/engine_impl/sync_manager_impl.cc b/components/sync/engine_impl/sync_manager_impl.cc index 4d43b0d..5de0403 100644 --- a/components/sync/engine_impl/sync_manager_impl.cc +++ b/components/sync/engine_impl/sync_manager_impl.cc
@@ -26,7 +26,6 @@ #include "components/sync/engine/engine_util.h" #include "components/sync/engine/net/http_post_provider_factory.h" #include "components/sync/engine/polling_constants.h" -#include "components/sync/engine/sync_engine_switches.h" #include "components/sync/engine_impl/cycle/directory_type_debug_info_emitter.h" #include "components/sync/engine_impl/loopback_server/loopback_connection_manager.h" #include "components/sync/engine_impl/model_type_connector_proxy.h" @@ -35,9 +34,8 @@ #include "components/sync/engine_impl/sync_scheduler.h" #include "components/sync/engine_impl/syncer_types.h" #include "components/sync/engine_impl/uss_migrator.h" +#include "components/sync/nigori/cryptographer.h" #include "components/sync/nigori/nigori.h" -#include "components/sync/nigori/nigori_model_type_processor.h" -#include "components/sync/nigori/nigori_sync_bridge_impl.h" #include "components/sync/protocol/sync.pb.h" #include "components/sync/syncable/base_node.h" #include "components/sync/syncable/directory.h" @@ -147,9 +145,11 @@ network::NetworkConnectionTracker* network_connection_tracker) : name_(name), network_connection_tracker_(network_connection_tracker), + share_(nullptr), change_delegate_(nullptr), initialized_(false), observing_network_connectivity_changes_(false), + sync_encryption_handler_(nullptr), weak_ptr_factory_(this) { // Pre-fill |notification_info_map_|. for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; ++i) { @@ -296,29 +296,11 @@ report_unrecoverable_error_function_ = args->report_unrecoverable_error_function; - allstatus_.SetHasKeystoreKey( - !args->restored_keystore_key_for_bootstrapping.empty()); + DCHECK(args->user_share); + share_ = args->user_share; - Cryptographer* cryptographer_for_directory = nullptr; - syncable::NigoriHandler* nigori_handler = nullptr; - KeystoreKeysHandler* keystore_keys_handler = nullptr; - if (base::FeatureList::IsEnabled(switches::kSyncUSSNigori)) { - auto nigori_sync_bridge_impl = std::make_unique<NigoriSyncBridgeImpl>( - std::make_unique<NigoriModelTypeProcessor>(), args->encryptor); - keystore_keys_handler = nigori_sync_bridge_impl.get(); - sync_encryption_handler_ = std::move(nigori_sync_bridge_impl); - } else { - auto sync_encryption_handler_impl = - std::make_unique<SyncEncryptionHandlerImpl>( - &share_, args->encryptor, args->restored_key_for_bootstrapping, - args->restored_keystore_key_for_bootstrapping, - base::BindRepeating(&Nigori::GenerateScryptSalt)); - cryptographer_for_directory = - sync_encryption_handler_impl->GetCryptographerUnsafe(); - nigori_handler = sync_encryption_handler_impl.get(); - keystore_keys_handler = sync_encryption_handler_impl.get(); - sync_encryption_handler_ = std::move(sync_encryption_handler_impl); - } + DCHECK(args->encryption_handler); + sync_encryption_handler_ = args->encryption_handler; // Register for encryption related changes now. We have to do this before // the initial download of control types or initializing the encryption @@ -356,12 +338,13 @@ DCHECK(backing_store); - // Note: |nigori_handler| and |cryptographer_for_directory| are nullptrs iff - // kSyncUSSNigori is enabled. - share_.directory = std::make_unique<syncable::Directory>( + // Note: NigoriHandler and Cryptographer passed to Directory are nullptrs iff + // USS implementation of Nigori is enabled. + share_->directory = std::make_unique<syncable::Directory>( std::move(backing_store), args->unrecoverable_error_handler, - report_unrecoverable_error_function_, nigori_handler, - cryptographer_for_directory); + report_unrecoverable_error_function_, + sync_encryption_handler_->GetNigoriHandler(), + sync_encryption_handler_->GetCryptographerUnsafe()); DVLOG(1) << "AccountId: " << args->authenticated_account_id; if (!OpenDirectory(args)) { @@ -370,6 +353,9 @@ return; } + allstatus_.SetHasKeystoreKey( + !sync_encryption_handler_->GetKeystoreKeysHandler()->NeedKeystoreKey()); + if (args->enable_local_sync_backend) { VLOG(1) << "Running against local sync backend."; allstatus_.SetLocalBackendFolder( @@ -394,8 +380,9 @@ allstatus_.SetInvalidatorClientId(args->invalidator_client_id); model_type_registry_ = std::make_unique<ModelTypeRegistry>( - args->workers, &share_, this, base::Bind(&MigrateDirectoryData), - args->cancelation_signal, keystore_keys_handler); + args->workers, share_, this, base::Bind(&MigrateDirectoryData), + args->cancelation_signal, + sync_encryption_handler_->GetKeystoreKeysHandler()); sync_encryption_handler_->AddObserver(model_type_registry_.get()); // Build a SyncCycleContext and store the worker in it. @@ -422,12 +409,6 @@ scheduler_->OnCredentialsUpdated(); } - // Control types don't have DataTypeControllers, but they need to have - // update handlers registered in ModelTypeRegistry. - for (ModelType control_type : ControlTypes()) { - model_type_registry_->RegisterDirectoryType(control_type, GROUP_PASSIVE); - } - NotifyInitializationSuccess(); } @@ -505,7 +486,8 @@ } syncable::Directory* SyncManagerImpl::directory() { - return share_.directory.get(); + DCHECK(share_); + return share_->directory.get(); } const SyncScheduler* SyncManagerImpl::scheduler() const { @@ -671,7 +653,10 @@ directory()->SaveChanges(); } - share_.directory.reset(); + // TODO(crbug.com/922900): can this be replaced with DCHECK(share_)? + if (share_) { + share_->directory.reset(); + } change_delegate_ = nullptr; @@ -1009,7 +994,13 @@ UserShare* SyncManagerImpl::GetUserShare() { DCHECK(initialized_); - return &share_; + DCHECK(share_); + return share_; +} + +ModelTypeConnector* SyncManagerImpl::GetModelTypeConnector() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return model_type_registry_.get(); } std::unique_ptr<ModelTypeConnector> @@ -1042,7 +1033,8 @@ } SyncEncryptionHandler* SyncManagerImpl::GetEncryptionHandler() { - return sync_encryption_handler_.get(); + DCHECK(sync_encryption_handler_); + return sync_encryption_handler_; } std::vector<std::unique_ptr<ProtocolEvent>>
diff --git a/components/sync/engine_impl/sync_manager_impl.h b/components/sync/engine_impl/sync_manager_impl.h index e9b9785..a3c45a2b 100644 --- a/components/sync/engine_impl/sync_manager_impl.h +++ b/components/sync/engine_impl/sync_manager_impl.h
@@ -28,14 +28,13 @@ #include "components/sync/engine_impl/nudge_handler.h" #include "components/sync/engine_impl/sync_engine_event_listener.h" #include "components/sync/js/js_backend.h" -#include "components/sync/nigori/cryptographer.h" #include "components/sync/syncable/change_reorder_buffer.h" #include "components/sync/syncable/directory_change_delegate.h" -#include "components/sync/syncable/user_share.h" #include "services/network/public/cpp/network_connection_tracker.h" namespace syncer { +class Cryptographer; class ModelTypeRegistry; class SyncCycleContext; class TypeDebugInfoObserver; @@ -92,6 +91,7 @@ void SaveChanges() override; void ShutdownOnSyncThread() override; UserShare* GetUserShare() override; + ModelTypeConnector* GetModelTypeConnector() override; std::unique_ptr<ModelTypeConnector> GetModelTypeConnectorProxy() override; std::string cache_guid() override; std::string birthday() override; @@ -255,7 +255,7 @@ // We give a handle to share_ to clients of the API for use when constructing // any transaction type. - UserShare share_; + UserShare* share_; // This can be called from any thread, but only between calls to // OpenDirectory() and ShutdownOnSyncThread(). @@ -315,9 +315,7 @@ base::Closure report_unrecoverable_error_function_; - // Points to either SyncEncryptionHandlerImpl or NigoriSyncBridgeImpl - // depending on whether USS implementation of Nigori is enabled or not. - std::unique_ptr<SyncEncryptionHandler> sync_encryption_handler_; + SyncEncryptionHandler* sync_encryption_handler_; std::unique_ptr<SyncEncryptionHandler::Observer> encryption_observer_proxy_;
diff --git a/components/sync/engine_impl/sync_manager_impl_unittest.cc b/components/sync/engine_impl/sync_manager_impl_unittest.cc index 6ee6925..2fda433 100644 --- a/components/sync/engine_impl/sync_manager_impl_unittest.cc +++ b/components/sync/engine_impl/sync_manager_impl_unittest.cc
@@ -35,6 +35,7 @@ #include "components/sync/engine/polling_constants.h" #include "components/sync/engine/test_engine_components_factory.h" #include "components/sync/engine_impl/cycle/sync_cycle.h" +#include "components/sync/engine_impl/sync_encryption_handler_impl.h" #include "components/sync/engine_impl/sync_scheduler.h" #include "components/sync/engine_impl/test_entry_factory.h" #include "components/sync/js/js_event_handler.h" @@ -952,6 +953,11 @@ std::make_unique<StrictMock<SyncEncryptionHandlerObserverMock>>(); encryption_observer_ = encryption_observer.get(); + encryption_handler_ = std::make_unique<SyncEncryptionHandlerImpl>( + &user_share_, &encryptor_, /*restored_key_for_bootstrapping=*/"", + /*restored_keystore_key_for_bootstrapping=*/"", + base::BindRepeating(&Nigori::GenerateScryptSalt)); + SyncManager::InitArgs args; args.database_location = temp_dir_.GetPath(); args.service_url = GURL("https://example.com/"); @@ -967,7 +973,8 @@ args.enable_local_sync_backend = enable_local_sync_backend; args.local_sync_backend_folder = temp_dir_.GetPath(); args.engine_components_factory.reset(GetFactory()); - args.encryptor = &encryptor_; + args.user_share = &user_share_; + args.encryption_handler = encryption_handler_.get(); args.unrecoverable_error_handler = MakeWeakHandle(mock_unrecoverable_error_handler_.GetWeakPtr()); args.cancelation_signal = &cancelation_signal_; @@ -1163,6 +1170,8 @@ protected: FakeEncryptor encryptor_; + UserShare user_share_; + std::unique_ptr<SyncEncryptionHandler> encryption_handler_; SyncManagerImpl sync_manager_; CancelationSignal cancelation_signal_; WeakHandle<JsBackend> js_backend_;
diff --git a/components/sync/nigori/forwarding_model_type_processor.cc b/components/sync/nigori/forwarding_model_type_processor.cc new file mode 100644 index 0000000..eca08cff --- /dev/null +++ b/components/sync/nigori/forwarding_model_type_processor.cc
@@ -0,0 +1,48 @@ +// Copyright 2019 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 "components/sync/nigori/forwarding_model_type_processor.h" + +#include <utility> +#include "base/callback.h" +#include "components/sync/engine/commit_queue.h" + +namespace syncer { + +ForwardingModelTypeProcessor::ForwardingModelTypeProcessor( + ModelTypeProcessor* processor) + : processor_(processor) { + DCHECK(processor_); +} + +ForwardingModelTypeProcessor::~ForwardingModelTypeProcessor() = default; + +void ForwardingModelTypeProcessor::ConnectSync( + std::unique_ptr<CommitQueue> worker) { + processor_->ConnectSync(std::move(worker)); +} + +void ForwardingModelTypeProcessor::DisconnectSync() { + processor_->DisconnectSync(); +} + +void ForwardingModelTypeProcessor::GetLocalChanges( + size_t max_entries, + GetLocalChangesCallback callback) { + processor_->GetLocalChanges(max_entries, std::move(callback)); +} + +void ForwardingModelTypeProcessor::OnCommitCompleted( + const sync_pb::ModelTypeState& type_state, + const CommitResponseDataList& response_list) { + processor_->OnCommitCompleted(type_state, response_list); +} + +void ForwardingModelTypeProcessor::OnUpdateReceived( + const sync_pb::ModelTypeState& type_state, + UpdateResponseDataList updates) { + processor_->OnUpdateReceived(type_state, std::move(updates)); +} + +} // namespace syncer
diff --git a/components/sync/nigori/forwarding_model_type_processor.h b/components/sync/nigori/forwarding_model_type_processor.h new file mode 100644 index 0000000..98bc5493 --- /dev/null +++ b/components/sync/nigori/forwarding_model_type_processor.h
@@ -0,0 +1,42 @@ +// Copyright 2019 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 COMPONENTS_SYNC_NIGORI_FORWARDING_MODEL_TYPE_PROCESSOR_H_ +#define COMPONENTS_SYNC_NIGORI_FORWARDING_MODEL_TYPE_PROCESSOR_H_ + +#include <memory> + +#include "base/macros.h" +#include "components/sync/engine/model_type_processor.h" + +namespace syncer { + +// Trivial implementation of ModelTypeProcessor, that simply forwards +// call to another processor. This is useful when an API requires transferring +// ownership, but the calling site also wants to keep ownership of the actual +// implementation, and can guarantee the lifetime constraints. +class ForwardingModelTypeProcessor : public ModelTypeProcessor { + public: + // |processor| must not be null and must outlive this object. + explicit ForwardingModelTypeProcessor(ModelTypeProcessor* processor); + ~ForwardingModelTypeProcessor() override; + + void ConnectSync(std::unique_ptr<CommitQueue> worker) override; + void DisconnectSync() override; + void GetLocalChanges(size_t max_entries, + GetLocalChangesCallback callback) override; + void OnCommitCompleted(const sync_pb::ModelTypeState& type_state, + const CommitResponseDataList& response_list) override; + void OnUpdateReceived(const sync_pb::ModelTypeState& type_state, + UpdateResponseDataList updates) override; + + private: + ModelTypeProcessor* const processor_; + + DISALLOW_COPY_AND_ASSIGN(ForwardingModelTypeProcessor); +}; + +} // namespace syncer + +#endif // COMPONENTS_SYNC_NIGORI_FORWARDING_MODEL_TYPE_PROCESSOR_H_
diff --git a/components/sync/nigori/nigori_model_type_processor.cc b/components/sync/nigori/nigori_model_type_processor.cc index 56bc044..604ede7 100644 --- a/components/sync/nigori/nigori_model_type_processor.cc +++ b/components/sync/nigori/nigori_model_type_processor.cc
@@ -8,8 +8,8 @@ #include "components/sync/base/data_type_histogram.h" #include "components/sync/base/time.h" #include "components/sync/engine/commit_queue.h" -#include "components/sync/engine/model_type_processor_proxy.h" #include "components/sync/model_impl/processor_entity.h" +#include "components/sync/nigori/forwarding_model_type_processor.h" #include "components/sync/nigori/nigori_sync_bridge.h" #include "components/sync/protocol/proto_memory_estimations.h" #include "components/sync/protocol/proto_value_conversions.h" @@ -26,9 +26,7 @@ } // namespace NigoriModelTypeProcessor::NigoriModelTypeProcessor() - : bridge_(nullptr), - weak_ptr_factory_for_controller_(this), - weak_ptr_factory_for_worker_(this) {} + : bridge_(nullptr), weak_ptr_factory_for_controller_(this) {} NigoriModelTypeProcessor::~NigoriModelTypeProcessor() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -48,7 +46,6 @@ DCHECK(IsConnected()); DVLOG(1) << "Disconnecting sync for Encryption Keys"; - weak_ptr_factory_for_worker_.InvalidateWeakPtrs(); worker_.reset(); if (entity_) { entity_->ClearTransientSyncState(); @@ -226,9 +223,6 @@ break; } } - - // Do not let any delayed callbacks to be called. - weak_ptr_factory_for_worker_.InvalidateWeakPtrs(); } void NigoriModelTypeProcessor::GetAllNodesForDebugging( @@ -421,9 +415,7 @@ auto activation_response = std::make_unique<DataTypeActivationResponse>(); activation_response->model_type_state = model_type_state_; activation_response->type_processor = - std::make_unique<ModelTypeProcessorProxy>( - weak_ptr_factory_for_worker_.GetWeakPtr(), - base::SequencedTaskRunnerHandle::Get()); + std::make_unique<ForwardingModelTypeProcessor>(this); std::move(start_callback_).Run(std::move(activation_response)); }
diff --git a/components/sync/nigori/nigori_model_type_processor.h b/components/sync/nigori/nigori_model_type_processor.h index db9f593..48af934 100644 --- a/components/sync/nigori/nigori_model_type_processor.h +++ b/components/sync/nigori/nigori_model_type_processor.h
@@ -104,9 +104,6 @@ base::WeakPtrFactory<ModelTypeControllerDelegate> weak_ptr_factory_for_controller_; - // WeakPtrFactory for this processor which will be sent to sync thread. - base::WeakPtrFactory<NigoriModelTypeProcessor> weak_ptr_factory_for_worker_; - DISALLOW_COPY_AND_ASSIGN(NigoriModelTypeProcessor); };
diff --git a/components/sync/nigori/nigori_model_type_processor_unittest.cc b/components/sync/nigori/nigori_model_type_processor_unittest.cc index 38de778..abfdbe3 100644 --- a/components/sync/nigori/nigori_model_type_processor_unittest.cc +++ b/components/sync/nigori/nigori_model_type_processor_unittest.cc
@@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/test/mock_callback.h" -#include "base/test/scoped_task_environment.h" #include "components/sync/base/time.h" #include "components/sync/engine/commit_queue.h" #include "components/sync/nigori/nigori_sync_bridge.h" @@ -146,10 +145,6 @@ NigoriModelTypeProcessor* processor() { return &processor_; } private: - // This sets SequencedTaskRunnerHandle on the current thread, which the type - // processor will pick up as the sync task runner. - base::test::ScopedTaskEnvironment task_environment_; - testing::NiceMock<MockNigoriSyncBridge> mock_nigori_sync_bridge_; std::unique_ptr<testing::NiceMock<MockCommitQueue>> mock_commit_queue_; MockCommitQueue* mock_commit_queue_ptr_; @@ -407,9 +402,6 @@ ASSERT_FALSE(processor()->IsConnectedForTest()); captured_response->type_processor->ConnectSync( std::make_unique<testing::NiceMock<MockCommitQueue>>()); - // RunUntilIdle() is needed because ModelTypeProcessorProxy() is used and it - // internally does posting of tasks. - base::RunLoop().RunUntilIdle(); EXPECT_TRUE(processor()->IsConnectedForTest()); }
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.cc b/components/sync/nigori/nigori_sync_bridge_impl.cc index 400a1eb3..fe7f451 100644 --- a/components/sync/nigori/nigori_sync_bridge_impl.cc +++ b/components/sync/nigori/nigori_sync_bridge_impl.cc
@@ -314,6 +314,25 @@ return base::Time(); } +Cryptographer* NigoriSyncBridgeImpl::GetCryptographerUnsafe() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // This method exposes Cryptographer to Directory, and it's redundant in case + // USS implementation is enabled. + return nullptr; +} + +KeystoreKeysHandler* NigoriSyncBridgeImpl::GetKeystoreKeysHandler() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return this; +} + +syncable::NigoriHandler* NigoriSyncBridgeImpl::GetNigoriHandler() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // Note: GetNigoriHandler() is a workaround for coexistence with Directory + // implementation, returning nullptr here is expected behavior. + return nullptr; +} + bool NigoriSyncBridgeImpl::NeedKeystoreKey() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // We explicitly ask the server for keystore keys iff it's first-time sync,
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.h b/components/sync/nigori/nigori_sync_bridge_impl.h index fcf14f1..d779999 100644 --- a/components/sync/nigori/nigori_sync_bridge_impl.h +++ b/components/sync/nigori/nigori_sync_bridge_impl.h
@@ -53,6 +53,9 @@ void EnableEncryptEverything() override; bool IsEncryptEverythingEnabled() const override; base::Time GetKeystoreMigrationTime() const override; + Cryptographer* GetCryptographerUnsafe() override; + KeystoreKeysHandler* GetKeystoreKeysHandler() override; + syncable::NigoriHandler* GetNigoriHandler() override; // KeystoreKeysHandler implementation. bool NeedKeystoreKey() const override;
diff --git a/components/sync/test/engine/test_directory_setter_upper.cc b/components/sync/test/engine/test_directory_setter_upper.cc index a193683..138a6df 100644 --- a/components/sync/test/engine/test_directory_setter_upper.cc +++ b/components/sync/test/engine/test_directory_setter_upper.cc
@@ -35,7 +35,7 @@ name_, base::BindRepeating( []() -> std::string { return "kTestCacheGuid"; })), MakeWeakHandle(handler_.GetWeakPtr()), base::Closure(), - &encryption_handler_, encryption_handler_.cryptographer()); + &encryption_handler_, encryption_handler_.GetCryptographerUnsafe()); ASSERT_EQ(syncable::OPENED_NEW, directory_->Open(name_, &delegate_, transaction_observer)); directory_->set_cache_guid("kTestCacheGuid"); @@ -52,7 +52,7 @@ directory_ = std::make_unique<syncable::Directory>( std::move(directory_store), MakeWeakHandle(handler_.GetWeakPtr()), base::Closure(), &encryption_handler_, - encryption_handler_.cryptographer()); + encryption_handler_.GetCryptographerUnsafe()); ASSERT_EQ(syncable::OPENED_EXISTING, directory_->Open(name_, &delegate_, transaction_observer)); directory_->set_cache_guid("kTestCacheGuid");
diff --git a/components/sync/test/fake_sync_encryption_handler.cc b/components/sync/test/fake_sync_encryption_handler.cc index 1a089dbd..e66e709 100644 --- a/components/sync/test/fake_sync_encryption_handler.cc +++ b/components/sync/test/fake_sync_encryption_handler.cc
@@ -128,4 +128,16 @@ return base::Time(); } +Cryptographer* FakeSyncEncryptionHandler::GetCryptographerUnsafe() { + return &cryptographer_; +} + +KeystoreKeysHandler* FakeSyncEncryptionHandler::GetKeystoreKeysHandler() { + return this; +} + +syncable::NigoriHandler* FakeSyncEncryptionHandler::GetNigoriHandler() { + return this; +} + } // namespace syncer
diff --git a/components/sync/test/fake_sync_encryption_handler.h b/components/sync/test/fake_sync_encryption_handler.h index 002b065..34869c1 100644 --- a/components/sync/test/fake_sync_encryption_handler.h +++ b/components/sync/test/fake_sync_encryption_handler.h
@@ -43,6 +43,9 @@ PassphraseType GetPassphraseType( syncable::BaseTransaction* const trans) const override; base::Time GetKeystoreMigrationTime() const override; + Cryptographer* GetCryptographerUnsafe() override; + KeystoreKeysHandler* GetKeystoreKeysHandler() override; + syncable::NigoriHandler* GetNigoriHandler() override; // NigoriHandler implemenation. void ApplyNigoriUpdate(const sync_pb::NigoriSpecifics& nigori, @@ -57,8 +60,6 @@ bool NeedKeystoreKey() const override; bool SetKeystoreKeys(const std::vector<std::string>& keys) override; - Cryptographer* cryptographer() { return &cryptographer_; } - private: base::ObserverList<SyncEncryptionHandler::Observer>::Unchecked observers_; ModelTypeSet encrypted_types_;
diff --git a/components/sync_sessions/local_session_event_handler_impl_unittest.cc b/components/sync_sessions/local_session_event_handler_impl_unittest.cc index 79fe3ed..b585262 100644 --- a/components/sync_sessions/local_session_event_handler_impl_unittest.cc +++ b/components/sync_sessions/local_session_event_handler_impl_unittest.cc
@@ -596,7 +596,14 @@ AddTab(kWindowId1, kBar1, kTabId2); } -TEST_F(LocalSessionEventHandlerImplTest, PropagateClosedTab) { +TEST_F(LocalSessionEventHandlerImplTest, + PropagateClosedTabWithoutDeferredRecyclingNorImmediateDeletion) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{}, + /*disabled_features=*/{kDeferRecyclingOfSyncTabNodesIfUnsynced, + kTabNodePoolImmediateDeletion}); + AddWindow(kWindowId1); AddTab(kWindowId1, kFoo1, kTabId1); TestSyncedTabDelegate* tab2 = AddTab(kWindowId1, kBar1, kTabId2); @@ -625,8 +632,7 @@ handler_->OnLocalTabModified(tab2); } -TEST_F(LocalSessionEventHandlerImplTest, - PropagateClosedTabWithDeferredRecyclingAndImmediateDeletion) { +TEST_F(LocalSessionEventHandlerImplTest, PropagateClosedTab) { base::test::ScopedFeatureList feature_list; feature_list.InitWithFeatures( /*enabled_features=*/{kDeferRecyclingOfSyncTabNodesIfUnsynced,
diff --git a/components/sync_sessions/session_sync_bridge_unittest.cc b/components/sync_sessions/session_sync_bridge_unittest.cc index 8d0bab38..f4ced44 100644 --- a/components/sync_sessions/session_sync_bridge_unittest.cc +++ b/components/sync_sessions/session_sync_bridge_unittest.cc
@@ -879,9 +879,8 @@ /*tab_node_id=*/1, {"http://bar.com/"}))))); } -TEST_F(SessionSyncBridgeTest, ShouldRestoreLocalSessionWithFreedTab) { - const int kWindowId1 = 1000001; - const int kWindowId2 = 1000002; +TEST_F(SessionSyncBridgeTest, ShouldRecycleTabNodeAfterCommitCompleted) { + const int kWindowId = 1000001; const int kTabId1 = 1000003; const int kTabId2 = 1000004; const int kTabId3 = 1000005; @@ -889,6 +888,107 @@ // Zero is the first assigned tab node ID. const int kTabNodeId1 = 0; const int kTabNodeId2 = 1; + const int kTabNodeId3 = 2; + + AddWindow(kWindowId); + TestSyncedTabDelegate* tab1 = AddTab(kWindowId, "http://foo.com/", kTabId1); + + const std::string header_storage_key = + SessionStore::GetHeaderStorageKey(kLocalSessionTag); + const std::string tab_storage_key1 = + SessionStore::GetTabStorageKey(kLocalSessionTag, kTabNodeId1); + const std::string tab_storage_key2 = + SessionStore::GetTabStorageKey(kLocalSessionTag, kTabNodeId2); + const std::string tab_storage_key3 = + SessionStore::GetTabStorageKey(kLocalSessionTag, kTabNodeId3); + const std::string tab_client_tag1 = + SessionStore::GetTabClientTagForTest(kLocalSessionTag, kTabNodeId1); + const std::string tab_client_tag2 = + SessionStore::GetTabClientTagForTest(kLocalSessionTag, kTabNodeId2); + const std::string tab_client_tag3 = + SessionStore::GetTabClientTagForTest(kLocalSessionTag, kTabNodeId3); + + InitializeBridge(); + StartSyncing(); + + // Mimic a commit completing for the initial sync. + ASSERT_TRUE(real_processor()->HasLocalChangesForTest()); + sync_pb::ModelTypeState state; + state.set_initial_sync_done(true); + real_processor()->OnCommitCompleted(state, + {CreateSuccessResponse(kLocalSessionTag), + CreateSuccessResponse(tab_client_tag1)}); + ASSERT_FALSE(real_processor()->HasLocalChangesForTest()); + + // Open a second tab. + AddTab(kWindowId, "http://bar.com/", kTabId2); + ASSERT_TRUE(real_processor()->HasLocalChangesForTest()); + + // Close |kTabId2| and force reassociation by navigating in the remaining open + // tab, leading to a freed tab entity. However, while there are pending + // changes to commit, the entity shouldn't be deleted (to prevent history + // loss). + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + CloseTab(kTabId2); + tab1->Navigate("http://foo2.com/"); + EXPECT_TRUE(real_processor()->HasLocalChangesForTest()); + + EXPECT_THAT( + GetAllData(), + UnorderedElementsAre( + Pair(header_storage_key, + EntityDataHasSpecifics( + MatchesHeader(kLocalSessionTag, {kWindowId}, {kTabId1}))), + Pair(tab_storage_key1, + EntityDataHasSpecifics( + MatchesTab(kLocalSessionTag, kWindowId, kTabId1, kTabNodeId1, + {"http://foo.com/", "http://foo2.com/"}))), + Pair(tab_storage_key2, EntityDataHasSpecifics(MatchesTab( + kLocalSessionTag, kWindowId, kTabId2, + kTabNodeId2, {"http://bar.com/"}))))); + + // If a new tab is opened, the entity with unsynced changes should not be + // recycled. + AddTab(kWindowId, "http://baz.com/", kTabId3); + EXPECT_THAT(GetAllData(), UnorderedElementsAre(Pair(header_storage_key, _), + Pair(tab_storage_key1, _), + Pair(tab_storage_key2, _), + Pair(tab_storage_key3, _))); + + // Completing the commit for the previously closed tab should issue a + // deletion. For that to trigger, we need to trigger the next association, + // which we do by navigating in one of the open tabs. + EXPECT_CALL(mock_processor(), Delete(tab_storage_key2, _)); + real_processor()->OnCommitCompleted(state, + {CreateSuccessResponse(tab_client_tag2)}); + tab1->Navigate("http://foo3.com/"); + EXPECT_THAT(GetAllData(), UnorderedElementsAre(Pair(header_storage_key, _), + Pair(tab_storage_key1, _), + Pair(tab_storage_key3, _))); + + // If yet anothertab is opened, the entity for the closed tab should be + // recycled. + AddTab(kWindowId, "http://qux.com/", kTabId4); + EXPECT_THAT( + GetAllData(), + UnorderedElementsAre( + Pair(header_storage_key, _), Pair(tab_storage_key1, _), + Pair(tab_storage_key2, EntityDataHasSpecifics(MatchesTab( + kLocalSessionTag, kWindowId, kTabId4, + kTabNodeId2, {"http://qux.com/"}))), + Pair(tab_storage_key3, _))); +} + +TEST_F(SessionSyncBridgeTest, ShouldRestoreLocalSessionWithFreedTab) { + const int kWindowId1 = 1000001; + const int kWindowId2 = 1000002; + const int kTabId1 = 1000003; + const int kTabId2 = 1000004; + const int kTabId3 = 1000005; + // Zero is the first assigned tab node ID. + const int kTabNodeId1 = 0; + const int kTabNodeId2 = 1; + const int kTabNodeId3 = 2; AddWindow(kWindowId1); TestSyncedTabDelegate* tab1 = AddTab(kWindowId1, "http://foo.com/", kTabId1); @@ -900,6 +1000,8 @@ SessionStore::GetTabStorageKey(kLocalSessionTag, kTabNodeId1); const std::string tab_storage_key2 = SessionStore::GetTabStorageKey(kLocalSessionTag, kTabNodeId2); + const std::string tab_storage_key3 = + SessionStore::GetTabStorageKey(kLocalSessionTag, kTabNodeId3); InitializeBridge(); StartSyncing(); @@ -911,7 +1013,7 @@ // Close |kTabId2| and force reassociation by navigating in the remaining open // tab, leading to a freed tab entity. CloseTab(kTabId2); - tab1->Navigate("http://baz.com/"); + tab1->Navigate("http://foo2.com/"); ASSERT_THAT(GetData(header_storage_key), EntityDataHasSpecifics( @@ -923,39 +1025,31 @@ // The browser gets restarted with a new initial tab, for example because the // user chose "Continue where you left off". AddWindow(kWindowId2); - AddTab(kWindowId2, "http://qux.com/", kTabId3); + AddTab(kWindowId2, "http://baz.com/", kTabId3); // Start the bridge again. InitializeBridge(); StartSyncing(); - // One tab node de should be free at this point. In the current implementation - // (subject to change), this is |kTabNodeId1|. This is because |kTabId3| is - // assigned |kTabNodeId2|. + // Two tab nodes should be free at this point, because both tabs have been + // closed. However, they are also unsynced (the commit hasn't completed), + // which prevents their recycling, so a new tab node should be created. ASSERT_THAT( GetAllData(), UnorderedElementsAre( Pair(header_storage_key, EntityDataHasSpecifics( MatchesHeader(kLocalSessionTag, {kWindowId2}, {kTabId3}))), + Pair(tab_storage_key1, + EntityDataHasSpecifics(MatchesTab( + kLocalSessionTag, kWindowId1, kTabId1, kTabNodeId1, + {"http://foo.com/", "http://foo2.com/"}))), Pair(tab_storage_key2, EntityDataHasSpecifics(MatchesTab( + kLocalSessionTag, kWindowId1, kTabId2, + kTabNodeId2, {"http://bar.com/"}))), + Pair(tab_storage_key3, EntityDataHasSpecifics(MatchesTab( kLocalSessionTag, kWindowId2, kTabId3, - kTabNodeId2, {"http://qux.com/"}))))); - - // When a new tab is opened (|kTabId4|), |kTabNodeId1| should be reused. - AddTab(kWindowId2, "http://quux.com/", kTabId4); - EXPECT_THAT( - GetAllData(), - UnorderedElementsAre( - Pair(header_storage_key, - EntityDataHasSpecifics(MatchesHeader( - kLocalSessionTag, {kWindowId2}, {kTabId3, kTabId4}))), - Pair(tab_storage_key2, EntityDataHasSpecifics(MatchesTab( - kLocalSessionTag, kWindowId2, kTabId3, - kTabNodeId2, {"http://qux.com/"}))), - Pair(tab_storage_key1, EntityDataHasSpecifics(MatchesTab( - kLocalSessionTag, kWindowId2, kTabId4, - kTabNodeId1, {"http://quux.com/"}))))); + kTabNodeId3, {"http://baz.com/"}))))); } TEST_F(SessionSyncBridgeTest, ShouldDisableSyncAndReenable) {
diff --git a/components/sync_sessions/synced_session_tracker.cc b/components/sync_sessions/synced_session_tracker.cc index e7cba48..ae74d64 100644 --- a/components/sync_sessions/synced_session_tracker.cc +++ b/components/sync_sessions/synced_session_tracker.cc
@@ -16,8 +16,7 @@ namespace sync_sessions { const base::Feature kDeferRecyclingOfSyncTabNodesIfUnsynced{ - "DeferRecyclingOfSyncTabNodesIfUnsynced", - base::FEATURE_DISABLED_BY_DEFAULT}; + "DeferRecyclingOfSyncTabNodesIfUnsynced", base::FEATURE_ENABLED_BY_DEFAULT}; namespace { @@ -544,7 +543,7 @@ DCHECK(!local_session_tag_.empty()); TrackedSession* session = GetTrackedSession(local_session_tag_); CleanupSessionImpl(local_session_tag_, is_tab_node_unsynced_cb); - return session->tab_node_pool.CleanupTabNodes(); + return session->tab_node_pool.CleanupFreeTabNodes(); } int SyncedSessionTracker::LookupTabNodeFromTabId(const std::string& session_tag,
diff --git a/components/sync_sessions/synced_session_tracker_unittest.cc b/components/sync_sessions/synced_session_tracker_unittest.cc index eb97e15..8d8ea54 100644 --- a/components/sync_sessions/synced_session_tracker_unittest.cc +++ b/components/sync_sessions/synced_session_tracker_unittest.cc
@@ -494,7 +494,13 @@ ASSERT_TRUE(VerifyTabIntegrity(kTag)); } -TEST_F(SyncedSessionTrackerTest, CleanupLocalTabs) { +TEST_F(SyncedSessionTrackerTest, CleanupLocalTabsWithoutDeferredRecycling) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{}, + /*disabled_features=*/{kDeferRecyclingOfSyncTabNodesIfUnsynced, + kTabNodePoolImmediateDeletion}); + tracker_.InitLocalSession(kTag, kSessionName, kDeviceType); // Start with two restored tab nodes. @@ -537,7 +543,7 @@ ASSERT_TRUE(VerifyTabIntegrity(kTag)); } -TEST_F(SyncedSessionTrackerTest, CleanupLocalTabsWithDeferredRecycling) { +TEST_F(SyncedSessionTrackerTest, CleanupLocalTabs) { base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(kDeferRecyclingOfSyncTabNodesIfUnsynced); @@ -570,8 +576,8 @@ // During cleanup, only two tabs should be freed: // - |kTabNode3| because of its age, although it's unsynced. // - |kTabNode4| because it's synced. - EXPECT_TRUE( - tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()).empty()); + EXPECT_THAT(tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()), + ElementsAre(kTabNode3, kTabNode4)); ASSERT_EQ(kTabNode1, tracker_.LookupTabNodeFromTabId(kTag, kTab1)); EXPECT_EQ(kTabNode2, tracker_.LookupTabNodeFromTabId(kTag, kTab2)); EXPECT_EQ(TabNodePool::kInvalidTabNodeID, @@ -582,8 +588,8 @@ // |kTabNode2| now becomes synced (commit succeeded), which means it should be // freed during cleanup. EXPECT_CALL(is_tab_node_unsynced_cb_, Run(kTabNode2)).WillOnce(Return(false)); - EXPECT_TRUE( - tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()).empty()); + EXPECT_THAT(tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()), + ElementsAre(kTabNode2)); EXPECT_EQ(TabNodePool::kInvalidTabNodeID, tracker_.LookupTabNodeFromTabId(kTag, kTab2)); EXPECT_EQ(kTabNode2, tracker_.AssociateLocalTabWithFreeTabNode(kTab5)); @@ -745,8 +751,7 @@ EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1)); tracker_.PutWindowInSession(kTag, kWindow1); tracker_.PutTabInWindow(kTag, kWindow1, kTab2); - EXPECT_TRUE( - tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()).empty()); + tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()); ASSERT_TRUE(VerifyTabIntegrity(kTag)); EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1)); EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab2));
diff --git a/components/sync_sessions/tab_node_pool.cc b/components/sync_sessions/tab_node_pool.cc index 24f5be8..0eb692e 100644 --- a/components/sync_sessions/tab_node_pool.cc +++ b/components/sync_sessions/tab_node_pool.cc
@@ -20,7 +20,7 @@ const size_t TabNodePool::kFreeNodesHighWatermark = 100; const base::Feature kTabNodePoolImmediateDeletion{ - "TabNodePoolImmediateDeletion", base::FEATURE_DISABLED_BY_DEFAULT}; + "TabNodePoolImmediateDeletion", base::FEATURE_ENABLED_BY_DEFAULT}; TabNodePool::TabNodePool() : max_used_tab_node_id_(kInvalidTabNodeID) {} @@ -147,7 +147,7 @@ return SessionID::InvalidValue(); } -std::set<int> TabNodePool::CleanupTabNodes() { +std::set<int> TabNodePool::CleanupFreeTabNodes() { if (base::FeatureList::IsEnabled(kTabNodePoolImmediateDeletion)) { // Convert all free nodes into missing nodes, each representing a deletion. missing_nodes_pool_.insert(free_nodes_pool_.begin(),
diff --git a/components/sync_sessions/tab_node_pool.h b/components/sync_sessions/tab_node_pool.h index c7655cb..01f6874 100644 --- a/components/sync_sessions/tab_node_pool.h +++ b/components/sync_sessions/tab_node_pool.h
@@ -68,10 +68,8 @@ // pool. void FreeTab(SessionID tab_id); - // Returns the IDs for any free nodes to be deleted as proscribed by the free - // node low/high watermarks, in order to ensure the free node pool does not - // grow too large. - std::set<int> CleanupTabNodes(); + // Deletes all free tab nodes. Returns the IDs of the deleted nodes. + std::set<int> CleanupFreeTabNodes(); // Deletes all known mappings for |tab_node_id|. As opposed to FreeTab(), it // does NOT free the node for later reuse. This is used for foreign sessions
diff --git a/components/sync_sessions/tab_node_pool_unittest.cc b/components/sync_sessions/tab_node_pool_unittest.cc index f2bface8..b2eb15ca 100644 --- a/components/sync_sessions/tab_node_pool_unittest.cc +++ b/components/sync_sessions/tab_node_pool_unittest.cc
@@ -19,7 +19,6 @@ const int kTabNodeId1 = 10; const int kTabNodeId2 = 5; -const int kTabNodeId3 = 30; const SessionID kTabId1 = SessionID::FromSerializedValue(1010); const SessionID kTabId2 = SessionID::FromSerializedValue(1020); const SessionID kTabId3 = SessionID::FromSerializedValue(1030); @@ -44,31 +43,48 @@ TabNodePool pool_; }; -TEST_F(SyncTabNodePoolTest, TabNodeIdIncreases) { - // max_used_tab_node_ always increases. - pool_.ReassociateTabNode(kTabNodeId1, kTabId1); - EXPECT_EQ(kTabNodeId1, GetMaxUsedTabNodeId()); - pool_.ReassociateTabNode(kTabNodeId2, kTabId2); - EXPECT_EQ(kTabNodeId1, GetMaxUsedTabNodeId()); - pool_.ReassociateTabNode(kTabNodeId3, kTabId3); - EXPECT_EQ(kTabNodeId3, GetMaxUsedTabNodeId()); - // Freeing a tab node does not change max_used_tab_node_id_. +TEST_F(SyncTabNodePoolTest, MaxTabNodeIdShouldIncrease) { + EXPECT_EQ(-1, GetMaxUsedTabNodeId()); + pool_.ReassociateTabNode(10, kTabId1); + EXPECT_EQ(10, GetMaxUsedTabNodeId()); + pool_.ReassociateTabNode(5, kTabId2); + EXPECT_EQ(10, GetMaxUsedTabNodeId()); + pool_.ReassociateTabNode(20, kTabId3); + EXPECT_EQ(20, GetMaxUsedTabNodeId()); +} + +TEST_F(SyncTabNodePoolTest, MaxTabNodeIdShouldDecrease) { + pool_.ReassociateTabNode(10, kTabId1); + pool_.ReassociateTabNode(5, kTabId2); + pool_.ReassociateTabNode(20, kTabId3); + EXPECT_EQ(20, GetMaxUsedTabNodeId()); + pool_.FreeTab(kTabId3); - pool_.CleanupTabNodes(); - pool_.FreeTab(kTabId2); - EXPECT_THAT(pool_.CleanupTabNodes(), IsEmpty()); + ASSERT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(20)); + EXPECT_EQ(10, GetMaxUsedTabNodeId()); + pool_.FreeTab(kTabId1); - EXPECT_THAT(pool_.CleanupTabNodes(), IsEmpty()); - for (int i = 0; i < 3; ++i) { - const SessionID tab_id = SessionID::FromSerializedValue(i + 1); - ASSERT_EQ(TabNodePool::kInvalidTabNodeID, - pool_.GetTabNodeIdFromTabId(tab_id)); - EXPECT_NE(TabNodePool::kInvalidTabNodeID, - pool_.AssociateWithFreeTabNode(tab_id)); - EXPECT_EQ(kTabNodeId3, GetMaxUsedTabNodeId()); - } - EXPECT_THAT(pool_.CleanupTabNodes(), IsEmpty()); - EXPECT_EQ(kTabNodeId3, GetMaxUsedTabNodeId()); + ASSERT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(10)); + EXPECT_EQ(5, GetMaxUsedTabNodeId()); + + pool_.FreeTab(kTabId2); + ASSERT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(5)); + EXPECT_EQ(-1, GetMaxUsedTabNodeId()); +} + +TEST_F(SyncTabNodePoolTest, MaxTabNodeIdShouldNotChange) { + pool_.ReassociateTabNode(10, kTabId1); + pool_.ReassociateTabNode(5, kTabId2); + pool_.ReassociateTabNode(20, kTabId3); + EXPECT_EQ(20, GetMaxUsedTabNodeId()); + + pool_.FreeTab(kTabId1); + ASSERT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(10)); + EXPECT_EQ(20, GetMaxUsedTabNodeId()); + + pool_.FreeTab(kTabId2); + ASSERT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(5)); + EXPECT_EQ(20, GetMaxUsedTabNodeId()); } TEST_F(SyncTabNodePoolTest, Reassociation) { @@ -136,7 +152,10 @@ EXPECT_EQ(0, pool_.AssociateWithFreeTabNode(kTabId3)); } -TEST_F(SyncTabNodePoolTest, TabPoolFreeNodeLimits) { +TEST_F(SyncTabNodePoolTest, TabPoolFreeNodeWatermarkLimits) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(kTabNodePoolImmediateDeletion); + // Allocate TabNodePool::kFreeNodesHighWatermark + 1 nodes and verify that // freeing the last node reduces the free node pool size to // kFreeNodesLowWatermark. @@ -151,17 +170,16 @@ for (size_t i = 1; i <= used_sync_ids.size(); ++i) { pool_.FreeTab(SessionID::FromSerializedValue(i)); - EXPECT_THAT(pool_.CleanupTabNodes(), IsEmpty()); + EXPECT_THAT(pool_.CleanupFreeTabNodes(), IsEmpty()); } // Freeing the last sync node should drop the free nodes to // kFreeNodesLowWatermark. pool_.FreeTab( SessionID::FromSerializedValue(TabNodePool::kFreeNodesHighWatermark + 1)); - std::set<int> deleted_node_ids = pool_.CleanupTabNodes(); - EXPECT_EQ(TabNodePool::kFreeNodesHighWatermark + 1 - - TabNodePool::kFreeNodesLowWatermark, - deleted_node_ids.size()); + std::set<int> deleted_node_ids = pool_.CleanupFreeTabNodes(); + EXPECT_EQ(deleted_node_ids.size(), TabNodePool::kFreeNodesHighWatermark + 1 - + TabNodePool::kFreeNodesLowWatermark); // Make sure the highest ones are deleted. EXPECT_EQ(0U, deleted_node_ids.count(TabNodePool::kFreeNodesLowWatermark - 1)); @@ -191,42 +209,33 @@ EXPECT_EQ(2, pool_.AssociateWithFreeTabNode(kTabId5)); } -TEST_F(SyncTabNodePoolTest, AggressiveCleanupTabNodesMiddle) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(kTabNodePoolImmediateDeletion); - +TEST_F(SyncTabNodePoolTest, AggressiveCleanupFreeTabNodesMiddle) { pool_.ReassociateTabNode(/*tab_node_id=*/0, kTabId1); pool_.ReassociateTabNode(/*tab_node_id=*/1, kTabId2); pool_.ReassociateTabNode(/*tab_node_id=*/2, kTabId3); pool_.FreeTab(kTabId2); - EXPECT_THAT(pool_.CleanupTabNodes(), UnorderedElementsAre(1)); + EXPECT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(1)); EXPECT_EQ(2, GetMaxUsedTabNodeId()); EXPECT_EQ(1, pool_.AssociateWithFreeTabNode(kTabId4)); EXPECT_EQ(3, pool_.AssociateWithFreeTabNode(kTabId5)); } -TEST_F(SyncTabNodePoolTest, AggressiveCleanupTabNodesMax) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(kTabNodePoolImmediateDeletion); - +TEST_F(SyncTabNodePoolTest, AggressiveCleanupFreeTabNodesMax) { pool_.ReassociateTabNode(/*tab_node_id=*/0, kTabId1); pool_.ReassociateTabNode(/*tab_node_id=*/1, kTabId2); pool_.ReassociateTabNode(/*tab_node_id=*/2, kTabId3); pool_.FreeTab(kTabId3); - EXPECT_THAT(pool_.CleanupTabNodes(), UnorderedElementsAre(2)); + EXPECT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(2)); EXPECT_EQ(1, GetMaxUsedTabNodeId()); EXPECT_EQ(2, pool_.AssociateWithFreeTabNode(kTabId4)); EXPECT_EQ(3, pool_.AssociateWithFreeTabNode(kTabId5)); } -TEST_F(SyncTabNodePoolTest, AggressiveCleanupTabNodesMultiple) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(kTabNodePoolImmediateDeletion); - +TEST_F(SyncTabNodePoolTest, AggressiveCleanupFreeTabNodesMultiple) { pool_.ReassociateTabNode(/*tab_node_id=*/0, kTabId1); pool_.ReassociateTabNode(/*tab_node_id=*/1, kTabId2); pool_.ReassociateTabNode(/*tab_node_id=*/2, kTabId3); @@ -234,22 +243,19 @@ pool_.FreeTab(kTabId1); pool_.FreeTab(kTabId2); - EXPECT_THAT(pool_.CleanupTabNodes(), UnorderedElementsAre(0, 1)); + EXPECT_THAT(pool_.CleanupFreeTabNodes(), UnorderedElementsAre(0, 1)); EXPECT_EQ(2, GetMaxUsedTabNodeId()); EXPECT_EQ(0, pool_.AssociateWithFreeTabNode(kTabId4)); EXPECT_EQ(1, pool_.AssociateWithFreeTabNode(kTabId5)); EXPECT_EQ(3, pool_.AssociateWithFreeTabNode(kTabId6)); } -TEST_F(SyncTabNodePoolTest, AggressiveCleanupTabNodesAll) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(kTabNodePoolImmediateDeletion); - +TEST_F(SyncTabNodePoolTest, AggressiveCleanupFreeTabNodesAll) { pool_.ReassociateTabNode(/*tab_node_id=*/0, kTabId1); pool_.FreeTab(kTabId1); - EXPECT_THAT(pool_.CleanupTabNodes(), UnorderedElementsAre(0)); + EXPECT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(0)); EXPECT_EQ(-1, GetMaxUsedTabNodeId()); EXPECT_EQ(0, pool_.AssociateWithFreeTabNode(kTabId4)); }
diff --git a/components/tracing/test/trace_event_perftest.cc b/components/tracing/test/trace_event_perftest.cc index 2cd7a03..684a8d2 100644 --- a/components/tracing/test/trace_event_perftest.cc +++ b/components/tracing/test/trace_event_perftest.cc
@@ -7,9 +7,9 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted_memory.h" -#include "base/message_loop/message_loop.h" #include "base/pending_task.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "base/threading/thread.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" @@ -90,7 +90,7 @@ } private: - base::MessageLoop _message_loop; + base::test::ScopedTaskEnvironment scoped_task_environment; }; TEST_F(TraceEventPerfTest, Submit_10000_TRACE_EVENT0) {
diff --git a/components/viz/client/shared_bitmap_reporter.h b/components/viz/client/shared_bitmap_reporter.h index b2e1549..ca9bfaa 100644 --- a/components/viz/client/shared_bitmap_reporter.h +++ b/components/viz/client/shared_bitmap_reporter.h
@@ -5,9 +5,9 @@ #ifndef COMPONENTS_VIZ_CLIENT_SHARED_BITMAP_REPORTER_H_ #define COMPONENTS_VIZ_CLIENT_SHARED_BITMAP_REPORTER_H_ +#include "base/memory/read_only_shared_memory_region.h" #include "components/viz/client/viz_client_export.h" #include "components/viz/common/resources/shared_bitmap.h" -#include "mojo/public/cpp/system/buffer.h" namespace viz { @@ -19,7 +19,7 @@ class VIZ_CLIENT_EXPORT SharedBitmapReporter { public: // Associates a SharedBitmapId with a shared buffer handle. - virtual void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + virtual void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const SharedBitmapId& id) = 0; // Disassociates a SharedBitmapId previously passed to
diff --git a/components/viz/common/resources/bitmap_allocation.cc b/components/viz/common/resources/bitmap_allocation.cc index ede0e1f3..fd5d22f 100644 --- a/components/viz/common/resources/bitmap_allocation.cc +++ b/components/viz/common/resources/bitmap_allocation.cc
@@ -62,16 +62,6 @@ return shm; } -mojo::ScopedSharedBufferHandle ToMojoHandle( - base::ReadOnlySharedMemoryRegion region) { - return mojo::WrapReadOnlySharedMemoryRegion(std::move(region)); -} - -base::ReadOnlySharedMemoryRegion FromMojoHandle( - mojo::ScopedSharedBufferHandle handle) { - return mojo::UnwrapReadOnlySharedMemoryRegion(std::move(handle)); -} - } // namespace bitmap_allocation } // namespace viz
diff --git a/components/viz/common/resources/bitmap_allocation.h b/components/viz/common/resources/bitmap_allocation.h index 8900a16..8068a193 100644 --- a/components/viz/common/resources/bitmap_allocation.h +++ b/components/viz/common/resources/bitmap_allocation.h
@@ -26,22 +26,6 @@ const gfx::Size& size, ResourceFormat format); -// Converts a base::ReadOnlySharedMemoryRegion to its corresponding -// Mojo scoped handle. This simply calls mojo::WrapReadOnlySharedMemoryRegion() -// but allows the caller to not include the corresponding header where it is -// defined. Moreover, it will be easy to grep for all uses of this method -// in the future when MojoHandles will not longer be necessary. -// TODO(crbug.com/951391): Remove once refactor is completed. -VIZ_COMMON_EXPORT mojo::ScopedSharedBufferHandle ToMojoHandle( - base::ReadOnlySharedMemoryRegion region); - -// Converts a scoped Mojo handle back to a base::ReadOnlySharedMemoryRegion -// This simply calls mojo::UnwrapReadOnlySharedMemoryRegion(), but has the same -// benefits as ToMojoHandle() described above. -// TODO(crbug.com/951391): Remove once refactor is completed. -VIZ_COMMON_EXPORT base::ReadOnlySharedMemoryRegion FromMojoHandle( - mojo::ScopedSharedBufferHandle handle); - } // namespace bitmap_allocation } // namespace viz
diff --git a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc index d084b0b4..6c9e745b 100644 --- a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc +++ b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
@@ -58,10 +58,8 @@ sink_client.BindInterfacePtr()); for (auto& fuzzed_bitmap : allocated_bitmaps) { - sink_ptr->DidAllocateSharedBitmap( - bitmap_allocation::ToMojoHandle( - fuzzed_bitmap.shared_region.Duplicate()), - fuzzed_bitmap.id); + sink_ptr->DidAllocateSharedBitmap(fuzzed_bitmap.shared_region.Duplicate(), + fuzzed_bitmap.id); } lsi_allocator_.GenerateId();
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc index c9d6235..41754d2 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc
@@ -88,9 +88,9 @@ } void CompositorFrameSinkImpl::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, + base::ReadOnlySharedMemoryRegion region, const SharedBitmapId& id) { - if (!support_->DidAllocateSharedBitmap(std::move(buffer), id)) { + if (!support_->DidAllocateSharedBitmap(std::move(region), id)) { DLOG(ERROR) << "DidAllocateSharedBitmap failed for duplicate " << "SharedBitmapId"; compositor_frame_sink_binding_.Close();
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_impl.h b/components/viz/service/frame_sinks/compositor_frame_sink_impl.h index b05aaea..8eb02da 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_impl.h +++ b/components/viz/service/frame_sinks/compositor_frame_sink_impl.h
@@ -6,6 +6,7 @@ #define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_COMPOSITOR_FRAME_SINK_IMPL_H_ #include "base/macros.h" +#include "base/memory/read_only_shared_memory_region.h" #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/local_surface_id.h" #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h" @@ -42,7 +43,7 @@ uint64_t submit_time, SubmitCompositorFrameSyncCallback callback) override; void DidNotProduceFrame(const BeginFrameAck& begin_frame_ack) override; - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const SharedBitmapId& id) override; void DidDeleteSharedBitmap(const SharedBitmapId& id) override;
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc index 324e69a9..8f028bb2 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -334,10 +334,10 @@ } bool CompositorFrameSinkSupport::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, + base::ReadOnlySharedMemoryRegion region, const SharedBitmapId& id) { if (!frame_sink_manager_->shared_bitmap_manager()->ChildAllocatedSharedBitmap( - bitmap_allocation::FromMojoHandle(std::move(buffer)).Map(), id)) { + region.Map(), id)) { return false; }
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h index a6b5fd83..723b061 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/time/time.h" @@ -143,7 +144,7 @@ base::Optional<HitTestRegionList> hit_test_region_list = base::nullopt, uint64_t submit_time = 0); // Returns false if the notification was not valid (a duplicate). - bool DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + bool DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const SharedBitmapId& id); void DidDeleteSharedBitmap(const SharedBitmapId& id);
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc index 7529d22..bc7ad62f 100644 --- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc +++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
@@ -185,9 +185,9 @@ } void DirectLayerTreeFrameSink::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, + base::ReadOnlySharedMemoryRegion region, const SharedBitmapId& id) { - bool ok = support_->DidAllocateSharedBitmap(std::move(buffer), id); + bool ok = support_->DidAllocateSharedBitmap(std::move(region), id); DCHECK(ok); }
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h index a8a61f0..15ae36b 100644 --- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h +++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
@@ -6,6 +6,7 @@ #define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_DIRECT_LAYER_TREE_FRAME_SINK_H_ #include "base/macros.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" #include "cc/trees/layer_tree_frame_sink.h" @@ -73,7 +74,7 @@ bool hit_test_data_changed, bool show_hit_test_borders) override; void DidNotProduceFrame(const BeginFrameAck& ack) override; - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const SharedBitmapId& id) override; void DidDeleteSharedBitmap(const SharedBitmapId& id) override;
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc index 89ee7f6..b58ef60 100644 --- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc +++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
@@ -274,9 +274,9 @@ } void RootCompositorFrameSinkImpl::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, + base::ReadOnlySharedMemoryRegion region, const SharedBitmapId& id) { - if (!support_->DidAllocateSharedBitmap(std::move(buffer), id)) { + if (!support_->DidAllocateSharedBitmap(std::move(region), id)) { DLOG(ERROR) << "DidAllocateSharedBitmap failed for duplicate " << "SharedBitmapId"; compositor_frame_sink_binding_.Close();
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h index e21d989..ba90476 100644 --- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h +++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "base/memory/read_only_shared_memory_region.h" #include "build/build_config.h" #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/local_surface_id.h" @@ -73,7 +74,7 @@ base::Optional<HitTestRegionList> hit_test_region_list, uint64_t submit_time) override; void DidNotProduceFrame(const BeginFrameAck& begin_frame_ack) override; - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const SharedBitmapId& id) override; void DidDeleteSharedBitmap(const SharedBitmapId& id) override; void SubmitCompositorFrameSync(
diff --git a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm index 188fe917..03c722b 100644 --- a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm +++ b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
@@ -680,7 +680,7 @@ // to exit fullscreen and we don't want to prevent them from exiting. ui::DomCode domCode = ui::KeycodeConverter::NativeKeycodeToDomCode(keyCode); return keyboardLockActive_ && domCode != ui::DomCode::ESCAPE && - (!lockedKeys_ || base::ContainsKey(lockedKeys_.value(), domCode)); + (!lockedKeys_ || base::Contains(lockedKeys_.value(), domCode)); } - (BOOL)performKeyEquivalent:(NSEvent*)theEvent {
diff --git a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc index 3583821..c9e23d0 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -190,13 +190,313 @@ dict->Set(kChildrenDictAttr, std::move(children)); } +// TODO(aleventhal) Remove this and use atk_role_get_name() once the following +// GNOME bug is fixed: https://bugzilla.gnome.org/show_bug.cgi?id=795983 +const char* const kRoleNames[] = { + "invalid", // ATK_ROLE_INVALID. + "accelerator label", + "alert", + "animation", + "arrow", + "calendar", + "canvas", + "check box", + "check menu item", + "color chooser", + "column header", + "combo box", + "dateeditor", + "desktop icon", + "desktop frame", + "dial", + "dialog", + "directory pane", + "drawing area", + "file chooser", + "filler", + "fontchooser", + "frame", + "glass pane", + "html container", + "icon", + "image", + "internal frame", + "label", + "layered pane", + "list", + "list item", + "menu", + "menu bar", + "menu item", + "option pane", + "page tab", + "page tab list", + "panel", + "password text", + "popup menu", + "progress bar", + "push button", + "radio button", + "radio menu item", + "root pane", + "row header", + "scroll bar", + "scroll pane", + "separator", + "slider", + "split pane", + "spin button", + "statusbar", + "table", + "table cell", + "table column header", + "table row header", + "tear off menu item", + "terminal", + "text", + "toggle button", + "tool bar", + "tool tip", + "tree", + "tree table", + "unknown", + "viewport", + "window", + "header", + "footer", + "paragraph", + "ruler", + "application", + "autocomplete", + "edit bar", + "embedded component", + "entry", + "chart", + "caption", + "document frame", + "heading", + "page", + "section", + "redundant object", + "form", + "link", + "input method window", + "table row", + "tree item", + "document spreadsheet", + "document presentation", + "document text", + "document web", + "document email", + "comment", + "list box", + "grouping", + "image map", + "notification", + "info bar", + "level bar", + "title bar", + "block quote", + "audio", + "video", + "definition", + "article", + "landmark", + "log", + "marquee", + "math", + "rating", + "timer", + "description list", + "description term", + "description value", + "static", + "math fraction", + "math root", + "subscript", + "superscript", + "footnote", // ATK_ROLE_FOOTNOTE = 122. +}; + void AccessibilityTreeFormatterAuraLinux::AddProperties( const BrowserAccessibility& node, base::DictionaryValue* dict) { dict->SetInteger("id", node.GetId()); BrowserAccessibilityAuraLinux* acc_obj = ToBrowserAccessibilityAuraLinux(const_cast<BrowserAccessibility*>(&node)); - acc_obj->GetNode()->AddAccessibilityTreeProperties(dict); + DCHECK(acc_obj); + + ui::AXPlatformNodeAuraLinux* ax_platform_node = acc_obj->GetNode(); + DCHECK(ax_platform_node); + + AtkObject* atk_object = ax_platform_node->GetNativeViewAccessible(); + DCHECK(atk_object); + + AtkRole role = atk_object_get_role(atk_object); + if (role != ATK_ROLE_UNKNOWN) { + int role_index = static_cast<int>(role); + dict->SetString("role", kRoleNames[role_index]); + } + + const gchar* name = atk_object_get_name(atk_object); + if (name) + dict->SetString("name", std::string(name)); + const gchar* description = atk_object_get_description(atk_object); + if (description) + dict->SetString("description", std::string(description)); + + AtkStateSet* state_set = atk_object_ref_state_set(atk_object); + auto states = std::make_unique<base::ListValue>(); + for (int i = ATK_STATE_INVALID; i < ATK_STATE_LAST_DEFINED; i++) { + AtkStateType state_type = static_cast<AtkStateType>(i); + if (atk_state_set_contains_state(state_set, state_type)) + states->AppendString(atk_state_type_get_name(state_type)); + } + dict->Set("states", std::move(states)); + + AtkRelationSet* relation_set = atk_object_ref_relation_set(atk_object); + auto relations = std::make_unique<base::ListValue>(); + for (int i = ATK_RELATION_NULL; i < ATK_RELATION_LAST_DEFINED; i++) { + AtkRelationType relation_type = static_cast<AtkRelationType>(i); + if (atk_relation_set_contains(relation_set, relation_type)) + relations->AppendString(atk_relation_type_get_name(relation_type)); + } + dict->Set("relations", std::move(relations)); + + AtkAttributeSet* attributes = atk_object_get_attributes(atk_object); + for (AtkAttributeSet* attr = attributes; attr; attr = attr->next) { + AtkAttribute* attribute = static_cast<AtkAttribute*>(attr->data); + dict->SetString(attribute->name, attribute->value); + } + atk_attribute_set_free(attributes); + + // Properties obtained via AtkValue. + auto value_properties = std::make_unique<base::ListValue>(); + if (ATK_IS_VALUE(atk_object)) { + AtkValue* value = ATK_VALUE(atk_object); + GValue current = G_VALUE_INIT; + g_value_init(¤t, G_TYPE_FLOAT); + atk_value_get_current_value(value, ¤t); + value_properties->AppendString( + base::StringPrintf("current=%f", g_value_get_float(¤t))); + + GValue minimum = G_VALUE_INIT; + g_value_init(&minimum, G_TYPE_FLOAT); + atk_value_get_minimum_value(value, &minimum); + value_properties->AppendString( + base::StringPrintf("minimum=%f", g_value_get_float(&minimum))); + + GValue maximum = G_VALUE_INIT; + g_value_init(&maximum, G_TYPE_FLOAT); + atk_value_get_maximum_value(value, &maximum); + value_properties->AppendString( + base::StringPrintf("maximum=%f", g_value_get_float(&maximum))); + } + dict->Set("value", std::move(value_properties)); + + // Properties obtained via AtkTable. + auto table_properties = std::make_unique<base::ListValue>(); + if (ATK_IS_TABLE(atk_object)) { + AtkTable* table = ATK_TABLE(atk_object); + + // Column details. + int n_cols = atk_table_get_n_columns(table); + table_properties->AppendString(base::StringPrintf("cols=%i", n_cols)); + + std::vector<std::string> col_headers; + for (int i = 0; i < n_cols; i++) { + std::string header = atk_table_get_column_description(table, i); + if (!header.empty()) + col_headers.push_back(base::StringPrintf("'%s'", header.c_str())); + } + + if (!col_headers.size()) + col_headers.push_back("NONE"); + + table_properties->AppendString(base::StringPrintf( + "headers=(%s);", base::JoinString(col_headers, ", ").c_str())); + + // Row details. + int n_rows = atk_table_get_n_rows(table); + table_properties->AppendString(base::StringPrintf("rows=%i", n_rows)); + + std::vector<std::string> row_headers; + for (int i = 0; i < n_rows; i++) { + std::string header = atk_table_get_row_description(table, i); + if (!header.empty()) + row_headers.push_back(base::StringPrintf("'%s'", header.c_str())); + } + + if (!row_headers.size()) + row_headers.push_back("NONE"); + + table_properties->AppendString(base::StringPrintf( + "headers=(%s);", base::JoinString(row_headers, ", ").c_str())); + + // Caption details. + AtkObject* caption = atk_table_get_caption(table); + table_properties->AppendString( + base::StringPrintf("caption=%s;", caption ? "true" : "false")); + + // Summarize information about the cells from the table's perspective here. + std::vector<std::string> span_info; + for (int r = 0; r < n_rows; r++) { + for (int c = 0; c < n_cols; c++) { + int row_span = atk_table_get_row_extent_at(table, r, c); + int col_span = atk_table_get_column_extent_at(table, r, c); + if (row_span != 1 || col_span != 1) { + span_info.push_back(base::StringPrintf("cell at %i,%i: %ix%i", r, c, + row_span, col_span)); + } + } + } + if (!span_info.size()) + span_info.push_back("all: 1x1"); + + table_properties->AppendString(base::StringPrintf( + "spans=(%s)", base::JoinString(span_info, ", ").c_str())); + } + + dict->Set("table", std::move(table_properties)); + + // Properties obtained via AtkTableCell, if possible. If we do not have at + // least ATK 2.12, use the same logic in our AtkTableCell implementation so + // that tests can still be run. + auto cell_properties = std::make_unique<base::ListValue>(); + if (role == ATK_ROLE_TABLE_CELL || role == ATK_ROLE_COLUMN_HEADER || + role == ATK_ROLE_ROW_HEADER) { + int row, col, row_span, col_span; + int n_row_headers = 0, n_column_headers = 0; + auto cell_interface = ui::AtkTableCellInterface::Get(); + if (cell_interface.has_value()) { + AtkTableCell* cell = G_TYPE_CHECK_INSTANCE_CAST( + (atk_object), cell_interface->GetType(), AtkTableCell); + GPtrArray* column_headers = cell_interface->GetColumnHeaderCells(cell); + GPtrArray* row_headers = cell_interface->GetRowHeaderCells(cell); + n_column_headers = column_headers->len; + n_row_headers = row_headers->len; + g_ptr_array_unref(column_headers); + g_ptr_array_unref(row_headers); + cell_interface->GetRowColumnSpan(cell, &row, &col, &row_span, &col_span); + } else { + row = ax_platform_node->GetTableRow(); + col = ax_platform_node->GetTableColumn(); + row_span = ax_platform_node->GetTableRowSpan(); + col_span = ax_platform_node->GetTableColumnSpan(); + if (role == ATK_ROLE_TABLE_CELL) { + auto* delegate = ax_platform_node->GetTable()->GetDelegate(); + n_column_headers = delegate->GetColHeaderNodeIds(col).size(); + n_row_headers = delegate->GetRowHeaderNodeIds(row).size(); + } + } + cell_properties->AppendString( + base::StringPrintf("(row=%i, col=%i, row_span=%i, col_span=%i", row, + col, row_span, col_span)); + cell_properties->AppendString( + base::StringPrintf("n_row_headers=%i, n_col_headers=%i)", n_row_headers, + n_column_headers)); + } + dict->Set("cell", std::move(cell_properties)); } void AccessibilityTreeFormatterAuraLinux::AddProperties(
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc index 3901695..84115f3 100644 --- a/content/browser/child_process_security_policy_impl.cc +++ b/content/browser/child_process_security_policy_impl.cc
@@ -434,11 +434,13 @@ const url::Origin& origin, BrowsingInstanceId min_browsing_instance_id, BrowserContext* browser_context, - ResourceContext* resource_context) + ResourceContext* resource_context, + bool isolate_all_subdomains) : origin_(origin), min_browsing_instance_id_(min_browsing_instance_id), browser_context_(browser_context), - resource_context_(resource_context) { + resource_context_(resource_context), + isolate_all_subdomains_(isolate_all_subdomains) { // If there is a BrowserContext, there must also be a ResourceContext // associated with this entry. DCHECK_EQ(!browser_context, !resource_context); @@ -1388,37 +1390,36 @@ } void ChildProcessSecurityPolicyImpl::AddIsolatedOrigins( - std::vector<url::Origin> origins_to_add, + const std::vector<url::Origin>& origins_to_add, + BrowserContext* browser_context) { + std::vector<IsolatedOriginPattern> patterns; + patterns.reserve(origins_to_add.size()); + std::transform(origins_to_add.cbegin(), origins_to_add.cend(), + std::back_inserter(patterns), + [](const url::Origin& o) -> IsolatedOriginPattern { + return IsolatedOriginPattern(o); + }); + AddIsolatedOrigins(patterns, browser_context); +} + +void ChildProcessSecurityPolicyImpl::AddIsolatedOrigins( + const std::vector<IsolatedOriginPattern>& patterns, BrowserContext* browser_context) { // This can only be called from the UI thread, as it reads state that's only // available (and is only safe to be retrieved) on the UI thread, such as // BrowsingInstance IDs. DCHECK_CURRENTLY_ON(BrowserThread::UI); - // Filter out origins that cannot be used as an isolated origin. - base::EraseIf(origins_to_add, [](const url::Origin& origin) { - if (IsolatedOriginUtil::IsValidIsolatedOrigin(origin)) - return false; // Don't remove. - - LOG(ERROR) << "Invalid isolated origin: " << origin; - return true; // Remove. - }); - - // Ports are ignored when matching isolated origins (see also - // https://crbug.com/914511). - for (url::Origin& origin : origins_to_add) { - const std::string& scheme = origin.scheme(); - int default_port = - url::DefaultPortForScheme(scheme.data(), scheme.length()); - if (origin.port() != default_port) { - LOG(ERROR) << "Ignoring port number in isolated origin: " << origin; - origin = url::Origin::Create(GURL( - origin.scheme() + url::kStandardSchemeSeparator + origin.host())); - } - } - base::AutoLock isolated_origins_lock(isolated_origins_lock_); - for (url::Origin& origin : origins_to_add) { + + for (const IsolatedOriginPattern& pattern : patterns) { + if (!pattern.is_valid()) { + LOG(ERROR) << "Invalid isolated origin: " << pattern.pattern(); + continue; + } + + url::Origin origin_to_add = pattern.origin(); + // GetSiteForOrigin() is used to look up the site URL of |origin| to speed // up the isolated origin lookup. This only performs a straightforward // translation of an origin to eTLD+1; it does *not* take into account @@ -1426,7 +1427,7 @@ // here, but *is* typically needed for making process model decisions. Be // very careful about using GetSiteForOrigin() elsewhere, and consider // whether you should be using GetSiteForURL() instead. - GURL key(SiteInstanceImpl::GetSiteForOrigin(origin)); + GURL key(SiteInstanceImpl::GetSiteForOrigin(origin_to_add)); // Isolated origins should apply only to future BrowsingInstances and // processes. Save the first BrowsingInstance ID to which they should @@ -1438,7 +1439,7 @@ // need to be added again. bool should_add = true; for (const auto& entry : isolated_origins_[key]) { - if (entry.origin() != origin) + if (entry.origin() != origin_to_add) continue; // If the added origin already exists for the same BrowserContext, don't @@ -1463,9 +1464,10 @@ if (should_add) { ResourceContext* resource_context = browser_context ? browser_context->GetResourceContext() : nullptr; - IsolatedOriginEntry entry(std::move(origin), min_browsing_instance_id, - browser_context, resource_context); - isolated_origins_[key].insert(std::move(entry)); + IsolatedOriginEntry entry( + std::move(origin_to_add), min_browsing_instance_id, browser_context, + resource_context, pattern.isolate_all_subdomains()); + isolated_origins_[key].emplace_back(std::move(entry)); } } } @@ -1557,7 +1559,7 @@ } // Looks for all isolated origins that were already isolated at the time - // |isolation_context| was created. If multiple isolated origins are + // |isolation_context| was created. If multiple isolated origins are // registered with a common domain suffix, return the most specific one. For // example, if foo.isolated.com and isolated.com are both isolated origins, // bar.foo.isolated.com should return foo.isolated.com. @@ -1576,6 +1578,16 @@ if (matches_browsing_instance_id && IsolatedOriginUtil::DoesOriginMatchIsolatedOrigin( origin, isolated_origin_entry.origin())) { + // If a match has been found that requires all subdomains to be + // isolated then return immediately. |origin| is returned to ensure + // proper process isolation, e.g. https://a.b.c.isolated.com matches + // an IsolatedOriginEntry constructed from http://**.isolated.com, so + // https://a.b.c.isolated.com must be returned. + if (isolated_origin_entry.isolate_all_subdomains()) { + *result = origin; + return true; + } + if (!found || result->host().length() < isolated_origin_entry.origin().host().length()) { *result = isolated_origin_entry.origin();
diff --git a/content/browser/child_process_security_policy_impl.h b/content/browser/child_process_security_policy_impl.h index 31f391c..552d3fa 100644 --- a/content/browser/child_process_security_policy_impl.h +++ b/content/browser/child_process_security_policy_impl.h
@@ -20,6 +20,7 @@ #include "base/memory/singleton.h" #include "base/synchronization/lock.h" #include "base/thread_annotations.h" +#include "content/browser/isolated_origin_util.h" #include "content/browser/isolation_context.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/common/resource_type.h" @@ -39,7 +40,7 @@ namespace storage { class FileSystemContext; class FileSystemURL; -} +} // namespace storage namespace content { @@ -100,7 +101,9 @@ bool HasWebUIBindings(int child_id) override; void GrantSendMidiSysExMessage(int child_id) override; bool CanAccessDataForOrigin(int child_id, const GURL& url) override; - void AddIsolatedOrigins(std::vector<url::Origin> origins, + void AddIsolatedOrigins(const std::vector<url::Origin>& origins, + BrowserContext* browser_context = nullptr) override; + void AddIsolatedOrigins(const std::vector<IsolatedOriginPattern>& patterns, BrowserContext* browser_context = nullptr) override; bool IsGloballyIsolatedOriginForTesting(const url::Origin& origin) override; @@ -335,6 +338,12 @@ IsolatedOriginsForSpecificBrowserContexts); FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, IsolatedOriginsRemovedWhenBrowserContextDestroyed); + FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, + IsolateAllSuborigins); + FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, + WildcardAndNonWildcardOrigins); + FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, + WildcardAndNonWildcardEmbedded); class SecurityState; @@ -350,7 +359,9 @@ IsolatedOriginEntry(const url::Origin& origin, BrowsingInstanceId min_browsing_instance_id, BrowserContext* browser_context, - ResourceContext* resource_context); + ResourceContext* resource_context, + bool isolate_all_subdomains); + // Copyable and movable. IsolatedOriginEntry(const IsolatedOriginEntry& other); IsolatedOriginEntry& operator=(const IsolatedOriginEntry& other); @@ -361,16 +372,18 @@ // Allow this class to be used as a key in STL. bool operator<(const IsolatedOriginEntry& other) const { return std::tie(origin_, min_browsing_instance_id_, browser_context_, - resource_context_) < + resource_context_, isolate_all_subdomains_) < std::tie(other.origin_, other.min_browsing_instance_id_, - other.browser_context_, other.resource_context_); + other.browser_context_, other.resource_context_, + other.isolate_all_subdomains_); } bool operator==(const IsolatedOriginEntry& other) const { return origin_ == other.origin_ && min_browsing_instance_id_ == other.min_browsing_instance_id_ && browser_context_ == other.browser_context_ && - resource_context_ == other.resource_context_; + resource_context_ == other.resource_context_ && + isolate_all_subdomains_ == other.isolate_all_subdomains_; } // True if this isolated origin applies globally to all profiles. @@ -390,6 +403,8 @@ const BrowserContext* browser_context() const { return browser_context_; } + bool isolate_all_subdomains() const { return isolate_all_subdomains_; } + private: url::Origin origin_; BrowsingInstanceId min_browsing_instance_id_; @@ -401,6 +416,14 @@ BrowserContext* browser_context_; ResourceContext* resource_context_; + // True if origins at this or lower level should be treated as distinct + // isolated origins, effectively isolating all domains below a given domain, + // e.g. if the origin is https://foo.com and isolate_all_subdomains_ is + // true, then https://bar.foo.com, https://qux.bar.foo.com and all + // subdomains of the form https://<<any pattern here>>.foo.com are + // considered isolated origins. + bool isolate_all_subdomains_; + // TODO(alexmos): Track the source of each isolated origin entry, e.g., to // distinguish those that should be displayed to the user from those that // should not. See https://crbug.com/920911. @@ -426,10 +449,9 @@ // Grants access permission to the given isolated file system // identified by |filesystem_id|. See comments for // ChildProcessSecurityPolicy::GrantReadFileSystem() for more details. - void GrantPermissionsForFileSystem( - int child_id, - const std::string& filesystem_id, - int permission); + void GrantPermissionsForFileSystem(int child_id, + const std::string& filesystem_id, + int permission); // Determines if certain permissions were granted for a file. |permissions| // is an internally defined bit-set. @@ -446,10 +468,9 @@ // Determines if certain permissions were granted for a file system. // |permissions| is an internally defined bit-set. - bool HasPermissionsForFileSystem( - int child_id, - const std::string& filesystem_id, - int permission); + bool HasPermissionsForFileSystem(int child_id, + const std::string& filesystem_id, + int permission); // Gets the SecurityState object associated with |child_id|. // Note: Returned object is only valid for the duration the caller holds @@ -529,7 +550,7 @@ // represents https://test.foo.com being isolated in profile1 starting // with BrowsingInstance ID 4, and also in profile2 starting with // BrowsingInstance ID 7. - base::flat_map<GURL, base::flat_set<IsolatedOriginEntry>> isolated_origins_ + base::flat_map<GURL, std::vector<IsolatedOriginEntry>> isolated_origins_ GUARDED_BY(isolated_origins_lock_); DISALLOW_COPY_AND_ASSIGN(ChildProcessSecurityPolicyImpl);
diff --git a/content/browser/child_process_security_policy_unittest.cc b/content/browser/child_process_security_policy_unittest.cc index d62db81..92a30f6 100644 --- a/content/browser/child_process_security_policy_unittest.cc +++ b/content/browser/child_process_security_policy_unittest.cc
@@ -13,6 +13,7 @@ #include "base/test/bind_test_util.h" #include "base/test/mock_log.h" #include "content/browser/child_process_security_policy_impl.h" +#include "content/browser/isolated_origin_util.h" #include "content/browser/site_instance_impl.h" #include "content/public/common/bindings_policy.h" #include "content/public/common/url_constants.h" @@ -99,20 +100,23 @@ // where site_url is created from |origin| and // entry contains |origin| and |min_browsing_instance_id|. auto GetIsolatedOriginEntry(int min_browsing_instance_id, - const url::Origin& origin) { - return std::pair<GURL, base::flat_set<IsolatedOriginEntry>>( + const url::Origin& origin, + bool isolate_all_subdomains = false) { + return std::pair<GURL, std::vector<IsolatedOriginEntry>>( SiteInstanceImpl::GetSiteForOrigin(origin), {IsolatedOriginEntry( origin, BrowsingInstanceId::FromUnsafeValue(min_browsing_instance_id), - nullptr, nullptr)}); + nullptr, nullptr, isolate_all_subdomains)}); } // Converts |origin| -> (site_url, {entry}) // where site_url is created from |origin| and // entry contains |origin| and the latest BrowsingInstance ID. - auto GetIsolatedOriginEntry(const url::Origin& origin) { + auto GetIsolatedOriginEntry(const url::Origin& origin, + bool isolate_all_subdomains = false) { return GetIsolatedOriginEntry( - SiteInstanceImpl::NextBrowsingInstanceId().GetUnsafeValue(), origin); + SiteInstanceImpl::NextBrowsingInstanceId().GetUnsafeValue(), origin, + isolate_all_subdomains); } // Converts |origin1|, |origin2| -> (site_url, {entry1, entry2}) // where |site_url| is created from |origin1|, but is assumed to be the @@ -121,17 +125,19 @@ // entry1 contains |origin1| and the latest BrowsingInstance ID, // entry2 contains |origin2| and the latest BrowsingInstance ID. auto GetIsolatedOriginEntry(const url::Origin& origin1, - const url::Origin& origin2) { + const url::Origin& origin2, + bool origin1_isolate_all_subdomains = false, + bool origin2_isolate_all_subdomains = false) { EXPECT_EQ(SiteInstanceImpl::GetSiteForOrigin(origin1), SiteInstanceImpl::GetSiteForOrigin(origin2)); - return std::pair<GURL, base::flat_set<IsolatedOriginEntry>>( + return std::pair<GURL, std::vector<IsolatedOriginEntry>>( SiteInstanceImpl::GetSiteForOrigin(origin1), {IsolatedOriginEntry(origin1, SiteInstanceImpl::NextBrowsingInstanceId(), - nullptr, nullptr), - IsolatedOriginEntry(origin2, - SiteInstanceImpl::NextBrowsingInstanceId(), - nullptr, nullptr)}); + nullptr, nullptr, origin1_isolate_all_subdomains), + IsolatedOriginEntry( + origin2, SiteInstanceImpl::NextBrowsingInstanceId(), nullptr, + nullptr, origin2_isolate_all_subdomains)}); } bool IsIsolatedOrigin(BrowserContext* context, @@ -160,6 +166,15 @@ }); } + void CheckGetSiteForURL(BrowserContext* context, + std::map<GURL, GURL> to_test) { + for (const auto& entry : to_test) { + EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(IsolationContext(context), + entry.first), + entry.second); + } + } + protected: void RegisterTestScheme(const std::string& scheme) { test_browser_client_.AddScheme(scheme); @@ -1396,6 +1411,274 @@ p->RemoveIsolatedOriginForTesting(bar); p->RemoveIsolatedOriginForTesting(baz); p->RemoveIsolatedOriginForTesting(baz_http); + + // We should have removed all isolated origins at this point. + LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_, + testing::IsEmpty()); +} + +TEST_F(ChildProcessSecurityPolicyTest, IsolateAllSuborigins) { + url::Origin qux = url::Origin::Create(GURL("https://qux.com/")); + IsolatedOriginPattern etld1_wild("https://**.foo.com"); + IsolatedOriginPattern etld2_wild("https://**.bar.foo.com"); + url::Origin etld1 = url::Origin::Create(GURL("https://foo.com")); + url::Origin etld2 = url::Origin::Create(GURL("https://bar.foo.com")); + + ChildProcessSecurityPolicyImpl* p = + ChildProcessSecurityPolicyImpl::GetInstance(); + + // Check we can add a single wildcard origin. + p->AddIsolatedOrigins({etld1_wild}); + + LOCKED_EXPECT_THAT( + p->isolated_origins_lock_, p->isolated_origins_, + testing::UnorderedElementsAre(GetIsolatedOriginEntry(etld1, true))); + + // Add a conventional origin and check they can live side by side. + p->AddIsolatedOrigins({qux}); + LOCKED_EXPECT_THAT( + p->isolated_origins_lock_, p->isolated_origins_, + testing::UnorderedElementsAre(GetIsolatedOriginEntry(etld1, true), + GetIsolatedOriginEntry(qux, false))); + + // Check that a wildcard domain within another wildcard domain can be added. + p->AddIsolatedOrigins({etld2_wild}); + LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_, + testing::UnorderedElementsAre( + GetIsolatedOriginEntry(etld1, etld2, true, true), + GetIsolatedOriginEntry(qux, false))); + + // Check that removing a single wildcard domain, that contains another + // wildcard domain, doesn't affect the isolating behavior of the original + // wildcard domain. + p->RemoveIsolatedOriginForTesting(etld1); + LOCKED_EXPECT_THAT( + p->isolated_origins_lock_, p->isolated_origins_, + testing::UnorderedElementsAre(GetIsolatedOriginEntry(etld2, true), + GetIsolatedOriginEntry(qux, false))); + + // Removing remaining domains. + p->RemoveIsolatedOriginForTesting(qux); + p->RemoveIsolatedOriginForTesting(etld2); + + LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_, + testing::IsEmpty()); +} + +// Verify that the isolation behavior for wildcard and non-wildcard origins, +// singly or in concert, behaves correctly via calls to GetSiteForURL(). +TEST_F(ChildProcessSecurityPolicyTest, WildcardAndNonWildcardOrigins) { + ChildProcessSecurityPolicyImpl* p = + ChildProcessSecurityPolicyImpl::GetInstance(); + + // There should be no isolated origins before this test starts. + LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_, + testing::IsEmpty()); + + // Construct a simple case, a single isolated origin. + // IsolatedOriginPattern isolated("https://isolated.com"); + IsolatedOriginPattern inner_isolated("https://inner.isolated.com"); + IsolatedOriginPattern wildcard("https://**.wildcard.com"); + IsolatedOriginPattern inner_wildcard("https://**.inner.wildcard.com"); + + GURL isolated_url("https://isolated.com"); + GURL inner_isolated_url("https://inner.isolated.com"); + GURL host_inner_isolated_url("https://host.inner.isolated.com"); + GURL wildcard_url("https://wildcard.com"); + GURL inner_wildcard_url("https://inner.wildcard.com"); + GURL host_inner_wildcard_url("https://host.inner.wildcard.com"); + GURL unrelated_url("https://unrelated.com"); + + // Verify the isolation behavior of the test patterns before isolating any + // domains. + std::map<GURL, GURL> origins_site_test_map{ + {isolated_url, isolated_url}, + {inner_isolated_url, isolated_url}, + {host_inner_isolated_url, isolated_url}, + {wildcard_url, wildcard_url}, + {inner_wildcard_url, wildcard_url}, + {host_inner_wildcard_url, wildcard_url}, + {unrelated_url, unrelated_url}, + }; + CheckGetSiteForURL(browser_context(), origins_site_test_map); + + // Add |wildcard|, a wildcard origin from a different domain, then verify that + // the existing behavior of |isolated_url| and |inner_isolated_url| remains + // unaffected, while all subdomains of wildcard.com are returned as unique + // sites. + p->AddIsolatedOrigins({wildcard}); + origins_site_test_map[inner_wildcard_url] = inner_wildcard_url; + origins_site_test_map[host_inner_wildcard_url] = host_inner_wildcard_url; + CheckGetSiteForURL(browser_context(), origins_site_test_map); + + // Add |inner_isolated|, then verify that querying for |inner_isolated_url| + // returns |inner_isolated_url| while leaving the wildcard origins unaffected. + p->AddIsolatedOrigins({inner_isolated}); + origins_site_test_map[inner_isolated_url] = inner_isolated_url; + origins_site_test_map[host_inner_isolated_url] = inner_isolated_url; + CheckGetSiteForURL(browser_context(), origins_site_test_map); + + // Add |inner_wildcard|. This should not change the behavior of the test + // above as all subdomains of |inner_wildcard| are contained within + // |wildcard|. + p->AddIsolatedOrigins({inner_wildcard}); + CheckGetSiteForURL(browser_context(), origins_site_test_map); + + p->RemoveIsolatedOriginForTesting(wildcard.origin()); + p->RemoveIsolatedOriginForTesting(inner_isolated.origin()); + p->RemoveIsolatedOriginForTesting(inner_wildcard.origin()); + + LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_, + testing::IsEmpty()); +} + +TEST_F(ChildProcessSecurityPolicyTest, WildcardAndNonWildcardEmbedded) { + ChildProcessSecurityPolicyImpl* p = + ChildProcessSecurityPolicyImpl::GetInstance(); + + // There should be no isolated origins before this test starts. + LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_, + testing::IsEmpty()); + + { + // Test the behavior of a wildcard origin contained within a single + // isolated origin. Removing the isolated origin should have no effect on + // the wildcard origin. + IsolatedOriginPattern isolated("https://isolated.com"); + IsolatedOriginPattern wildcard_isolated("https://**.wildcard.isolated.com"); + + GURL isolated_url("https://isolated.com"); + GURL a_isolated_url("https://a.isolated.com"); + GURL wildcard_isolated_url("https://wildcard.isolated.com"); + GURL a_wildcard_isolated_url("https://a.wildcard.isolated.com"); + + p->AddIsolatedOrigins({isolated, wildcard_isolated}); + std::map<GURL, GURL> origin_site_map{ + {isolated_url, isolated_url}, + {a_isolated_url, isolated_url}, + {wildcard_isolated_url, wildcard_isolated_url}, + {a_wildcard_isolated_url, a_wildcard_isolated_url}, + }; + + CheckGetSiteForURL(browser_context(), origin_site_map); + + p->RemoveIsolatedOriginForTesting(isolated.origin()); + p->RemoveIsolatedOriginForTesting(wildcard_isolated.origin()); + } + + // No isolated origins should persist between tests. + LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_, + testing::IsEmpty()); + + { + // A single isolated origin is nested within a wildcard origin. In this + // scenario the wildcard origin supersedes isolated origins. + IsolatedOriginPattern wildcard("https://**.wildcard.com"); + IsolatedOriginPattern isolated_wildcard("https://isolated.wildcard.com"); + + GURL wildcard_url("https://wildcard.com"); + GURL a_wildcard_url("https://a.wildcard.com"); + GURL isolated_wildcard_url("https://isolated.wildcard.com"); + GURL a_isolated_wildcard_url("https://a.isolated.wildcard.com"); + + p->AddIsolatedOrigins({wildcard, isolated_wildcard}); + std::map<GURL, GURL> origin_site_map{ + {wildcard_url, wildcard_url}, + {a_wildcard_url, a_wildcard_url}, + {isolated_wildcard_url, isolated_wildcard_url}, + {a_isolated_wildcard_url, a_isolated_wildcard_url}, + }; + + CheckGetSiteForURL(browser_context(), origin_site_map); + + p->RemoveIsolatedOriginForTesting(wildcard.origin()); + p->RemoveIsolatedOriginForTesting(isolated_wildcard.origin()); + } + + LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_, + testing::IsEmpty()); + + { + // Nest wildcard isolated origins within each other. Verify that removing + // the outer wildcard origin doesn't affect the inner one. + IsolatedOriginPattern outer("https://**.outer.com"); + IsolatedOriginPattern inner("https://**.inner.outer.com"); + + GURL outer_url("https://outer.com"); + GURL a_outer_url("https://a.outer.com"); + GURL inner_url("https://inner.outer.com"); + GURL a_inner_url("https://a.inner.outer.com"); + + p->AddIsolatedOrigins({inner, outer}); + + std::map<GURL, GURL> origin_site_map{ + {outer_url, outer_url}, + {a_outer_url, a_outer_url}, + {inner_url, inner_url}, + {a_inner_url, a_inner_url}, + }; + + CheckGetSiteForURL(browser_context(), origin_site_map); + p->RemoveIsolatedOriginForTesting(outer.origin()); + p->RemoveIsolatedOriginForTesting(inner.origin()); + } + + LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_, + testing::IsEmpty()); + + // Verify that adding a wildcard domain then a then a conventional domain + // doesn't affect the isolating behavior of the wildcard, i.e. whichever + // isolated domain is added entered 'wins'. + { + IsolatedOriginPattern wild("https://**.bar.foo.com"); + IsolatedOriginPattern single("https://bar.foo.com"); + + GURL host_url("https://host.bar.foo.com"); + + p->AddIsolatedOrigins({wild}); + std::map<GURL, GURL> origin_site_map{ + {host_url, host_url}, + }; + + CheckGetSiteForURL(browser_context(), origin_site_map); + + p->AddIsolatedOrigins({single}); + + CheckGetSiteForURL(browser_context(), origin_site_map); + + p->RemoveIsolatedOriginForTesting(wild.origin()); + p->RemoveIsolatedOriginForTesting(single.origin()); + } + + LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_, + testing::IsEmpty()); + + // Verify the first domain added remains dominant in the case of differing + // wildcard and non-wildcard statuses. + { + IsolatedOriginPattern wild("https://**.bar.foo.com"); + IsolatedOriginPattern single("https://bar.foo.com"); + + GURL host_url("https://host.bar.foo.com"); + GURL domain_url("https://bar.foo.com"); + + p->AddIsolatedOrigins({single}); + std::map<GURL, GURL> origin_site_map{ + {host_url, domain_url}, + }; + + CheckGetSiteForURL(browser_context(), origin_site_map); + + p->AddIsolatedOrigins({wild}); + + CheckGetSiteForURL(browser_context(), origin_site_map); + + p->RemoveIsolatedOriginForTesting(wild.origin()); + p->RemoveIsolatedOriginForTesting(single.origin()); + } + + LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_, + testing::IsEmpty()); } // Verifies that isolated origins only apply to future BrowsingInstances. @@ -1811,4 +2094,81 @@ EXPECT_FALSE(io_after_remove_complete); } +TEST_F(ChildProcessSecurityPolicyTest, IsolatedOriginPattern) { + const base::StringPiece etld1_wild("https://**.foo.com"); + url::Origin etld1_wild_origin = url::Origin::Create(GURL("https://foo.com")); + IsolatedOriginPattern p(etld1_wild); + EXPECT_TRUE(p.isolate_all_subdomains()); + EXPECT_TRUE(p.is_valid()); + EXPECT_EQ(p.origin(), etld1_wild_origin); + + const base::StringPiece etld2_wild("https://**.bar.foo.com"); + url::Origin etld2_wild_origin = + url::Origin::Create(GURL("https://bar.foo.com")); + bool result = p.Parse(etld2_wild); + EXPECT_TRUE(result); + EXPECT_TRUE(p.isolate_all_subdomains()); + EXPECT_TRUE(p.is_valid()); + EXPECT_EQ(p.origin(), etld2_wild_origin); + EXPECT_FALSE(p.origin().opaque()); + + const base::StringPiece etld1("https://baz.com"); + url::Origin etld1_origin = url::Origin::Create(GURL("https://baz.com")); + result = p.Parse(etld1); + EXPECT_TRUE(result); + EXPECT_FALSE(p.isolate_all_subdomains()); + EXPECT_TRUE(p.is_valid()); + EXPECT_EQ(p.origin(), etld1_origin); + EXPECT_FALSE(p.origin().opaque()); + + const base::StringPiece bad_scheme("ftp://foo.com"); + result = p.Parse(bad_scheme); + EXPECT_FALSE(result); + EXPECT_FALSE(p.isolate_all_subdomains()); + EXPECT_FALSE(p.is_valid()); + EXPECT_TRUE(p.origin().opaque()); + + const base::StringPiece no_scheme_sep("httpsfoo.com"); + result = p.Parse(no_scheme_sep); + EXPECT_FALSE(result); + EXPECT_FALSE(p.isolate_all_subdomains()); + EXPECT_FALSE(p.is_valid()); + EXPECT_TRUE(p.origin().opaque()); + + const base::StringPiece bad_registry("https://co.uk"); + result = p.Parse(bad_registry); + EXPECT_FALSE(result); + EXPECT_FALSE(p.isolate_all_subdomains()); + EXPECT_FALSE(p.is_valid()); + EXPECT_TRUE(p.origin().opaque()); + + const base::StringPiece trailing_dot("https://bar.com."); + result = p.Parse(trailing_dot); + EXPECT_FALSE(result); + EXPECT_FALSE(p.isolate_all_subdomains()); + EXPECT_FALSE(p.is_valid()); + EXPECT_TRUE(p.origin().opaque()); + + const base::StringPiece ip_addr("https://10.20.30.40"); + url::Origin ip_origin = url::Origin::Create(GURL("https://10.20.30.40")); + result = p.Parse(ip_addr); + EXPECT_TRUE(result); + EXPECT_FALSE(p.isolate_all_subdomains()); + EXPECT_FALSE(p.origin().opaque()); + EXPECT_TRUE(p.is_valid()); + EXPECT_EQ(p.origin(), ip_origin); + + const base::StringPiece wild_ip_addr("https://**.10.20.30.40"); + result = p.Parse(wild_ip_addr); + EXPECT_FALSE(result); + EXPECT_FALSE(p.isolate_all_subdomains()); + EXPECT_FALSE(p.is_valid()); + + const url::Origin bad_origin; + IsolatedOriginPattern bad_pattern(bad_origin); + EXPECT_FALSE(bad_pattern.isolate_all_subdomains()); + EXPECT_TRUE(bad_pattern.origin().opaque()); + EXPECT_FALSE(p.is_valid()); +} + } // namespace content
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index d30acb17..5426a98c 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -6340,33 +6340,6 @@ base::debug::CrashKeySize::Size256), GetSiteInstance()->lock_url().spec()); - base::debug::SetCrashKeyString( - base::debug::AllocateCrashKeyString("original_url_origin", - base::debug::CrashKeySize::Size256), - GetSiteInstance()->original_url().GetOrigin().spec()); - - base::debug::SetCrashKeyString( - base::debug::AllocateCrashKeyString("is_transfer_needed", - base::debug::CrashKeySize::Size32), - bool_to_crash_key(frame_tree_node_->render_manager() - ->IsRendererTransferNeededForNavigation( - this, validated_params->url))); - - base::debug::SetCrashKeyString( - base::debug::AllocateCrashKeyString("is_mhtml_document", - base::debug::CrashKeySize::Size32), - bool_to_crash_key(is_mhtml_document())); - - base::debug::SetCrashKeyString( - base::debug::AllocateCrashKeyString("last_committed_url_origin", - base::debug::CrashKeySize::Size256), - GetLastCommittedURL().GetOrigin().spec()); - - base::debug::SetCrashKeyString( - base::debug::AllocateCrashKeyString("last_successful_url_origin", - base::debug::CrashKeySize::Size256), - last_successful_url().GetOrigin().spec()); - if (navigation_request && navigation_request->navigation_handle()) { NavigationHandleImpl* handle = navigation_request->navigation_handle(); base::debug::SetCrashKeyString( @@ -6391,11 +6364,6 @@ base::debug::SetCrashKeyString( base::debug::AllocateCrashKeyString( - "from_begin_navigation", base::debug::CrashKeySize::Size32), - bool_to_crash_key(navigation_request->from_begin_navigation())); - - base::debug::SetCrashKeyString( - base::debug::AllocateCrashKeyString( "net_error_code", base::debug::CrashKeySize::Size32), base::NumberToString(navigation_request->net_error())); @@ -6410,17 +6378,6 @@ base::debug::AllocateCrashKeyString( "starting_site_instance", base::debug::CrashKeySize::Size64), handle->GetStartingSiteInstance()->GetSiteURL().spec()); - - // Recompute the target SiteInstance to see if it matches the current one - // at commit time. - scoped_refptr<SiteInstance> dest_instance = - frame_tree_node_->render_manager() - ->GetSiteInstanceForNavigationRequest(*navigation_request); - base::debug::SetCrashKeyString( - base::debug::AllocateCrashKeyString( - "does_recomputed_site_instance_match_current", - base::debug::CrashKeySize::Size32), - bool_to_crash_key(dest_instance == GetSiteInstance())); } // Kills the process.
diff --git a/content/browser/isolated_origin_util.cc b/content/browser/isolated_origin_util.cc index 5c36547..7c2bfd5 100644 --- a/content/browser/isolated_origin_util.cc +++ b/content/browser/isolated_origin_util.cc
@@ -2,14 +2,89 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <string> + #include "content/browser/isolated_origin_util.h" #include "base/strings/string_util.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "url/gurl.h" +const char* kAllSubdomainsWildcard = "**."; + namespace content { +IsolatedOriginPattern::IsolatedOriginPattern(base::StringPiece pattern) + : isolate_all_subdomains_(false), is_valid_(false) { + Parse(pattern); +} + +IsolatedOriginPattern::IsolatedOriginPattern(const url::Origin& origin) + : IsolatedOriginPattern(origin.GetURL().spec()) {} + +IsolatedOriginPattern::~IsolatedOriginPattern() = default; +IsolatedOriginPattern::IsolatedOriginPattern( + const IsolatedOriginPattern& other) = default; +IsolatedOriginPattern& IsolatedOriginPattern::operator=( + const IsolatedOriginPattern& other) = default; +IsolatedOriginPattern::IsolatedOriginPattern(IsolatedOriginPattern&& other) = + default; +IsolatedOriginPattern& IsolatedOriginPattern::operator=( + IsolatedOriginPattern&& other) = default; + +bool IsolatedOriginPattern::Parse(const base::StringPiece& unparsed_pattern) { + pattern_ = unparsed_pattern.as_string(); + origin_ = url::Origin(); + isolate_all_subdomains_ = false; + is_valid_ = false; + + size_t host_begin = unparsed_pattern.find(url::kStandardSchemeSeparator); + if (host_begin == base::StringPiece::npos || host_begin == 0) + return false; + + // Skip over the scheme separator. + host_begin += strlen(url::kStandardSchemeSeparator); + if (host_begin >= unparsed_pattern.size()) + return false; + + base::StringPiece scheme_part = unparsed_pattern.substr(0, host_begin); + base::StringPiece host_part = unparsed_pattern.substr(host_begin); + + // Empty schemes or hosts are invalid for isolation purposes. + if (host_part.size() == 0) + return false; + + if (host_part.starts_with(kAllSubdomainsWildcard)) { + isolate_all_subdomains_ = true; + host_part.remove_prefix(strlen(kAllSubdomainsWildcard)); + } + + GURL conformant_url(base::JoinString({scheme_part, host_part}, "")); + origin_ = url::Origin::Create(conformant_url); + + // Ports are ignored when matching isolated origins (see also + // https://crbug.com/914511). + const std::string& scheme = origin_.scheme(); + int default_port = url::DefaultPortForScheme(scheme.data(), scheme.length()); + if (origin_.port() != default_port) { + LOG(ERROR) << "Ignoring port number in isolated origin: " << origin_; + origin_ = url::Origin::Create(GURL( + origin_.scheme() + url::kStandardSchemeSeparator + origin_.host())); + } + + // Can't isolate subdomains of an IP address, must be a valid isolated origin + // after processing. + if ((conformant_url.HostIsIPAddress() && isolate_all_subdomains_) || + !IsolatedOriginUtil::IsValidIsolatedOrigin(origin_)) { + origin_ = url::Origin(); + isolate_all_subdomains_ = false; + return false; + } + + is_valid_ = true; + return true; +} + // static bool IsolatedOriginUtil::DoesOriginMatchIsolatedOrigin( const url::Origin& origin,
diff --git a/content/browser/isolated_origin_util.h b/content/browser/isolated_origin_util.h index 4ee8037..9513d76 100644 --- a/content/browser/isolated_origin_util.h +++ b/content/browser/isolated_origin_util.h
@@ -5,11 +5,69 @@ #ifndef CONTENT_BROWSER_ISOLATED_ORIGIN_UTIL_H_ #define CONTENT_BROWSER_ISOLATED_ORIGIN_UTIL_H_ +#include <string> + +#include "base/gtest_prod_util.h" +#include "base/strings/string_util.h" #include "content/common/content_export.h" #include "url/origin.h" namespace content { +// This class holds isolated origin patterns, providing support for double +// wildcard origins, e.g. https://**.foo.com indicates that all domains under +// foo.com are to be treated as if they are distinct isolated +// origins. Non-wildcard origins to be isolated are also supported, e.g. +// https://bar.com. +class CONTENT_EXPORT IsolatedOriginPattern { + public: + explicit IsolatedOriginPattern(base::StringPiece pattern); + explicit IsolatedOriginPattern(const url::Origin& origin); + ~IsolatedOriginPattern(); + + // Copying and moving supported. + IsolatedOriginPattern(const IsolatedOriginPattern& other); + IsolatedOriginPattern& operator=(const IsolatedOriginPattern& other); + + IsolatedOriginPattern(IsolatedOriginPattern&& other); + IsolatedOriginPattern& operator=(IsolatedOriginPattern&& other); + + bool operator==(const IsolatedOriginPattern& other) const { + return pattern_ == other.pattern_ && origin_ == other.origin_ && + isolate_all_subdomains_ == other.isolate_all_subdomains_; + } + + // Returns the url::Origin corresponding to the pattern supplied at + // construction time or via a call to Parse. In the event of parsing failure + // this oriqin will be opaque. + const url::Origin& origin() const { return origin_; } + + // True if the supplied pattern was of the form https://**.foo.com, indicating + // all subdomains of foo.com are to be isolated. + bool isolate_all_subdomains() const { return isolate_all_subdomains_; } + + // Return the original pattern used to construct this instance. + const base::StringPiece pattern() const { return pattern_; } + + // Return if this origin is valid for isolation purposes. + bool is_valid() const { return is_valid_; } + + private: + friend class ChildProcessSecurityPolicyTest; + FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, + IsolatedOriginPattern); + + // Checks if |pattern| is a wildcard pattern, checks the scheme is one of + // {http, https} and constructs a url::Origin() that can be retrieved if + // parsing is successful. Returns true on successful parsing. + bool Parse(const base::StringPiece& pattern); + + std::string pattern_; + url::Origin origin_; + bool isolate_all_subdomains_; + bool is_valid_; +}; + class CONTENT_EXPORT IsolatedOriginUtil { public: // Checks whether |origin| matches the isolated origin specified by
diff --git a/content/browser/loader/prefetch_browsertest.cc b/content/browser/loader/prefetch_browsertest.cc index 8fa10d5..2c2a541 100644 --- a/content/browser/loader/prefetch_browsertest.cc +++ b/content/browser/loader/prefetch_browsertest.cc
@@ -68,7 +68,6 @@ }; IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, Simple) { - int target_fetch_count = 0; const char* prefetch_path = "/prefetch.html"; const char* target_path = "/target.html"; RegisterResponse( @@ -80,21 +79,21 @@ ResponseEntry("<head><title>Prefetch Target</title></head>")); base::RunLoop prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), target_path, - &target_fetch_count, &prefetch_waiter); + auto request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), target_path, &prefetch_waiter); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(0, target_fetch_count); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, request_counter->GetRequestCount()); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); const GURL target_url = embedded_test_server()->GetURL(target_path); // Loading a page that prefetches the target URL would increment the - // |target_fetch_count|. + // |request_counter|. NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); prefetch_waiter.Run(); - EXPECT_EQ(1, target_fetch_count); - EXPECT_EQ(1, prefetch_url_loader_called_); + EXPECT_EQ(1, request_counter->GetRequestCount()); + EXPECT_EQ(1, GetPrefetchURLLoaderCallCount()); // Shutdown the server. EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); @@ -105,7 +104,6 @@ } IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, CrossOrigin) { - int target_fetch_count = 0; const char* prefetch_path = "/prefetch.html"; const char* target_path = "/target.html"; RegisterResponse( @@ -113,8 +111,8 @@ ResponseEntry("<head><title>Prefetch Target</title></head>")); base::RunLoop prefetch_waiter; - RegisterRequestMonitor(cross_origin_server_.get(), target_path, - &target_fetch_count, &prefetch_waiter); + auto request_counter = RequestCounter::CreateAndMonitor( + cross_origin_server_.get(), target_path, &prefetch_waiter); RegisterRequestHandler(cross_origin_server_.get()); ASSERT_TRUE(cross_origin_server_->Start()); @@ -126,15 +124,15 @@ cross_origin_target_url.spec().c_str()))); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(0, target_fetch_count); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, request_counter->GetRequestCount()); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); // Loading a page that prefetches the target URL would increment the - // |target_fetch_count|. + // |request_counter|. NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); prefetch_waiter.Run(); - EXPECT_EQ(1, target_fetch_count); - EXPECT_EQ(1, prefetch_url_loader_called_); + EXPECT_EQ(1, request_counter->GetRequestCount()); + EXPECT_EQ(1, GetPrefetchURLLoaderCallCount()); // Shutdown the servers. EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); @@ -146,7 +144,6 @@ } IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, DoublePrefetch) { - int target_fetch_count = 0; const char* prefetch_path = "/prefetch.html"; const char* target_path = "/target.html"; RegisterResponse(prefetch_path, ResponseEntry(base::StringPrintf( @@ -158,21 +155,21 @@ ResponseEntry("<head><title>Prefetch Target</title></head>")); base::RunLoop prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), target_path, - &target_fetch_count, &prefetch_waiter); + auto request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), target_path, &prefetch_waiter); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(0, target_fetch_count); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, request_counter->GetRequestCount()); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); const GURL target_url = embedded_test_server()->GetURL(target_path); // Loading a page that prefetches the target URL would increment the - // |target_fetch_count|, but it should hit only once. + // |request_counter|, but it should hit only once. NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); prefetch_waiter.Run(); - EXPECT_EQ(1, target_fetch_count); - EXPECT_EQ(1, prefetch_url_loader_called_); + EXPECT_EQ(1, request_counter->GetRequestCount()); + EXPECT_EQ(1, GetPrefetchURLLoaderCallCount()); // Shutdown the server. EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); @@ -183,8 +180,6 @@ } IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, NoCacheAndNoStore) { - int nocache_fetch_count = 0; - int nostore_fetch_count = 0; const char* prefetch_path = "/prefetch.html"; const char* nocache_path = "/target1.html"; const char* nostore_path = "/target2.html"; @@ -203,41 +198,39 @@ base::RunLoop nocache_waiter; base::RunLoop nostore_waiter; - RegisterRequestMonitor(embedded_test_server(), nocache_path, - &nocache_fetch_count, &nocache_waiter); - RegisterRequestMonitor(embedded_test_server(), nostore_path, - &nostore_fetch_count, &nostore_waiter); + auto nocache_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), nocache_path, &nocache_waiter); + auto nostore_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), nostore_path, &nostore_waiter); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); // Loading a page that prefetches the target URL would increment the // fetch count for the both targets. NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); nocache_waiter.Run(); nostore_waiter.Run(); - EXPECT_EQ(1, nocache_fetch_count); - EXPECT_EQ(1, nostore_fetch_count); - EXPECT_EQ(2, prefetch_url_loader_called_); + EXPECT_EQ(1, nocache_request_counter->GetRequestCount()); + EXPECT_EQ(1, nostore_request_counter->GetRequestCount()); + EXPECT_EQ(2, GetPrefetchURLLoaderCallCount()); // Subsequent navigation to the no-cache URL wouldn't hit the network, because // no-cache resource is kept available up to kPrefetchReuseMins. NavigateToURLAndWaitTitle(embedded_test_server()->GetURL(nocache_path), "NoCache Target"); - EXPECT_EQ(1, nocache_fetch_count); + EXPECT_EQ(1, nocache_request_counter->GetRequestCount()); // Subsequent navigation to the no-store URL hit the network again, because // no-store resource is not cached even for prefetch. NavigateToURLAndWaitTitle(embedded_test_server()->GetURL(nostore_path), "NoStore Target"); - EXPECT_EQ(2, nostore_fetch_count); + EXPECT_EQ(2, nostore_request_counter->GetRequestCount()); - EXPECT_EQ(2, prefetch_url_loader_called_); + EXPECT_EQ(2, GetPrefetchURLLoaderCallCount()); } IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WithPreload) { - int target_fetch_count = 0; - int preload_fetch_count = 0; const char* prefetch_path = "/prefetch.html"; const char* target_path = "/target.html"; const char* preload_path = "/preload.js"; @@ -256,23 +249,23 @@ {{"cache-control", "public, max-age=600"}})); base::RunLoop preload_waiter; - RegisterRequestMonitor(embedded_test_server(), target_path, - &target_fetch_count, nullptr /* waiter */); - RegisterRequestMonitor(embedded_test_server(), preload_path, - &preload_fetch_count, &preload_waiter); + auto target_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), target_path); + auto preload_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), preload_path, &preload_waiter); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); const GURL target_url = embedded_test_server()->GetURL(target_path); // Loading a page that prefetches the target URL would increment both - // |target_fetch_count| and |preload_fetch_count|. + // |target_request_counter| and |preload_request_counter|. NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); preload_waiter.Run(); - EXPECT_EQ(1, target_fetch_count); - EXPECT_EQ(1, preload_fetch_count); - EXPECT_EQ(1, prefetch_url_loader_called_); + EXPECT_EQ(1, target_request_counter->GetRequestCount()); + EXPECT_EQ(1, preload_request_counter->GetRequestCount()); + EXPECT_EQ(1, GetPrefetchURLLoaderCallCount()); WaitUntilLoaded(embedded_test_server()->GetURL(preload_path)); @@ -283,8 +276,6 @@ } IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, CrossOriginWithPreload) { - int target_fetch_count = 0; - int preload_fetch_count = 0; const char* target_path = "/target.html"; const char* preload_path = "/preload.js"; RegisterResponse( @@ -299,11 +290,10 @@ {{"cache-control", "public, max-age=600"}})); base::RunLoop preload_waiter; - - RegisterRequestMonitor(cross_origin_server_.get(), target_path, - &target_fetch_count, nullptr /* waiter */); - RegisterRequestMonitor(cross_origin_server_.get(), preload_path, - &preload_fetch_count, &preload_waiter); + auto target_request_counter = + RequestCounter::CreateAndMonitor(cross_origin_server_.get(), target_path); + auto preload_request_counter = RequestCounter::CreateAndMonitor( + cross_origin_server_.get(), preload_path, &preload_waiter); RegisterRequestHandler(cross_origin_server_.get()); ASSERT_TRUE(cross_origin_server_->Start()); @@ -316,15 +306,15 @@ cross_origin_target_url.spec().c_str()))); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); // Loading a page that prefetches the target URL would increment both - // |target_fetch_count| and |preload_fetch_count|. + // |target_request_counter| and |preload_request_counter|. NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); preload_waiter.Run(); - EXPECT_EQ(1, target_fetch_count); - EXPECT_EQ(1, preload_fetch_count); - EXPECT_EQ(1, prefetch_url_loader_called_); + EXPECT_EQ(1, target_request_counter->GetRequestCount()); + EXPECT_EQ(1, preload_request_counter->GetRequestCount()); + EXPECT_EQ(1, GetPrefetchURLLoaderCallCount()); WaitUntilLoaded(cross_origin_server_->GetURL(preload_path)); @@ -337,9 +327,7 @@ NavigateToURLAndWaitTitle(cross_origin_target_url, "done"); } -IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) { - int target_fetch_count = 0; - int preload_fetch_count = 0; +IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, SignedExchangeWithPreload) { const char* prefetch_path = "/prefetch.html"; const char* target_sxg_path = "/target.sxg"; const char* target_path = "/target.html"; @@ -363,13 +351,13 @@ base::RunLoop preload_waiter; base::RunLoop prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), target_sxg_path, - &target_fetch_count, &prefetch_waiter); - RegisterRequestMonitor(embedded_test_server(), preload_path_in_sxg, - &preload_fetch_count, &preload_waiter); + auto target_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), target_sxg_path, &prefetch_waiter); + auto preload_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), preload_path_in_sxg, &preload_waiter); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); const GURL preload_url_in_sxg = embedded_test_server()->GetURL(preload_path_in_sxg); @@ -384,10 +372,10 @@ ScopedSignedExchangeHandlerFactory scoped_factory(&factory); // Loading a page that prefetches the target URL would increment both - // |target_fetch_count| and |preload_fetch_count|. + // |target_request_counter| and |preload_request_counter|. NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); prefetch_waiter.Run(); - EXPECT_EQ(1, target_fetch_count); + EXPECT_EQ(1, target_request_counter->GetRequestCount()); // Test after this point requires SignedHTTPExchange support if (!GetParam().signed_exchange_enabled) @@ -396,8 +384,8 @@ // If the header in the .sxg file is correctly extracted, we should // be able to also see the preload. preload_waiter.Run(); - EXPECT_EQ(1, preload_fetch_count); - EXPECT_EQ(1, prefetch_url_loader_called_); + EXPECT_EQ(1, preload_request_counter->GetRequestCount()); + EXPECT_EQ(1, GetPrefetchURLLoaderCallCount()); // Shutdown the server. EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); @@ -407,9 +395,8 @@ NavigateToURLAndWaitTitle(target_sxg_url, "done"); } -IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, CrossOriginWebPackageWithPreload) { - int target_fetch_count = 0; - int preload_fetch_count = 0; +IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, + CrossOriginSignedExchangeWithPreload) { const char* prefetch_path = "/prefetch.html"; const char* target_sxg_path = "/target.sxg"; const char* target_path = "/target.html"; @@ -429,10 +416,10 @@ base::RunLoop preload_waiter; base::RunLoop prefetch_waiter; - RegisterRequestMonitor(cross_origin_server_.get(), target_sxg_path, - &target_fetch_count, &prefetch_waiter); - RegisterRequestMonitor(cross_origin_server_.get(), preload_path_in_sxg, - &preload_fetch_count, &preload_waiter); + auto target_request_counter = RequestCounter::CreateAndMonitor( + cross_origin_server_.get(), target_sxg_path, &prefetch_waiter); + auto preload_request_counter = RequestCounter::CreateAndMonitor( + cross_origin_server_.get(), preload_path_in_sxg, &preload_waiter); RegisterRequestHandler(cross_origin_server_.get()); ASSERT_TRUE(cross_origin_server_->Start()); @@ -446,7 +433,7 @@ target_sxg_url.spec().c_str()))); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); MockSignedExchangeHandlerFactory factory({MockSignedExchangeHandlerParams( target_sxg_url, SignedExchangeLoadResult::kSuccess, net::OK, @@ -457,10 +444,10 @@ ScopedSignedExchangeHandlerFactory scoped_factory(&factory); // Loading a page that prefetches the target URL would increment both - // |target_fetch_count| and |preload_fetch_count|. + // |target_request_counter| and |preload_request_counter|. NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); prefetch_waiter.Run(); - EXPECT_EQ(1, target_fetch_count); + EXPECT_EQ(1, target_request_counter->GetRequestCount()); // Test after this point requires SignedHTTPExchange support if (!GetParam().signed_exchange_enabled) @@ -468,9 +455,9 @@ // If the header in the .sxg file is correctly extracted, we should // be able to also see the preload. preload_waiter.Run(); - EXPECT_EQ(1, preload_fetch_count); + EXPECT_EQ(1, preload_request_counter->GetRequestCount()); - EXPECT_EQ(1, prefetch_url_loader_called_); + EXPECT_EQ(1, GetPrefetchURLLoaderCallCount()); WaitUntilLoaded(preload_url_in_sxg);
diff --git a/content/browser/loader/prefetch_browsertest_base.cc b/content/browser/loader/prefetch_browsertest_base.cc index 88c0293..c43b5c4a 100644 --- a/content/browser/loader/prefetch_browsertest_base.cc +++ b/content/browser/loader/prefetch_browsertest_base.cc
@@ -88,30 +88,16 @@ return nullptr; } -void PrefetchBrowserTestBase::WatchURLAndRunClosure( - const std::string& relative_url, - int* visit_count, - base::OnceClosure closure, - const net::test_server::HttpRequest& request) { - if (request.relative_url == relative_url) { - (*visit_count)++; - if (closure) - std::move(closure).Run(); - } -} - void PrefetchBrowserTestBase::OnPrefetchURLLoaderCalled() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + base::AutoLock lock(lock_); prefetch_url_loader_called_++; } -void PrefetchBrowserTestBase::RegisterRequestMonitor( - net::EmbeddedTestServer* test_server, - const std::string& path, - int* count, - base::RunLoop* waiter) { - test_server->RegisterRequestMonitor(base::BindRepeating( - &PrefetchBrowserTestBase::WatchURLAndRunClosure, base::Unretained(this), - path, count, waiter ? waiter->QuitClosure() : base::RepeatingClosure())); +int PrefetchBrowserTestBase::GetPrefetchURLLoaderCallCount() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + base::AutoLock lock(lock_); + return prefetch_url_loader_called_; } void PrefetchBrowserTestBase::RegisterRequestHandler( @@ -157,4 +143,40 @@ ASSERT_TRUE(result); } +// static +scoped_refptr<PrefetchBrowserTestBase::RequestCounter> +PrefetchBrowserTestBase::RequestCounter::CreateAndMonitor( + net::EmbeddedTestServer* test_server, + const std::string& path, + base::RunLoop* waiter) { + auto counter = base::MakeRefCounted<RequestCounter>(path, waiter); + test_server->RegisterRequestMonitor( + base::BindRepeating(&RequestCounter::OnRequest, counter)); + return counter; +} + +PrefetchBrowserTestBase::RequestCounter::RequestCounter(const std::string& path, + base::RunLoop* waiter) + : waiter_closure_(waiter ? waiter->QuitClosure() : base::OnceClosure()), + path_(path) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); +} + +PrefetchBrowserTestBase::RequestCounter::~RequestCounter() = default; + +int PrefetchBrowserTestBase::RequestCounter::GetRequestCount() { + base::AutoLock lock(lock_); + return request_count_; +} + +void PrefetchBrowserTestBase::RequestCounter::OnRequest( + const net::test_server::HttpRequest& request) { + if (request.relative_url != path_) + return; + base::AutoLock lock(lock_); + ++request_count_; + if (waiter_closure_) + std::move(waiter_closure_).Run(); +} + } // namespace content
diff --git a/content/browser/loader/prefetch_browsertest_base.h b/content/browser/loader/prefetch_browsertest_base.h index eb478ea..4050076 100644 --- a/content/browser/loader/prefetch_browsertest_base.h +++ b/content/browser/loader/prefetch_browsertest_base.h
@@ -10,6 +10,9 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" +#include "base/thread_annotations.h" #include "content/public/test/content_browser_test.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" @@ -56,30 +59,54 @@ void SetUpOnMainThread() override; protected: + class RequestCounter : public base::RefCountedThreadSafe<RequestCounter> { + public: + // Create a counter that is to be incremented when |path| on the + // |test_server| is accessed. |waiter| can be optionally specified that will + // be run after the counter is incremented. The counter value can be + // obtained via GetRequestCount(). This class works across threads, + // GetRequestCount can be called on any threads. + static scoped_refptr<RequestCounter> CreateAndMonitor( + net::EmbeddedTestServer* test_server, + const std::string& path, + base::RunLoop* waiter = nullptr); + RequestCounter(const std::string& path, base::RunLoop* waiter); + + int GetRequestCount(); + + private: + friend base::RefCountedThreadSafe<RequestCounter>; + ~RequestCounter(); + + void OnRequest(const net::test_server::HttpRequest& request); + + base::OnceClosure waiter_closure_; + const std::string path_; + int request_count_ GUARDED_BY(lock_) = 0; + base::Lock lock_; + + DISALLOW_COPY_AND_ASSIGN(RequestCounter); + }; + void RegisterResponse(const std::string& url, ResponseEntry&& entry); std::unique_ptr<net::test_server::HttpResponse> ServeResponses( const net::test_server::HttpRequest& request); - void WatchURLAndRunClosure(const std::string& relative_url, - int* visit_count, - base::OnceClosure closure, - const net::test_server::HttpRequest& request); void OnPrefetchURLLoaderCalled(); - void RegisterRequestMonitor(net::test_server::EmbeddedTestServer* test_server, - const std::string& path, - int* count, - base::RunLoop* waiter); void RegisterRequestHandler( net::test_server::EmbeddedTestServer* test_server); void NavigateToURLAndWaitTitle(const GURL& url, const std::string& title); void WaitUntilLoaded(const GURL& url); - int prefetch_url_loader_called_ = 0; + int GetPrefetchURLLoaderCallCount(); private: std::map<std::string, ResponseEntry> response_map_; + int prefetch_url_loader_called_ GUARDED_BY(lock_) = 0; + base::Lock lock_; + DISALLOW_COPY_AND_ASSIGN(PrefetchBrowserTestBase); };
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc index dc7ce0c..e119d8b 100644 --- a/content/browser/navigation_browsertest.cc +++ b/content/browser/navigation_browsertest.cc
@@ -1763,7 +1763,7 @@ shell()->LoadURL(embedded_test_server()->GetURL("/doc")); response_1.WaitForRequest(); EXPECT_FALSE( - base::ContainsKey(response_1.http_request()->headers, "header_name")); + base::Contains(response_1.http_request()->headers, "header_name")); response_1.Send( "HTTP/1.1 302 Moved Temporarily\r\nLocation: /new_doc\r\n\r\n"); response_1.Done(); @@ -1859,7 +1859,7 @@ // 2) The header is removed from the second request after the redirect. response_2.WaitForRequest(); EXPECT_FALSE( - base::ContainsKey(response_2.http_request()->headers, "header_name")); + base::Contains(response_2.http_request()->headers, "header_name")); } struct NewWebContentsData {
diff --git a/content/browser/network_service_client.cc b/content/browser/network_service_client.cc index f988069..82b6868 100644 --- a/content/browser/network_service_client.cc +++ b/content/browser/network_service_client.cc
@@ -354,9 +354,12 @@ const base::Optional<network::ResourceResponseHead>& head, network::mojom::AuthChallengeResponderPtr auth_challenge_responder, FrameTreeNodeIdRegistry::IsMainFrameGetter is_main_frame_getter) { - // |is_main_frame_getter| should not be a null callback because the - // FrameTreeNodeIdRegistry should have a corresponding FrameTreeNode id. - CHECK(is_main_frame_getter); + if (!is_main_frame_getter) { + // FrameTreeNode id may already be removed from FrameTreeNodeIdRegistry + // due to thread hopping. + std::move(auth_challenge_responder)->OnAuthCredentials(base::nullopt); + return; + } base::Optional<bool> is_main_frame_opt = is_main_frame_getter.Run(); // The frame may already be gone due to thread hopping. if (!is_main_frame_opt) {
diff --git a/content/browser/plugin_list.cc b/content/browser/plugin_list.cc index 30d8862..466f607 100644 --- a/content/browser/plugin_list.cc +++ b/content/browser/plugin_list.cc
@@ -188,7 +188,7 @@ } for (const base::FilePath& path : extra_plugin_paths) { - if (base::ContainsValue(*plugin_paths, path)) + if (base::Contains(*plugin_paths, path)) continue; plugin_paths->push_back(path); }
diff --git a/content/browser/plugin_private_storage_helper.cc b/content/browser/plugin_private_storage_helper.cc index e9973be..9821dced 100644 --- a/content/browser/plugin_private_storage_helper.cc +++ b/content/browser/plugin_private_storage_helper.cc
@@ -418,7 +418,7 @@ if (!storage_origin.is_empty()) { DCHECK(origin_matcher.is_null()) << "Only 1 of |storage_origin| and " "|origin_matcher| should be specified."; - if (!base::ContainsKey(origins, storage_origin)) { + if (!base::Contains(origins, storage_origin)) { // Nothing matches, so nothing to do. callback.Run(); return;
diff --git a/content/browser/portal/portal_browsertest.cc b/content/browser/portal/portal_browsertest.cc index 729d342..88743034 100644 --- a/content/browser/portal/portal_browsertest.cc +++ b/content/browser/portal/portal_browsertest.cc
@@ -11,6 +11,7 @@ #include "content/browser/frame_host/render_frame_host_manager.h" #include "content/browser/frame_host/render_frame_proxy_host.h" #include "content/browser/portal/portal.h" +#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/renderer_host/render_widget_host_view_child_frame.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -245,7 +246,7 @@ EXPECT_NE(nullptr, portal_contents); EXPECT_NE(portal_contents->GetLastCommittedURL(), a_url); - // The portal should not have navigated yet, we can observe the Portal's + // The portal should not have navigated yet, so we can observe the Portal's // first navigation. TestNavigationObserver navigation_observer(portal_contents); navigation_observer.Wait(); @@ -536,6 +537,53 @@ EXPECT_EQ(base::nullopt, kill_waiter.Wait()); } +// Regression test for crbug.com/969714. Tests that receiving a touch ack +// from the predecessor after portal activation doesn't cause a crash. +IN_PROC_BROWSER_TEST_F(PortalBrowserTest, TouchAckAfterActivate) { + EXPECT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL("portal.test", "/title1.html"))); + WebContentsImpl* web_contents_impl = + static_cast<WebContentsImpl*>(shell()->web_contents()); + RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame(); + + // Create portal and wait for navigation. + PortalCreatedObserver portal_created_observer(main_frame); + GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html")); + EXPECT_TRUE(ExecJs( + main_frame, JsReplace("var portal = document.createElement('portal');" + "portal.src = $1;" + "document.body.appendChild(portal);" + "document.body.addEventListener('touchstart', " + "e => { portal.activate(); }, {passive: false});", + a_url))); + Portal* portal = portal_created_observer.WaitUntilPortalCreated(); + WebContentsImpl* portal_contents = portal->GetPortalContents(); + + // The portal should not have navigated yet, wait for the first navigation. + TestNavigationObserver navigation_observer(portal_contents); + navigation_observer.Wait(); + + PortalInterceptorForTesting* portal_interceptor = + PortalInterceptorForTesting::From(portal); + RenderWidgetHostImpl* render_widget_host = main_frame->GetRenderWidgetHost(); + InputEventAckWaiter input_event_ack_waiter( + render_widget_host, blink::WebInputEvent::Type::kTouchStart); + + SyntheticTapGestureParams params; + params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params.position = gfx::PointF(20, 20); + + std::unique_ptr<SyntheticTapGesture> gesture = + std::make_unique<SyntheticTapGesture>(params); + render_widget_host->QueueSyntheticGesture( + std::move(gesture), base::Bind([](SyntheticGesture::Result) {})); + portal_interceptor->WaitForActivate(); + EXPECT_EQ(portal_contents, shell()->web_contents()); + + // Wait for a touch ack to be sent from the predecessor. + input_event_ack_waiter.Wait(); +} + class PortalOOPIFBrowserTest : public PortalBrowserTest { protected: PortalOOPIFBrowserTest() {}
diff --git a/content/browser/posix_file_descriptor_info_impl.cc b/content/browser/posix_file_descriptor_info_impl.cc index fc76d25..94a498a9 100644 --- a/content/browser/posix_file_descriptor_info_impl.cc +++ b/content/browser/posix_file_descriptor_info_impl.cc
@@ -66,7 +66,7 @@ } bool PosixFileDescriptorInfoImpl::OwnsFD(base::PlatformFile file) { - return base::ContainsValue(owned_descriptors_, file); + return base::Contains(owned_descriptors_, file); } base::ScopedFD PosixFileDescriptorInfoImpl::ReleaseFD(base::PlatformFile file) {
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 8b87570b..6415dc8 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -2271,11 +2271,9 @@ } void RenderWidgetHostImpl::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, + base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) { - if (!shared_bitmap_manager_->ChildAllocatedSharedBitmap( - viz::bitmap_allocation::FromMojoHandle(std::move(buffer)).Map(), - id)) { + if (!shared_bitmap_manager_->ChildAllocatedSharedBitmap(region.Map(), id)) { bad_message::ReceivedBadMessage(GetProcess(), bad_message::RWH_SHARED_BITMAP); } @@ -2710,6 +2708,12 @@ auto* input_event_router = delegate() ? delegate()->GetInputEventRouter() : nullptr; + // With portals, if a touch event triggers an activation, it is possible to + // receive a touch ack after activation. The view is destroyed on activation + // and any pending events in the touch ack queue have already been cleared, so + // we just ignore this ack. + if (!view_) + return; // At present interstitial pages might not have an input event router, so we // just have the view process the ack directly in that case; the view is @@ -2717,7 +2721,7 @@ // ProcessAckedTouchEvent(). if (input_event_router) input_event_router->ProcessAckedTouchEvent(event, ack_result, view_.get()); - else if (view_) + else view_->ProcessAckedTouchEvent(event, ack_result); }
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 654c60e..067b75f 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -21,7 +21,7 @@ #include "base/containers/queue.h" #include "base/gtest_prod_util.h" #include "base/macros.h" -#include "base/memory/shared_memory_handle.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/optional.h" @@ -656,7 +656,7 @@ uint64_t submit_time, const SubmitCompositorFrameSyncCallback callback) override; void DidNotProduceFrame(const viz::BeginFrameAck& ack) override; - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) override; void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override;
diff --git a/content/browser/scheduler/browser_task_executor.h b/content/browser/scheduler/browser_task_executor.h index e72e31a..f37dac3 100644 --- a/content/browser/scheduler/browser_task_executor.h +++ b/content/browser/scheduler/browser_task_executor.h
@@ -62,6 +62,8 @@ // // Attention: This method can only be called once (as there must be only one // IO thread). + // Attention: Must be called after Create() + // Attention: Can not be called after Shutdown() or ResetForTesting() static std::unique_ptr<BrowserProcessSubThread> CreateIOThread(); // Enables non best effort queues on the IO thread. Usually called from @@ -83,7 +85,9 @@ // Winds down the BrowserTaskExecutor, after this no tasks can be executed // and the base::TaskExecutor APIs are non-functional but won't crash if - // called. + // called. In unittests however we need to clean up, so + // BrowserTaskExecutor::ResetForTesting should be + // called (~TestBrowserThreadBundle() takes care of this). static void Shutdown(); // Unregister and delete the TaskExecutor after a test.
diff --git a/content/browser/service_worker/service_worker_database.h b/content/browser/service_worker/service_worker_database.h index 0d26258..e3c87c18 100644 --- a/content/browser/service_worker/service_worker_database.h +++ b/content/browser/service_worker/service_worker_database.h
@@ -94,15 +94,31 @@ }; struct ResourceRecord { + // Represents an error state. Each enum instance should be a negative + // value. This is just temporary for debugging. + // TODO(hayato): Remove this once we fix crbug.com/946719. + enum class ErrorState : int64_t { + // We don't use -1 here to catch an untracked usage of -1 as an error + // code. + kStartedCaching = -2, + kFinishedCachingNoBytesWritten = -3, + }; + int64_t resource_id; GURL url; - // Signed so we can store -1 to specify an unknown or error state. When - // stored to the database, this value should always be >= 0. + // Signed so we can store ErrorState. When stored to the database, this + // value should always be >= 0. int64_t size_bytes; ResourceRecord() : resource_id(-1), size_bytes(0) {} ResourceRecord(int64_t id, GURL url, int64_t size_bytes) - : resource_id(id), url(url), size_bytes(size_bytes) {} + : resource_id(id), url(url), size_bytes(size_bytes) { + DCHECK_GE(size_bytes, 0); + } + ResourceRecord(int64_t id, GURL url, ErrorState error_state) + : resource_id(id), + url(url), + size_bytes(static_cast<int64_t>(error_state)) {} }; // Reads next available ids from the database. Returns OK if they are
diff --git a/content/browser/service_worker/service_worker_script_cache_map.cc b/content/browser/service_worker/service_worker_script_cache_map.cc index d568d80..62c79ed 100644 --- a/content/browser/service_worker/service_worker_script_cache_map.cc +++ b/content/browser/service_worker/service_worker_script_cache_map.cc
@@ -42,8 +42,9 @@ << owner_->status(); if (!context_) return; // Our storage has been wiped via DeleteAndStartOver. - resource_map_[url] = - ServiceWorkerDatabase::ResourceRecord(resource_id, url, -1); + resource_map_[url] = ServiceWorkerDatabase::ResourceRecord( + resource_id, url, + ServiceWorkerDatabase::ResourceRecord::ErrorState::kStartedCaching); context_->storage()->StoreUncommittedResourceId(resource_id); } @@ -66,8 +67,12 @@ main_script_status_ = net::URLRequestStatus::FromError(net_error); main_script_status_message_ = status_message; } - } else { + } else if (size_bytes >= 0) { resource_map_[url].size_bytes = size_bytes; + } else { + resource_map_[url].size_bytes = + static_cast<int64_t>(ServiceWorkerDatabase::ResourceRecord::ErrorState:: + kFinishedCachingNoBytesWritten); } }
diff --git a/content/browser/service_worker/service_worker_single_script_update_checker.cc b/content/browser/service_worker/service_worker_single_script_update_checker.cc index c300cf105..89bbc04 100644 --- a/content/browser/service_worker/service_worker_single_script_update_checker.cc +++ b/content/browser/service_worker/service_worker_single_script_update_checker.cc
@@ -345,17 +345,6 @@ return; } - // Response body is empty. - if (network_loader_state_ == - ServiceWorkerNewScriptLoader::NetworkLoaderState::kCompleted && - body_writer_state_ == - ServiceWorkerNewScriptLoader::WriterState::kCompleted) { - // Compare the cached data with an empty data to notify |cache_writer_| - // the end of the comparison. - CompareData(nullptr /* pending_buffer */, 0 /* bytes_available */); - return; - } - MaybeStartNetworkConsumerHandleWatcher(); } @@ -422,9 +411,14 @@ NOTREACHED() << static_cast<int>(result); } +// |pending_buffer| is a buffer keeping a Mojo data pipe which is going to be +// read by a cache writer. It should be kept alive until the read is done. It's +// nullptr when there is no data to be read, and that means the body from the +// network reaches the end. In that case, |bytes_to_compare| is zero. void ServiceWorkerSingleScriptUpdateChecker::CompareData( scoped_refptr<network::MojoToNetPendingBuffer> pending_buffer, uint32_t bytes_to_compare) { + DCHECK(pending_buffer || bytes_to_compare == 0); auto buffer = base::MakeRefCounted<WrappedIOBuffer>( pending_buffer ? pending_buffer->buffer() : nullptr); @@ -435,11 +429,6 @@ &ServiceWorkerSingleScriptUpdateChecker::OnCompareDataComplete, weak_factory_.GetWeakPtr(), pending_buffer, bytes_to_compare)); - if (pending_buffer) { - pending_buffer->CompleteRead(bytes_to_compare); - network_consumer_ = pending_buffer->ReleaseHandle(); - } - if (error == net::ERR_IO_PENDING && !cache_writer_->is_pausing()) { // OnCompareDataComplete() will be called asynchronously. return; @@ -449,10 +438,25 @@ OnCompareDataComplete(std::move(pending_buffer), bytes_to_compare, error); } +// |pending_buffer| is a buffer passed from CompareData(). Please refer to the +// comment on CompareData(). |error| is the result of the comparison done by the +// cache writer (which is actually reading and not yet writing to the cache, +// since it's in the comparison phase). It's net::OK when the body from the +// network and from the disk cache are the same, net::ERR_IO_PENDING if it +// detects a change in the script, or other error code if something went wrong +// reading from the disk cache. void ServiceWorkerSingleScriptUpdateChecker::OnCompareDataComplete( scoped_refptr<network::MojoToNetPendingBuffer> pending_buffer, uint32_t bytes_written, net::Error error) { + DCHECK(pending_buffer || bytes_written == 0); + if (pending_buffer) { + // We consumed |bytes_written| bytes of data from the network so call + // CompleteRead(), regardless of what |error| is. + pending_buffer->CompleteRead(bytes_written); + network_consumer_ = pending_buffer->ReleaseHandle(); + } + if (cache_writer_->is_pausing()) { // |cache_writer_| can be pausing only when it finds difference between // stored body and network body. @@ -460,11 +464,21 @@ Succeed(Result::kDifferent); return; } - if (!pending_buffer || error != net::OK) { + + if (error != net::OK) { + // Something went wrong reading from the disk cache. + Fail(blink::ServiceWorkerStatusCode::kErrorDiskCache, + kServiceWorkerFetchScriptError); + return; + } + + if (bytes_written == 0) { + // All data has been read. If we reach here without any error, the script + // from the network was identical to the one in the disk cache. Succeed(Result::kIdentical); return; } - DCHECK(pending_buffer); + network_watcher_.ArmOrNotify(); }
diff --git a/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc b/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc index 0d07db7..94881e8 100644 --- a/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc +++ b/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
@@ -16,6 +16,7 @@ #include "net/base/load_flags.h" #include "net/http/http_util.h" #include "services/network/test/test_url_loader_factory.h" +#include "services/network/test/test_utils.h" namespace content { namespace { @@ -154,7 +155,19 @@ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerSingleScriptUpdateCheckerTest); }; -TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Identical_SingleSyncRead) { +class ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTest + : public ServiceWorkerSingleScriptUpdateCheckerTest, + public testing::WithParamInterface<bool> { + public: + static bool IsAsync() { return GetParam(); } +}; + +INSTANTIATE_TEST_SUITE_P(ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTestP, + ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTest, + testing::Bool()); + +TEST_P(ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTest, + Identical_SingleRead) { // Response body from the network. const std::string body_from_net("abcdef"); @@ -170,7 +183,7 @@ auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), - false /* async */); + IsAsync()); base::Optional<CheckResult> check_result; std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = @@ -178,6 +191,22 @@ kScriptURL, GURL(kScope), std::move(compare_reader), std::move(copy_reader), std::move(writer), loader_factory.get(), &check_result); + + if (IsAsync()) { + // Blocked on reading the header. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the header, and then blocked on reading the body. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body. + compare_reader_rawptr->CompletePendingRead(); + } + + // Complete the comparison of the body. It should be identical. base::RunLoop().RunUntilIdle(); EXPECT_TRUE(check_result.has_value()); EXPECT_EQ(check_result.value().result, @@ -186,12 +215,13 @@ EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone()); } -TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Different_SingleSyncRead) { +TEST_P(ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTest, + Identical_MultipleRead) { // Response body from the network. const std::string body_from_net("abcdef"); // Stored data for |kScriptURL|. - const std::vector<std::string> body_from_storage{"abxx"}; + const std::vector<std::string> body_from_storage{"abc", "def"}; std::unique_ptr<network::TestURLLoaderFactory> loader_factory = CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader, @@ -202,7 +232,7 @@ auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), - false /* async */); + IsAsync()); base::Optional<CheckResult> check_result; std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = @@ -211,121 +241,37 @@ std::move(copy_reader), std::move(writer), loader_factory.get(), &check_result); + if (IsAsync()) { + // Blocked on reading the header. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the header, and then blocked on reading the body. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body ("abc"). + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body ("def"). + compare_reader_rawptr->CompletePendingRead(); + } + + // Complete the comparison of the body. It should be identical. base::RunLoop().RunUntilIdle(); EXPECT_TRUE(check_result.has_value()); EXPECT_EQ(check_result.value().result, - ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent); + ServiceWorkerSingleScriptUpdateChecker::Result::kIdentical); EXPECT_EQ(check_result.value().url, kScriptURL); EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone()); } -TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Different_MultipleSyncRead) { - // Response body from the network. - const std::string body_from_net("abcdef"); - - // Stored data for |kScriptURL| (the data for compare reader). - // The comparison should stop in the second block of data. - const std::vector<std::string> body_from_storage{"ab", "cx"}; - - std::unique_ptr<network::TestURLLoaderFactory> loader_factory = - CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader, - body_from_net, net::OK); - - auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>(); - auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>(); - auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); - MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); - compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), - false /* async */); - - base::Optional<CheckResult> check_result; - std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = - CreateSingleScriptUpdateCheckerWithoutHttpCache( - kScriptURL, GURL(kScope), std::move(compare_reader), - std::move(copy_reader), std::move(writer), loader_factory.get(), - &check_result); - - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(check_result.has_value()); - EXPECT_EQ(check_result.value().result, - ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent); - EXPECT_EQ(check_result.value().url, kScriptURL); - EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone()); -} - -TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, NetworkDataLong_SyncRead) { - // Response body from the network. - const std::string body_from_net("abcdef"); - - // Stored data for |kScriptURL| (the data for compare reader). - const std::vector<std::string> body_from_storage{"ab", "cd", ""}; - - std::unique_ptr<network::TestURLLoaderFactory> loader_factory = - CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader, - body_from_net, net::OK); - - auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>(); - auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>(); - auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); - MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); - compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), - false /* async */); - - base::Optional<CheckResult> check_result; - std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = - CreateSingleScriptUpdateCheckerWithoutHttpCache( - kScriptURL, GURL(kScope), std::move(compare_reader), - std::move(copy_reader), std::move(writer), loader_factory.get(), - &check_result); - - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(check_result.has_value()); - EXPECT_EQ(check_result.value().result, - ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent); - EXPECT_EQ(check_result.value().url, kScriptURL); - EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone()); -} - -TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, NetworkDataShort_SyncRead) { - // Response body from the network. - const std::string body_from_net("abcdef"); - - // Stored data for |kScriptURL| (the data for compare reader). - const std::vector<std::string> body_in_storage{"ab", "cd", "ef", "gh"}; - - // Stored data that will actually be read from the compare reader. - // The last 2 bytes of |body_in_storage| won't be read. - const std::vector<std::string> body_read_from_storage{"ab", "cd", "ef"}; - - std::unique_ptr<network::TestURLLoaderFactory> loader_factory = - CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader, - body_from_net, net::OK); - - auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>(); - auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>(); - auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); - MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); - compare_reader->ExpectReadOk(body_read_from_storage, - TotalBytes(body_in_storage), false /* async */); - - base::Optional<CheckResult> check_result; - std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = - CreateSingleScriptUpdateCheckerWithoutHttpCache( - kScriptURL, GURL(kScope), std::move(compare_reader), - std::move(copy_reader), std::move(writer), loader_factory.get(), - &check_result); - - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(check_result.has_value()); - EXPECT_EQ(check_result.value().result, - ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent); - EXPECT_EQ(check_result.value().url, kScriptURL); - EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone()); -} - -TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Identical_SingleAsyncRead) { - // Response body from the network. - const std::string body_from_net("abcdef"); +TEST_P(ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTest, Identical_Empty) { + // Response body from the network, which is empty. + const std::string body_from_net(""); // Stored data for |kScriptURL| (the data for compare reader). const std::vector<std::string> body_from_storage{body_from_net}; @@ -339,7 +285,7 @@ auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), - true /* async */); + IsAsync()); base::Optional<CheckResult> check_result; std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = @@ -348,29 +294,438 @@ std::move(copy_reader), std::move(writer), loader_factory.get(), &check_result); - // Update check stops in WriteHeader() due to the asynchronous read of the - // |compare_reader|. - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(check_result.has_value()); + if (IsAsync()) { + // Blocked on reading the header. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); - // Continue the update check and trigger OnWriteHeadersComplete(). The resumed - // update check stops again at CompareData(). - compare_reader_rawptr->CompletePendingRead(); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(check_result.has_value()); + // Unblock the header. The initial block of the network body is empty, and + // the empty body is passed to the cache writer. It will finish the + // comparison immediately. + compare_reader_rawptr->CompletePendingRead(); + } - // Continue the update check and trigger OnCompareDataComplete(). This will - // finish the entire update check. - compare_reader_rawptr->CompletePendingRead(); + // Both network and storage are empty. The result should be kIdentical. base::RunLoop().RunUntilIdle(); EXPECT_TRUE(check_result.has_value()); EXPECT_EQ(check_result.value().result, ServiceWorkerSingleScriptUpdateChecker::Result::kIdentical); EXPECT_EQ(check_result.value().url, kScriptURL); EXPECT_FALSE(check_result.value().paused_state); +} + +TEST_P(ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTest, + Different_SingleRead_NetworkIsLonger) { + // Response body from the network. + const std::string body_from_net = "abcdef"; + + // Stored data for |kScriptURL|. + const std::vector<std::string> body_from_storage{"abc", ""}; + + std::unique_ptr<network::TestURLLoaderFactory> loader_factory = + CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader, + body_from_net, net::OK); + + auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); + MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); + compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), + IsAsync()); + + base::Optional<CheckResult> check_result; + std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = + CreateSingleScriptUpdateCheckerWithoutHttpCache( + kScriptURL, GURL(kScope), std::move(compare_reader), + std::move(copy_reader), std::move(writer), loader_factory.get(), + &check_result); + + if (IsAsync()) { + // Blocked on reading the header. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the header, and then blocked on reading the body. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body ("abc"). + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body from storage (""). The cache writer detects the end of + // the body from the disk cache. + compare_reader_rawptr->CompletePendingRead(); + } + + // Complete the comparison of the body. It should be different. + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(check_result.has_value()); + EXPECT_EQ(check_result.value().result, + ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent); + EXPECT_EQ(check_result.value().url, kScriptURL); EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone()); } +TEST_P(ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTest, + Different_SingleRead_StorageIsLonger) { + // Response body from the network. + const std::string body_from_net = "abc"; + + // Stored data for |kScriptURL|. + const std::vector<std::string> body_from_storage{"abc", "def"}; + + std::unique_ptr<network::TestURLLoaderFactory> loader_factory = + CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader, + body_from_net, net::OK); + + auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); + MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); + compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), + IsAsync()); + + base::Optional<CheckResult> check_result; + std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = + CreateSingleScriptUpdateCheckerWithoutHttpCache( + kScriptURL, GURL(kScope), std::move(compare_reader), + std::move(copy_reader), std::move(writer), loader_factory.get(), + &check_result); + + if (IsAsync()) { + // Blocked on reading the header. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the header, and then blocked on reading the body. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body ("abc"). At this point, data from the network reaches + // the end. + compare_reader_rawptr->CompletePendingRead(); + } + + // Complete the comparison of the body. It should be different. + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(check_result.has_value()); + EXPECT_EQ(check_result.value().result, + ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent); + EXPECT_EQ(check_result.value().url, kScriptURL); + + // The update checker realizes that the script is different before reaching + // the end of the script from the disk cache. + EXPECT_FALSE(compare_reader_rawptr->AllExpectedReadsDone()); +} + +TEST_P(ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTest, + Different_SingleRead_DifferentBody) { + // Response body from the network. + const std::string body_from_net = "abc"; + + // Stored data for |kScriptURL|. + const std::vector<std::string> body_from_storage{"abx"}; + + std::unique_ptr<network::TestURLLoaderFactory> loader_factory = + CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader, + body_from_net, net::OK); + + auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); + MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); + compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), + IsAsync()); + + base::Optional<CheckResult> check_result; + std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = + CreateSingleScriptUpdateCheckerWithoutHttpCache( + kScriptURL, GURL(kScope), std::move(compare_reader), + std::move(copy_reader), std::move(writer), loader_factory.get(), + &check_result); + + if (IsAsync()) { + // Blocked on reading the header. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the header, and then blocked on reading the body. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body ("abx"). + compare_reader_rawptr->CompletePendingRead(); + } + + // Complete the comparison of the body. It should be different. + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(check_result.has_value()); + EXPECT_EQ(check_result.value().result, + ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent); + EXPECT_EQ(check_result.value().url, kScriptURL); + EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone()); +} + +TEST_P(ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTest, + Different_MultipleRead_NetworkIsLonger) { + // Response body from the network. + const std::string body_from_net = "abcdef"; + + // Stored data for |kScriptURL| (the data for compare reader). + const std::vector<std::string> body_from_storage{"ab", "c", ""}; + + std::unique_ptr<network::TestURLLoaderFactory> loader_factory = + CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader, + body_from_net, net::OK); + + auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); + MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); + compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), + IsAsync()); + + base::Optional<CheckResult> check_result; + std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = + CreateSingleScriptUpdateCheckerWithoutHttpCache( + kScriptURL, GURL(kScope), std::move(compare_reader), + std::move(copy_reader), std::move(writer), loader_factory.get(), + &check_result); + + if (IsAsync()) { + // Blocked on reading the header. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the header, and then blocked on reading the body. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body from storage ("ab"), and then blocked on reading the + // body again. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body from storage ("c"), and then blocked on reading the body + // again. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body from storage (""). The cache writer detects the end of + // the body from the disk cache. + compare_reader_rawptr->CompletePendingRead(); + } + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(check_result.has_value()); + EXPECT_EQ(check_result.value().result, + ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent); + EXPECT_EQ(check_result.value().url, kScriptURL); + EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone()); +} + +TEST_P(ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTest, + Different_MultipleRead_StorageIsLonger) { + // Response body from the network. + const std::string body_from_net = "abc"; + + // Stored data for |kScriptURL| (the data for compare reader). + const std::vector<std::string> body_from_storage{"ab", "c", "def"}; + + std::unique_ptr<network::TestURLLoaderFactory> loader_factory = + CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader, + body_from_net, net::OK); + + auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); + MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); + compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), + IsAsync()); + + base::Optional<CheckResult> check_result; + std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = + CreateSingleScriptUpdateCheckerWithoutHttpCache( + kScriptURL, GURL(kScope), std::move(compare_reader), + std::move(copy_reader), std::move(writer), loader_factory.get(), + &check_result); + + if (IsAsync()) { + // Blocked on reading the header. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the header, and then blocked on reading the body. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body from storage ("ab"), and then blocked on reading the + // body again. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body from storage ("c"). At this point, data from the network + // reaches the end. + compare_reader_rawptr->CompletePendingRead(); + } + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(check_result.has_value()); + EXPECT_EQ(check_result.value().result, + ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent); + EXPECT_EQ(check_result.value().url, kScriptURL); + + // The update checker realizes that the script is different before reaching + // the end of the script from the disk cache. + EXPECT_FALSE(compare_reader_rawptr->AllExpectedReadsDone()); +} + +TEST_P(ServiceWorkerSingleScriptUpdateCheckerToggleAsyncTest, + Different_MultipleRead_DifferentBody) { + // Response body from the network. + const std::string body_from_net = "abc"; + + // Stored data for |kScriptURL| (the data for compare reader). + const std::vector<std::string> body_from_storage{"ab", "x"}; + + std::unique_ptr<network::TestURLLoaderFactory> loader_factory = + CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader, + body_from_net, net::OK); + + auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); + MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); + compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), + IsAsync()); + + base::Optional<CheckResult> check_result; + std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = + CreateSingleScriptUpdateCheckerWithoutHttpCache( + kScriptURL, GURL(kScope), std::move(compare_reader), + std::move(copy_reader), std::move(writer), loader_factory.get(), + &check_result); + + if (IsAsync()) { + // Blocked on reading the header. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the header, and then blocked on reading the body. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body from storage ("ab"), and then blocked on reading the + // body again. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Unblock the body from storage ("x"), which is different from the body + // from the network. + compare_reader_rawptr->CompletePendingRead(); + } + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(check_result.has_value()); + EXPECT_EQ(check_result.value().result, + ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent); + EXPECT_EQ(check_result.value().url, kScriptURL); + EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone()); +} + +TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, + PendingReadWithErrorStatusShouldNotLeak) { + // Response body from the network. + const std::string body_from_net("abc"); + + // Stored data for |kScriptURL| (the data for compare reader). + const std::vector<std::string> body_from_storage{"ab", "c"}; + + auto loader_factory = std::make_unique<network::TestURLLoaderFactory>(); + auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>(); + auto writer = std::make_unique<MockServiceWorkerResponseWriter>(); + MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get(); + compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage), + /*async=*/true); + + base::Optional<CheckResult> check_result; + std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = + CreateSingleScriptUpdateCheckerWithoutHttpCache( + kScriptURL, GURL(kScope), std::move(compare_reader), + std::move(copy_reader), std::move(writer), loader_factory.get(), + &check_result); + + // The update checker sends a request to the loader. The testing loader keeps + // the request. + base::RunLoop().RunUntilIdle(); + network::TestURLLoaderFactory::PendingRequest* request = + loader_factory->GetPendingRequest(0); + ASSERT_TRUE(request); + + // Simulate to send the head and the body back to the checker. + // Note that OnComplete() is not called yet. + { + network::ResourceResponseHead head = + network::CreateResourceResponseHead(net::HTTP_OK); + head.headers = base::MakeRefCounted<net::HttpResponseHeaders>( + net::HttpUtil::AssembleRawHeaders(kSuccessHeader)); + head.headers->GetMimeType(&head.mime_type); + request->client->OnReceiveResponse(head); + + MojoCreateDataPipeOptions options; + options.struct_size = sizeof(MojoCreateDataPipeOptions); + options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE; + options.element_num_bytes = 1; + options.capacity_num_bytes = body_from_net.size(); + mojo::ScopedDataPipeConsumerHandle consumer; + mojo::ScopedDataPipeProducerHandle producer; + EXPECT_EQ(MOJO_RESULT_OK, + mojo::CreateDataPipe(&options, &producer, &consumer)); + uint32_t bytes_written = body_from_net.size(); + EXPECT_EQ(MOJO_RESULT_OK, + producer->WriteData(body_from_net.data(), &bytes_written, + MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); + request->client->OnStartLoadingResponseBody(std::move(consumer)); + } + + // Blocked on reading the header from the storage due to the asynchronous + // read. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Update check stops in CompareReader() due to the asynchronous read of the + // |compare_reader|. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(check_result.has_value()); + + // Return failed status code at this point. The update checker will throw the + // internal state away. + request->client->OnComplete( + network::URLLoaderCompletionStatus(net::ERR_ABORTED)); + base::RunLoop().RunUntilIdle(); + + // Resume the pending read. This should not crash and return kFailed. + compare_reader_rawptr->CompletePendingRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(check_result.has_value()); + EXPECT_EQ(ServiceWorkerSingleScriptUpdateChecker::Result::kFailed, + check_result.value().result); +} + // Tests cache validation behavior when updateViaCache is 'all'. TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, UpdateViaCache_All) { auto loader_factory = std::make_unique<network::TestURLLoaderFactory>();
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc index 7c8be28c..8e58c7e 100644 --- a/content/browser/service_worker/service_worker_storage.cc +++ b/content/browser/service_worker/service_worker_storage.cc
@@ -459,6 +459,7 @@ uint64_t resources_total_size_bytes = 0; for (const auto& resource : resources) { + DCHECK_GE(resource.size_bytes, 0); resources_total_size_bytes += resource.size_bytes; } data.resources_total_size_bytes = resources_total_size_bytes;
diff --git a/content/browser/service_worker/service_worker_test_utils.cc b/content/browser/service_worker/service_worker_test_utils.cc index 9ae72b78..00b258f 100644 --- a/content/browser/service_worker/service_worker_test_utils.cc +++ b/content/browser/service_worker/service_worker_test_utils.cc
@@ -385,6 +385,7 @@ DCHECK(!expected_reads_.empty()); ExpectedRead expected = expected_reads_.front(); EXPECT_FALSE(expected.info); + EXPECT_LE(static_cast<int>(expected.len), buf_len); if (expected.async) { pending_callback_ = std::move(callback); pending_buffer_ = buf;
diff --git a/content/browser/snapshot_browsertest.cc b/content/browser/snapshot_browsertest.cc index 578e4c2a..1ed8faf 100644 --- a/content/browser/snapshot_browsertest.cc +++ b/content/browser/snapshot_browsertest.cc
@@ -357,7 +357,7 @@ ExpectedColor expected; do { PickRandomColor(&expected); - } while (base::ContainsValue(expected_snapshots, expected)); + } while (base::Contains(expected_snapshots, expected)); expected_snapshots.push_back(expected); std::string colorString = base::StringPrintf("#%02x%02x%02x", expected.r,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 62b2fa86..7b97736 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2496,7 +2496,7 @@ RenderFrameHostImpl* frame = static_cast<RenderFrameHostImpl*>(rfh); if (is_fullscreen) { - if (!base::ContainsKey(fullscreen_frames_, frame)) { + if (!base::Contains(fullscreen_frames_, frame)) { fullscreen_frames_.insert(frame); FullscreenFrameSetUpdated(); } @@ -6913,7 +6913,7 @@ base::Optional<gfx::Size> WebContentsImpl::GetFullscreenVideoSize() { base::Optional<MediaPlayerId> id = media_web_contents_observer_->GetFullscreenVideoMediaPlayerId(); - if (id && base::ContainsKey(cached_video_sizes_, id.value())) + if (id && base::Contains(cached_video_sizes_, id.value())) return base::Optional<gfx::Size>(cached_video_sizes_[id.value()]); return base::nullopt; }
diff --git a/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc b/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc index c16c8f9..53bfb94 100644 --- a/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc +++ b/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
@@ -217,10 +217,8 @@ const std::string& inner_url_path, const net::SHA256HashValue& header_integrity, const std::string& content) { - int sxg_fetch_count = 0; - base::RunLoop sxg_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), sxg_path, &sxg_fetch_count, - &sxg_prefetch_waiter); + auto sxg_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), sxg_path); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); @@ -241,15 +239,13 @@ "text/html", {}, header_integrity)}); ScopedSignedExchangeHandlerFactory scoped_factory(&factory); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, sxg_request_counter->GetRequestCount()); NavigateToURL(shell(), prefetch_page_url); - sxg_prefetch_waiter.Run(); - EXPECT_EQ(1, sxg_fetch_count); WaitUntilLoaded(sxg_url); - EXPECT_EQ(1, prefetch_url_loader_called_); + EXPECT_EQ(1, sxg_request_counter->GetRequestCount()); } private: @@ -336,15 +332,10 @@ const char* script_sxg_path = "/script_js.sxg"; const char* script_inner_url_path = "/script.js"; - int script_sxg_fetch_count = 0; - int script_fetch_count = 0; - - base::RunLoop script_sxg_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script_sxg_path, - &script_sxg_fetch_count, &script_sxg_prefetch_waiter); - base::RunLoop script_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script_inner_url_path, - &script_fetch_count, &script_prefetch_waiter); + auto script_sxg_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), script_sxg_path); + auto script_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), script_inner_url_path); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); @@ -396,20 +387,8 @@ script_header_integrity)}); ScopedSignedExchangeHandlerFactory scoped_factory(&factory); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); NavigateToURL(shell(), prefetch_page_url); - if (base::FeatureList::IsEnabled( - features::kSignedExchangeSubresourcePrefetch)) { - script_sxg_prefetch_waiter.Run(); - EXPECT_EQ(1, script_sxg_fetch_count); - EXPECT_EQ(0, script_fetch_count); - EXPECT_EQ(2, prefetch_url_loader_called_); - } else { - script_prefetch_waiter.Run(); - EXPECT_EQ(0, script_sxg_fetch_count); - EXPECT_EQ(1, script_fetch_count); - EXPECT_EQ(1, prefetch_url_loader_called_); - } WaitUntilLoaded(sxg_page_url); if (base::FeatureList::IsEnabled( @@ -419,6 +398,17 @@ WaitUntilLoaded(inner_url_script_url); } + if (base::FeatureList::IsEnabled( + features::kSignedExchangeSubresourcePrefetch)) { + EXPECT_EQ(1, script_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, script_request_counter->GetRequestCount()); + EXPECT_EQ(2, GetPrefetchURLLoaderCallCount()); + } else { + EXPECT_EQ(0, script_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(1, script_request_counter->GetRequestCount()); + EXPECT_EQ(1, GetPrefetchURLLoaderCallCount()); + } + const auto cached_exchanges = GetCachedExchanges(shell()); if (base::FeatureList::IsEnabled( features::kSignedExchangeSubresourcePrefetch)) { @@ -446,16 +436,16 @@ // The content is loaded from PrefetchedSignedExchangeCache. And the script // is also loaded from PrefetchedSignedExchangeCache. NavigateToURLAndWaitTitle(sxg_page_url, "done"); - EXPECT_EQ(1, script_sxg_fetch_count); - EXPECT_EQ(0, script_fetch_count); + EXPECT_EQ(1, script_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, script_request_counter->GetRequestCount()); } else { // Subsequent navigation to the target URL wouldn't hit the network for // the target URL. The target content should still be read correctly. // The content is loaded from PrefetchedSignedExchangeCache. But the script // is loaded from the server. NavigateToURLAndWaitTitle(sxg_page_url, "from server"); - EXPECT_EQ(0, script_sxg_fetch_count); - EXPECT_EQ(1, script_fetch_count); + EXPECT_EQ(0, script_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(1, script_request_counter->GetRequestCount()); } } @@ -512,22 +502,14 @@ const std::string& script_inner_url_path, const std::string& expected_title, int expected_script_fetch_count) { - int script_sxg_fetch_count = 0; - int script_fetch_count = 0; - // When |expected_script_fetch_count| is -1, we don't check the script fetch // count. const bool check_script_fetch_count = expected_script_fetch_count != -1; - base::RunLoop script_sxg_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script_sxg_path, - &script_sxg_fetch_count, - &script_sxg_prefetch_waiter); - base::RunLoop script_prefetch_waiter; - if (check_script_fetch_count) { - RegisterRequestMonitor(embedded_test_server(), script_inner_url_path, - &script_fetch_count, &script_prefetch_waiter); - } + auto script_sxg_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), script_sxg_path); + auto script_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), script_inner_url_path); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); @@ -581,18 +563,18 @@ script_header_integrity)}); ScopedSignedExchangeHandlerFactory scoped_factory(&factory); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); NavigateToURL(shell(), prefetch_page_url); - script_sxg_prefetch_waiter.Run(); - EXPECT_EQ(1, script_sxg_fetch_count); - if (check_script_fetch_count) { - EXPECT_EQ(0, script_fetch_count); - } - EXPECT_EQ(2, prefetch_url_loader_called_); WaitUntilLoaded(sxg_page_url); WaitUntilLoaded(sxg_script_url); + EXPECT_EQ(1, script_sxg_request_counter->GetRequestCount()); + if (check_script_fetch_count) { + EXPECT_EQ(0, script_request_counter->GetRequestCount()); + } + EXPECT_EQ(2, GetPrefetchURLLoaderCallCount()); + const auto cached_exchanges = GetCachedExchanges(shell()); EXPECT_EQ(2u, cached_exchanges.size()); @@ -618,9 +600,10 @@ // The script is loaded from the server. NavigateToURLAndWaitTitle(sxg_page_url, expected_title); - EXPECT_EQ(1, script_sxg_fetch_count); + EXPECT_EQ(1, script_sxg_request_counter->GetRequestCount()); if (check_script_fetch_count) { - EXPECT_EQ(expected_script_fetch_count, script_fetch_count); + EXPECT_EQ(expected_script_fetch_count, + script_request_counter->GetRequestCount()); } } @@ -646,21 +629,16 @@ bool has_nosniff, const std::string& expected_title, network::CrossOriginReadBlocking::Action expected_action) { - int script_sxg_fetch_count = 0; - int script_fetch_count = 0; const char* prefetch_path = "/prefetch.html"; const char* target_sxg_path = "/target.sxg"; const char* target_path = "/target.html"; const char* script_sxg_path = "/script_js.sxg"; const char* script_path = "/script.js"; - base::RunLoop script_sxg_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script_sxg_path, - &script_sxg_fetch_count, - &script_sxg_prefetch_waiter); - base::RunLoop script_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script_path, - &script_fetch_count, &script_prefetch_waiter); + auto script_sxg_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), script_sxg_path); + auto script_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), script_path); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); @@ -716,13 +694,13 @@ ScopedSignedExchangeHandlerFactory scoped_factory(&factory); NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); - script_sxg_prefetch_waiter.Run(); - EXPECT_EQ(1, script_sxg_fetch_count); - EXPECT_EQ(0, script_fetch_count); WaitUntilLoaded(target_sxg_url); WaitUntilLoaded(script_sxg_url); + EXPECT_EQ(1, script_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, script_request_counter->GetRequestCount()); + EXPECT_EQ(2u, GetCachedExchanges(shell()).size()); { @@ -735,8 +713,8 @@ expected_action, 1); } - EXPECT_EQ(1, script_sxg_fetch_count); - EXPECT_EQ(0, script_fetch_count); + EXPECT_EQ(1, script_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, script_request_counter->GetRequestCount()); } private: @@ -814,10 +792,6 @@ IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest, ImageSrcsetAndSizes) { - int image1_sxg_fetch_count = 0; - int image1_fetch_count = 0; - int image2_sxg_fetch_count = 0; - int image2_fetch_count = 0; const char* prefetch_path = "/prefetch.html"; const char* target_sxg_path = "/target.sxg"; const char* target_path = "/target.html"; @@ -826,18 +800,14 @@ const char* image2_sxg_path = "/image2_png.sxg"; const char* image2_path = "/image2.png"; - base::RunLoop image1_sxg_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), image1_sxg_path, - &image1_sxg_fetch_count, &image1_sxg_prefetch_waiter); - base::RunLoop image1_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), image1_path, - &image1_fetch_count, &image1_prefetch_waiter); - base::RunLoop image2_sxg_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), image2_sxg_path, - &image2_sxg_fetch_count, &image2_sxg_prefetch_waiter); - base::RunLoop image2_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), image2_path, - &image2_fetch_count, &image2_prefetch_waiter); + auto image1_sxg_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), image1_sxg_path); + auto image2_sxg_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), image2_sxg_path); + auto image1_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), image1_path); + auto image2_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), image2_path); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); @@ -913,15 +883,14 @@ ScopedSignedExchangeHandlerFactory scoped_factory(&factory); NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); - image1_sxg_prefetch_waiter.Run(); - EXPECT_EQ(1, image1_sxg_fetch_count); - EXPECT_EQ(0, image1_fetch_count); - EXPECT_EQ(0, image2_sxg_fetch_count); - EXPECT_EQ(0, image2_fetch_count); - WaitUntilLoaded(target_sxg_url); WaitUntilLoaded(image1_sxg_url); + EXPECT_EQ(1, image1_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, image1_request_counter->GetRequestCount()); + EXPECT_EQ(0, image2_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, image2_request_counter->GetRequestCount()); + const auto cached_exchanges = GetCachedExchanges(shell()); EXPECT_EQ(2u, cached_exchanges.size()); @@ -939,18 +908,14 @@ NavigateToURLAndWaitTitle(target_sxg_url, "done"); - EXPECT_EQ(1, image1_sxg_fetch_count); - EXPECT_EQ(0, image1_fetch_count); - EXPECT_EQ(0, image2_sxg_fetch_count); - EXPECT_EQ(0, image2_fetch_count); + EXPECT_EQ(1, image1_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, image1_request_counter->GetRequestCount()); + EXPECT_EQ(0, image2_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, image2_request_counter->GetRequestCount()); } IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest, MultipleResources) { - int script1_sxg_fetch_count = 0; - int script1_fetch_count = 0; - int script2_sxg_fetch_count = 0; - int script2_fetch_count = 0; const char* prefetch_path = "/prefetch.html"; const char* target_sxg_path = "/target.sxg"; const char* target_path = "/target.html"; @@ -959,23 +924,17 @@ const char* script2_sxg_path = "/script2_js.sxg"; const char* script2_path = "/script2.js"; - base::RunLoop script1_sxg_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script1_sxg_path, - &script1_sxg_fetch_count, - &script1_sxg_prefetch_waiter); - base::RunLoop script1_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script1_path, - &script1_fetch_count, &script1_prefetch_waiter); - base::RunLoop script2_sxg_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script2_sxg_path, - &script2_sxg_fetch_count, - &script2_sxg_prefetch_waiter); - base::RunLoop script2_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script2_path, - &script2_fetch_count, &script2_prefetch_waiter); + auto script1_sxg_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), script1_sxg_path); + auto script2_sxg_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), script2_sxg_path); + auto script1_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), script1_path); + auto script2_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), script2_path); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path); const GURL target_url = embedded_test_server()->GetURL(target_path); @@ -1034,17 +993,16 @@ ScopedSignedExchangeHandlerFactory scoped_factory(&factory); NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); - script1_sxg_prefetch_waiter.Run(); - script2_sxg_prefetch_waiter.Run(); - EXPECT_EQ(1, script1_sxg_fetch_count); - EXPECT_EQ(0, script1_fetch_count); - EXPECT_EQ(1, script2_sxg_fetch_count); - EXPECT_EQ(0, script2_fetch_count); WaitUntilLoaded(target_sxg_url); WaitUntilLoaded(script1_sxg_url); WaitUntilLoaded(script2_sxg_url); + EXPECT_EQ(1, script1_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, script1_request_counter->GetRequestCount()); + EXPECT_EQ(1, script2_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, script2_request_counter->GetRequestCount()); + const auto cached_exchanges = GetCachedExchanges(shell()); EXPECT_EQ(3u, cached_exchanges.size()); @@ -1072,31 +1030,27 @@ // are also loaded from PrefetchedSignedExchangeCache. NavigateToURLAndWaitTitle(target_sxg_url, "done"); - EXPECT_EQ(1, script1_sxg_fetch_count); - EXPECT_EQ(0, script1_fetch_count); - EXPECT_EQ(1, script2_sxg_fetch_count); - EXPECT_EQ(0, script2_fetch_count); + EXPECT_EQ(1, script1_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, script1_request_counter->GetRequestCount()); + EXPECT_EQ(1, script2_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, script2_request_counter->GetRequestCount()); } IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest, IntegrityMismatch) { - int script_sxg_fetch_count = 0; - int script_fetch_count = 0; const char* prefetch_path = "/prefetch.html"; const char* target_sxg_path = "/target.sxg"; const char* target_path = "/target.html"; const char* script_path = "/script.js"; const char* script_sxg_path = "/script_js.sxg"; - base::RunLoop script_sxg_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script_sxg_path, - &script_sxg_fetch_count, &script_sxg_prefetch_waiter); - base::RunLoop script_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script_path, - &script_fetch_count, &script_prefetch_waiter); + auto script_sxg_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), script_sxg_path); + auto script_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), script_path); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path); const GURL target_url = embedded_test_server()->GetURL(target_path); @@ -1142,27 +1096,24 @@ ScopedSignedExchangeHandlerFactory scoped_factory(&factory); NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); - script_sxg_prefetch_waiter.Run(); - EXPECT_EQ(1, script_sxg_fetch_count); - EXPECT_EQ(0, script_fetch_count); WaitUntilLoaded(target_sxg_url); WaitUntilLoaded(script_sxg_url); + EXPECT_EQ(1, script_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, script_request_counter->GetRequestCount()); + // The value of "header-integrity" in "allowed-alt-sxg" link header of the // inner response doesn't match the actual header integrity of script_js.sxg. // So the script request must go to the server. NavigateToURLAndWaitTitle(target_sxg_url, "from server"); - EXPECT_EQ(1, script_fetch_count); + EXPECT_EQ(1, script_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(1, script_request_counter->GetRequestCount()); } IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest, MultipleResources_IntegrityMismatch) { - int script1_sxg_fetch_count = 0; - int script1_fetch_count = 0; - int script2_sxg_fetch_count = 0; - int script2_fetch_count = 0; const char* prefetch_path = "/prefetch.html"; const char* target_sxg_path = "/target.sxg"; const char* target_path = "/target.html"; @@ -1171,23 +1122,17 @@ const char* script2_sxg_path = "/script2_js.sxg"; const char* script2_path = "/script2.js"; - base::RunLoop script1_sxg_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script1_sxg_path, - &script1_sxg_fetch_count, - &script1_sxg_prefetch_waiter); - base::RunLoop script1_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script1_path, - &script1_fetch_count, &script1_prefetch_waiter); - base::RunLoop script2_sxg_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script2_sxg_path, - &script2_sxg_fetch_count, - &script2_sxg_prefetch_waiter); - base::RunLoop script2_prefetch_waiter; - RegisterRequestMonitor(embedded_test_server(), script2_path, - &script2_fetch_count, &script2_prefetch_waiter); + auto script1_sxg_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), script1_sxg_path); + auto script2_sxg_request_counter = RequestCounter::CreateAndMonitor( + embedded_test_server(), script2_sxg_path); + auto script1_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), script1_path); + auto script2_request_counter = + RequestCounter::CreateAndMonitor(embedded_test_server(), script2_path); RegisterRequestHandler(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(0, prefetch_url_loader_called_); + EXPECT_EQ(0, GetPrefetchURLLoaderCallCount()); const GURL target_sxg_url = embedded_test_server()->GetURL(target_sxg_path); const GURL target_url = embedded_test_server()->GetURL(target_path); @@ -1251,17 +1196,16 @@ ScopedSignedExchangeHandlerFactory scoped_factory(&factory); NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_path)); - script1_sxg_prefetch_waiter.Run(); - script2_sxg_prefetch_waiter.Run(); - EXPECT_EQ(1, script1_sxg_fetch_count); - EXPECT_EQ(0, script1_fetch_count); - EXPECT_EQ(1, script2_sxg_fetch_count); - EXPECT_EQ(0, script2_fetch_count); WaitUntilLoaded(target_sxg_url); WaitUntilLoaded(script1_sxg_url); WaitUntilLoaded(script2_sxg_url); + EXPECT_EQ(1, script1_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, script1_request_counter->GetRequestCount()); + EXPECT_EQ(1, script2_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(0, script2_request_counter->GetRequestCount()); + const auto cached_exchanges = GetCachedExchanges(shell()); EXPECT_EQ(3u, cached_exchanges.size()); @@ -1270,10 +1214,10 @@ // So the all script requests must go to the server. NavigateToURLAndWaitTitle(target_sxg_url, "from server"); - EXPECT_EQ(1, script1_sxg_fetch_count); - EXPECT_EQ(1, script1_fetch_count); - EXPECT_EQ(1, script2_sxg_fetch_count); - EXPECT_EQ(1, script2_fetch_count); + EXPECT_EQ(1, script1_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(1, script1_request_counter->GetRequestCount()); + EXPECT_EQ(1, script2_sxg_request_counter->GetRequestCount()); + EXPECT_EQ(1, script2_request_counter->GetRequestCount()); } IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest, CORS) {
diff --git a/content/common/content_security_policy/content_security_policy_unittest.cc b/content/common/content_security_policy/content_security_policy_unittest.cc index 909de5c3..9fa20b12 100644 --- a/content/common/content_security_policy/content_security_policy_unittest.cc +++ b/content/common/content_security_policy/content_security_policy_unittest.cc
@@ -22,7 +22,7 @@ } bool SchemeShouldBypassCSP(const base::StringPiece& scheme) override { - return base::ContainsValue(scheme_to_bypass_, scheme); + return base::Contains(scheme_to_bypass_, scheme); } private:
diff --git a/content/common/font_cache_dispatcher_win.cc b/content/common/font_cache_dispatcher_win.cc index 7b21544..d4cb522 100644 --- a/content/common/font_cache_dispatcher_win.cc +++ b/content/common/font_cache_dispatcher_win.cc
@@ -45,7 +45,7 @@ base::string16 font_name = font.lfFaceName; int ref_count_inc = 1; - if (!base::ContainsValue(dispatcher_font_map_[dispatcher], font_name)) { + if (!base::Contains(dispatcher_font_map_[dispatcher], font_name)) { // Requested font is new to cache. dispatcher_font_map_[dispatcher].push_back(font_name); } else {
diff --git a/content/common/origin_util.cc b/content/common/origin_util.cc index 1261b8e..d6cd3855 100644 --- a/content/common/origin_util.cc +++ b/content/common/origin_util.cc
@@ -33,7 +33,7 @@ if (url.SchemeIsHTTPOrHTTPS() && IsOriginSecure(url)) return true; - if (base::ContainsValue(GetServiceWorkerSchemes(), url.scheme())) { + if (base::Contains(GetServiceWorkerSchemes(), url.scheme())) { return true; }
diff --git a/content/common/throttling_url_loader.cc b/content/common/throttling_url_loader.cc index a2c6e14..ecdedf3 100644 --- a/content/common/throttling_url_loader.cc +++ b/content/common/throttling_url_loader.cc
@@ -21,7 +21,7 @@ void MergeRemovedHeaders(std::vector<std::string>* removed_headers_A, const std::vector<std::string>& removed_headers_B) { for (auto& header : removed_headers_B) { - if (!base::ContainsValue(*removed_headers_A, header)) + if (!base::Contains(*removed_headers_A, header)) removed_headers_A->emplace_back(std::move(header)); } }
diff --git a/content/public/browser/child_process_security_policy.h b/content/public/browser/child_process_security_policy.h index 59608e1..e761298 100644 --- a/content/public/browser/child_process_security_policy.h +++ b/content/public/browser/child_process_security_policy.h
@@ -19,6 +19,7 @@ namespace content { class BrowserContext; +class IsolatedOriginPattern; // The ChildProcessSecurityPolicy class is used to grant and revoke security // capabilities for child processes. For example, it restricts whether a child @@ -264,7 +265,15 @@ // attempts to re-add an origin for the same |browser_context| will be // ignored. virtual void AddIsolatedOrigins( - std::vector<url::Origin> origins, + const std::vector<url::Origin>& origins, + BrowserContext* browser_context = nullptr) = 0; + + // Semantically identical to the above, but accepts IsolatedOriginPatterns, a + // container class which holds wildcard patterns for isolated origins, such as + // https://**.foo.com indicating that all domains that match the pattern are + // to be given their own isolated process. + virtual void AddIsolatedOrigins( + const std::vector<IsolatedOriginPattern>& patterns, BrowserContext* browser_context = nullptr) = 0; // Returns true if |origin| is a globally (not per-profile) isolated origin.
diff --git a/content/public/browser/notification_registrar.cc b/content/public/browser/notification_registrar.cc index 5fed6a2..91f205d 100644 --- a/content/public/browser/notification_registrar.cc +++ b/content/public/browser/notification_registrar.cc
@@ -110,7 +110,7 @@ const NotificationSource& source) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); Record record = { observer, type, source }; - return base::ContainsValue(registered_, record); + return base::Contains(registered_, record); } } // namespace content
diff --git a/content/public/common/referrer.cc b/content/public/common/referrer.cc index de78496..04706c4c 100644 --- a/content/public/common/referrer.cc +++ b/content/public/common/referrer.cc
@@ -6,8 +6,9 @@ #include <string> -#include "base/command_line.h" +#include "base/numerics/safe_conversions.h" #include "content/public/common/content_features.h" +#include "net/base/features.h" #include "services/network/loader_util.h" namespace content { @@ -81,6 +82,13 @@ } break; } + + if (base::FeatureList::IsEnabled(net::features::kCapRefererHeaderLength) && + base::saturated_cast<int>(sanitized_referrer.url.spec().length()) > + net::features::kMaxRefererHeaderLength.Get()) { + sanitized_referrer.url = sanitized_referrer.url.GetOrigin(); + } + return sanitized_referrer; }
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc index 9c9e8c96..bf2ed9a 100644 --- a/content/public/test/browser_test_base.cc +++ b/content/public/test/browser_test_base.cc
@@ -410,7 +410,6 @@ // for the test harness to be able to delete temp dirs. base::ThreadRestrictions::SetIOAllowed(true); - BrowserTaskExecutor::ResetForTesting(); #else GetContentMainParams()->ui_task = ui_task.release(); GetContentMainParams()->created_main_parts_closure =
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 2d34e18..cde062e 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -2156,7 +2156,7 @@ void TitleWatcher::TestTitle() { const base::string16& current_title = web_contents()->GetTitle(); - if (base::ContainsValue(expected_titles_, current_title)) { + if (base::Contains(expected_titles_, current_title)) { observed_title_ = current_title; run_loop_.Quit(); }
diff --git a/content/public/test/download_test_observer.cc b/content/public/test/download_test_observer.cc index 59472dec..6194485 100644 --- a/content/public/test/download_test_observer.cc +++ b/content/public/test/download_test_observer.cc
@@ -140,7 +140,7 @@ void DownloadTestObserver::OnDownloadUpdated(download::DownloadItem* download) { // Real UI code gets the user's response after returning from the observer. if (download->IsDangerous() && - !base::ContainsKey(dangerous_downloads_seen_, download->GetId())) { + !base::Contains(dangerous_downloads_seen_, download->GetId())) { dangerous_downloads_seen_.insert(download->GetId()); // Calling ValidateDangerousDownload() at this point will
diff --git a/content/public/test/test_launcher.cc b/content/public/test/test_launcher.cc index cf8db90..b9d52aab 100644 --- a/content/public/test/test_launcher.cc +++ b/content/public/test/test_launcher.cc
@@ -263,7 +263,7 @@ // Stack all dependent tests and run them sequentially. test_list.push_back(test_name); if (!IsPreTestName(test_name)) { - if (!base::ContainsKey(user_data_dir_map_, test_name)) { + if (!base::Contains(user_data_dir_map_, test_name)) { base::FilePath temp_dir; CHECK(base::CreateTemporaryDirInDir(temp_dir_.GetPath(), FILE_PATH_LITERAL("d"), &temp_dir)); @@ -293,7 +293,7 @@ // Make sure PRE_ tests and tests that depend on them share the same // data directory - based it on the test name without prefixes. std::string test_name_no_pre(RemoveAnyPrePrefixes(full_name)); - if (!base::ContainsKey(user_data_dir_map_, test_name_no_pre)) { + if (!base::Contains(user_data_dir_map_, test_name_no_pre)) { base::FilePath temp_dir; CHECK(base::CreateTemporaryDirInDir(temp_dir_.GetPath(), FILE_PATH_LITERAL("d"), &temp_dir)); @@ -429,7 +429,7 @@ // No other tests depend on this, we can delete the temporary directory now. // Do so to avoid too many temporary files using lots of disk space. - if (base::ContainsKey(user_data_dir_map_, test_name)) { + if (base::Contains(user_data_dir_map_, test_name)) { if (!base::DeleteFile(user_data_dir_map_[test_name], true)) { LOG(WARNING) << "Failed to delete " << user_data_dir_map_[test_name].value();
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index b281d1b..bde316ef 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -240,8 +240,6 @@ "media/stream/user_media_client_impl.h", "media/stream/user_media_processor.cc", "media/stream/user_media_processor.h", - "media/stream/webaudio_media_stream_source.cc", - "media/stream/webaudio_media_stream_source.h", "media/stream/webmediaplayer_ms.cc", "media/stream/webmediaplayer_ms.h", "media/stream/webmediaplayer_ms_compositor.cc",
diff --git a/content/renderer/accessibility/ax_image_annotator.cc b/content/renderer/accessibility/ax_image_annotator.cc index 8021718..7c40469 100644 --- a/content/renderer/accessibility/ax_image_annotator.cc +++ b/content/renderer/accessibility/ax_image_annotator.cc
@@ -70,12 +70,12 @@ bool AXImageAnnotator::HasImageInCache(const blink::WebAXObject& image) const { DCHECK(!image.IsDetached()); - return base::ContainsKey(image_annotations_, image.AxID()); + return base::Contains(image_annotations_, image.AxID()); } void AXImageAnnotator::OnImageAdded(blink::WebAXObject& image) { DCHECK(!image.IsDetached()); - DCHECK(!base::ContainsKey(image_annotations_, image.AxID())); + DCHECK(!base::Contains(image_annotations_, image.AxID())); const std::string image_id = GenerateImageSourceId(image); if (image_id.empty()) return; @@ -93,7 +93,7 @@ void AXImageAnnotator::OnImageUpdated(blink::WebAXObject& image) { DCHECK(!image.IsDetached()); - DCHECK(base::ContainsKey(image_annotations_, image.AxID())); + DCHECK(base::Contains(image_annotations_, image.AxID())); const std::string image_id = GenerateImageSourceId(image); if (image_id.empty()) return; @@ -242,7 +242,7 @@ void AXImageAnnotator::OnImageAnnotated( const blink::WebAXObject& image, image_annotation::mojom::AnnotateImageResultPtr result) { - if (!base::ContainsKey(image_annotations_, image.AxID())) + if (!base::Contains(image_annotations_, image.AxID())) return; if (image.IsDetached()) {
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc index 6c4d356..9df33a8 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.cc +++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -344,7 +344,7 @@ WebAXObject ancestor = obj; while (!ancestor.IsDetached()) { int32_t ancestor_id = ancestor.AxID(); - if (base::ContainsKey(load_inline_text_boxes_ids_, ancestor_id) || + if (base::Contains(load_inline_text_boxes_ids_, ancestor_id) || (ancestor_id == focus_id && ancestor.IsEditable())) { return true; }
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/content/renderer/android/synchronous_layer_tree_frame_sink.cc index 3bfc4880..20d62c2 100644 --- a/content/renderer/android/synchronous_layer_tree_frame_sink.cc +++ b/content/renderer/android/synchronous_layer_tree_frame_sink.cc
@@ -358,7 +358,7 @@ } void SynchronousLayerTreeFrameSink::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, + base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) { // Webview does not use software compositing (other than resourceless draws, // but this is called for software /resources/).
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.h b/content/renderer/android/synchronous_layer_tree_frame_sink.h index a1359160..a41f849 100644 --- a/content/renderer/android/synchronous_layer_tree_frame_sink.h +++ b/content/renderer/android/synchronous_layer_tree_frame_sink.h
@@ -13,6 +13,7 @@ #include "base/cancelable_callback.h" #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" @@ -98,7 +99,7 @@ bool hit_test_data_changed, bool show_hit_test_borders) override; void DidNotProduceFrame(const viz::BeginFrameAck& ack) override; - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) override; void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override; void Invalidate(bool needs_draw) override;
diff --git a/content/renderer/categorized_worker_pool.cc b/content/renderer/categorized_worker_pool.cc index c13116f..c5bf882 100644 --- a/content/renderer/categorized_worker_pool.cc +++ b/content/renderer/categorized_worker_pool.cc
@@ -236,7 +236,7 @@ CollectCompletedTasksWithLockAcquired(namespace_token_, &completed_tasks_); base::EraseIf(tasks_, [this](const scoped_refptr<cc::Task>& e) { - return base::ContainsValue(this->completed_tasks_, e); + return base::Contains(this->completed_tasks_, e); }); tasks_.push_back(base::MakeRefCounted<ClosureTask>(std::move(task)));
diff --git a/content/renderer/media/stream/media_stream_center.cc b/content/renderer/media/stream/media_stream_center.cc index 47b1d41..089451e 100644 --- a/content/renderer/media/stream/media_stream_center.cc +++ b/content/renderer/media/stream/media_stream_center.cc
@@ -14,12 +14,12 @@ #include "content/public/common/content_switches.h" #include "content/public/renderer/render_thread.h" #include "content/renderer/media/stream/processed_local_audio_source.h" -#include "content/renderer/media/stream/webaudio_media_stream_source.h" #include "content/renderer/media/webrtc_local_audio_source_provider.h" #include "media/base/sample_format.h" #include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_track.h" #include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_sink.h" #include "third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h" +#include "third_party/blink/public/platform/modules/mediastream/webaudio_media_stream_source.h" #include "third_party/blink/public/platform/web_media_constraints.h" #include "third_party/blink/public/platform/web_media_stream.h" #include "third_party/blink/public/platform/web_media_stream_source.h" @@ -52,7 +52,8 @@ // special case code isn't needed here. if (!media_stream_source && source.RequiresAudioConsumer()) { DVLOG(1) << "Creating WebAudio media stream source."; - media_stream_source = new WebAudioMediaStreamSource(&source, task_runner); + media_stream_source = + new blink::WebAudioMediaStreamSource(&source, task_runner); source.SetPlatformSource( base::WrapUnique(media_stream_source)); // Takes ownership.
diff --git a/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc b/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc index fb82b60..f763d0a 100644 --- a/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc +++ b/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc
@@ -63,7 +63,7 @@ template <typename T> static bool Contains(const std::vector<T>& vector, T value) { - return base::ContainsValue(vector, value); + return base::Contains(vector, value); } } // namespace
diff --git a/content/renderer/media/stream/user_media_processor.cc b/content/renderer/media/stream/user_media_processor.cc index ff20048..38128c4 100644 --- a/content/renderer/media/stream/user_media_processor.cc +++ b/content/renderer/media/stream/user_media_processor.cc
@@ -440,7 +440,7 @@ const blink::WebString& result_name) { // Check if we're waiting to be notified of this source. If not, then we'll // ignore the notification. - if (base::ContainsValue(sources_waiting_for_callback_, source)) + if (base::Contains(sources_waiting_for_callback_, source)) OnTrackStarted(source, result, result_name); }
diff --git a/content/renderer/media/webrtc/mock_peer_connection_impl.cc b/content/renderer/media/webrtc/mock_peer_connection_impl.cc index 353044a..d2882c8 100644 --- a/content/renderer/media/webrtc/mock_peer_connection_impl.cc +++ b/content/renderer/media/webrtc/mock_peer_connection_impl.cc
@@ -351,7 +351,7 @@ return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER); } for (const auto& stream_id : stream_ids) { - if (!base::ContainsValue(local_stream_ids_, stream_id)) { + if (!base::Contains(local_stream_ids_, stream_id)) { stream_label_ = stream_id; local_stream_ids_.push_back(stream_id); }
diff --git a/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc b/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc index 23be5bf..5f35909 100644 --- a/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc +++ b/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
@@ -440,7 +440,7 @@ base::AutoLock auto_lock(lock_); - if (!base::ContainsValue(decode_timestamps_, timestamp)) { + if (!base::Contains(decode_timestamps_, timestamp)) { DVLOG(2) << "Discarding frame with timestamp " << timestamp; return; }
diff --git a/content/renderer/media/webrtc/transmission_encoding_info_handler.cc b/content/renderer/media/webrtc/transmission_encoding_info_handler.cc index 76c29a8..21fe0dd4 100644 --- a/content/renderer/media/webrtc/transmission_encoding_info_handler.cc +++ b/content/renderer/media/webrtc/transmission_encoding_info_handler.cc
@@ -129,7 +129,7 @@ } else if (base::StartsWith(mime_type, audio_prefix, base::CompareCase::SENSITIVE)) { const std::string codec_name = mime_type.substr(strlen(audio_prefix)); - if (base::ContainsKey(supported_audio_codecs_, codec_name)) + if (base::Contains(supported_audio_codecs_, codec_name)) return codec_name; } return ""; @@ -167,7 +167,7 @@ info->supported = !codec_name.empty(); if (info->supported) { const bool is_hardware_accelerated = - base::ContainsKey(hardware_accelerated_video_codecs_, codec_name); + base::Contains(hardware_accelerated_video_codecs_, codec_name); info->smooth = is_hardware_accelerated || CanCpuEncodeSmoothly(video_config); info->power_efficient = is_hardware_accelerated;
diff --git a/content/renderer/media/webrtc/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc/webrtc_audio_device_impl.cc index 82f7916..9363e2d 100644 --- a/content/renderer/media/webrtc/webrtc_audio_device_impl.cc +++ b/content/renderer/media/webrtc/webrtc_audio_device_impl.cc
@@ -379,7 +379,7 @@ DCHECK(!capturer->device().id.empty()); base::AutoLock auto_lock(lock_); - DCHECK(!base::ContainsValue(capturers_, capturer)); + DCHECK(!base::Contains(capturers_, capturer)); capturers_.push_back(capturer); capturer->SetOutputDeviceForAec(output_device_id_for_aec_); } @@ -398,7 +398,7 @@ DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_); DCHECK(sink); base::AutoLock auto_lock(lock_); - DCHECK(!base::ContainsValue(playout_sinks_, sink)); + DCHECK(!base::Contains(playout_sinks_, sink)); playout_sinks_.push_back(sink); }
diff --git a/content/renderer/media/webrtc/webrtc_audio_renderer.cc b/content/renderer/media/webrtc/webrtc_audio_renderer.cc index 32a1255..fbc1090 100644 --- a/content/renderer/media/webrtc/webrtc_audio_renderer.cc +++ b/content/renderer/media/webrtc/webrtc_audio_renderer.cc
@@ -546,7 +546,7 @@ DCHECK(state->playing()); // Look up or add the |source| to the map. PlayingStates& array = source_playing_states_[source]; - if (base::ContainsValue(array, state)) + if (base::Contains(array, state)) return false; array.push_back(state);
diff --git a/content/renderer/media/webrtc/webrtc_audio_sink.cc b/content/renderer/media/webrtc/webrtc_audio_sink.cc index 8924c75..2a4e5d2 100644 --- a/content/renderer/media/webrtc/webrtc_audio_sink.cc +++ b/content/renderer/media/webrtc/webrtc_audio_sink.cc
@@ -152,7 +152,7 @@ signaling_task_runner_->RunsTasksInCurrentSequence()); DCHECK(sink); base::AutoLock auto_lock(lock_); - DCHECK(!base::ContainsValue(sinks_, sink)); + DCHECK(!base::Contains(sinks_, sink)); sinks_.push_back(sink); }
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 7b982df..21bf76f 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -4785,7 +4785,6 @@ UpdateEncoding(frame_, frame_->View()->PageEncoding().Utf8()); // Reset warning state that prevents log spam. - certificate_warning_origins_.clear(); tls_version_warning_origins_.clear(); } @@ -5434,7 +5433,7 @@ void RenderFrameImpl::ReportLegacyTLSVersion(const blink::WebURL& url) { url::Origin origin = url::Origin::Create(GURL(url)); // To prevent log spam, only log the message once per origin. - if (base::ContainsKey(tls_version_warning_origins_, origin)) + if (base::Contains(tls_version_warning_origins_, origin)) return; size_t num_warnings = tls_version_warning_origins_.size();
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index c3c439b..32b80ee3 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -1730,10 +1730,6 @@ blink::mojom::ClipboardHostPtr clipboard_host_; #endif - // The origins for which a legacy certificate warning has been printed. The - // size of this set is capped, after which no more warnings are printed. - std::set<url::Origin> certificate_warning_origins_; - // The origins for which a legacy TLS version warning has been printed. The // size of this set is capped, after which no more warnings are printed. std::set<url::Origin> tls_version_warning_origins_;
diff --git a/content/renderer/worker/worker_thread_registry.cc b/content/renderer/worker/worker_thread_registry.cc index 97dae12..b77257a2 100644 --- a/content/renderer/worker/worker_thread_registry.cc +++ b/content/renderer/worker/worker_thread_registry.cc
@@ -122,7 +122,7 @@ base::TaskRunner* WorkerThreadRegistry::GetTaskRunnerFor(int worker_id) { base::AutoLock locker(task_runner_map_lock_); - return base::ContainsKey(task_runner_map_, worker_id) + return base::Contains(task_runner_map_, worker_id) ? task_runner_map_[worker_id] : task_runner_for_dead_worker_.get(); }
diff --git a/content/shell/browser/web_test/blink_test_controller.cc b/content/shell/browser/web_test/blink_test_controller.cc index 985690a..7943a8a 100644 --- a/content/shell/browser/web_test/blink_test_controller.cc +++ b/content/shell/browser/web_test/blink_test_controller.cc
@@ -966,7 +966,7 @@ // Is this the 1st time this renderer contains parts of the main test window? if (main_window && - !base::ContainsKey(main_window_render_process_hosts_, process_host)) { + !base::Contains(main_window_render_process_hosts_, process_host)) { main_window_render_process_hosts_.insert(process_host); // Make sure the new renderer process_host has a test configuration shared
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc index 5c2baad4..53aed265 100644 --- a/content/shell/test_runner/test_runner.cc +++ b/content/shell/test_runner/test_runner.cc
@@ -1820,7 +1820,7 @@ if (!IsFramePartOfMainTestWindow(frame)) return; - if (!base::ContainsValue(loading_frames_, frame)) + if (!base::Contains(loading_frames_, frame)) return; DCHECK(web_test_runtime_flags_.have_loading_frame());
diff --git a/content/test/mock_clipboard_host.cc b/content/test/mock_clipboard_host.cc index fab0d96..dfa82b1 100644 --- a/content/test/mock_clipboard_host.cc +++ b/content/test/mock_clipboard_host.cc
@@ -43,7 +43,7 @@ if (!image_.isNull()) types.push_back(base::UTF8ToUTF16("image/png")); for (auto& it : custom_data_) { - CHECK(!base::ContainsValue(types, it.first)); + CHECK(!base::Contains(types, it.first)); types.push_back(it.first); } std::move(callback).Run(types, false);
diff --git a/content/test/web_contents_observer_sanity_checker.cc b/content/test/web_contents_observer_sanity_checker.cc index f6d19ee..3e01d78 100644 --- a/content/test/web_contents_observer_sanity_checker.cc +++ b/content/test/web_contents_observer_sanity_checker.cc
@@ -230,8 +230,8 @@ // If ReadyToCommitNavigation was dispatched, verify that the // |navigation_handle| has the same RenderFrameHost at this time as the one // returned at ReadyToCommitNavigation. - if (base::ContainsKey(ready_to_commit_hosts_, - navigation_handle->GetNavigationId())) { + if (base::Contains(ready_to_commit_hosts_, + navigation_handle->GetNavigationId())) { CHECK_EQ(ready_to_commit_hosts_[navigation_handle->GetNavigationId()], navigation_handle->GetRenderFrameHost()); ready_to_commit_hosts_.erase(navigation_handle->GetNavigationId()); @@ -283,7 +283,7 @@ const MediaPlayerInfo& media_info, const MediaPlayerId& id) { CHECK(!web_contents_destroyed_); - CHECK(!base::ContainsValue(active_media_players_, id)); + CHECK(!base::Contains(active_media_players_, id)); active_media_players_.push_back(id); } @@ -292,7 +292,7 @@ const MediaPlayerId& id, WebContentsObserver::MediaStoppedReason reason) { CHECK(!web_contents_destroyed_); - CHECK(base::ContainsValue(active_media_players_, id)); + CHECK(base::Contains(active_media_players_, id)); base::Erase(active_media_players_, id); }
diff --git a/device/bluetooth/bluetooth_adapter_factory_wrapper.cc b/device/bluetooth/bluetooth_adapter_factory_wrapper.cc index ca14603..26f264d 100644 --- a/device/bluetooth/bluetooth_adapter_factory_wrapper.cc +++ b/device/bluetooth/bluetooth_adapter_factory_wrapper.cc
@@ -107,7 +107,7 @@ BluetoothAdapter::Observer* observer) { DCHECK(thread_checker_.CalledOnValidThread()); - return base::ContainsKey(adapter_observers_, observer); + return base::Contains(adapter_observers_, observer); } void BluetoothAdapterFactoryWrapper::AddAdapterObserver(
diff --git a/device/bluetooth/bluetooth_adapter_winrt.cc b/device/bluetooth/bluetooth_adapter_winrt.cc index 48bd0eda..fbca322c 100644 --- a/device/bluetooth/bluetooth_adapter_winrt.cc +++ b/device/bluetooth/bluetooth_adapter_winrt.cc
@@ -1298,7 +1298,7 @@ void BluetoothAdapterWinrt::OnRegisterAdvertisement( BluetoothAdvertisement* advertisement, const CreateAdvertisementCallback& callback) { - DCHECK(base::ContainsValue(pending_advertisements_, advertisement)); + DCHECK(base::Contains(pending_advertisements_, advertisement)); auto wrapped_advertisement = base::WrapRefCounted(advertisement); base::Erase(pending_advertisements_, advertisement); callback.Run(std::move(wrapped_advertisement));
diff --git a/device/bluetooth/bluetooth_device_android.cc b/device/bluetooth/bluetooth_device_android.cc index 4ef8ad8..6ec4c86 100644 --- a/device/bluetooth/bluetooth_device_android.cc +++ b/device/bluetooth/bluetooth_device_android.cc
@@ -249,7 +249,7 @@ std::string instance_id_string = base::android::ConvertJavaStringToUTF8(env, instance_id); - if (base::ContainsKey(gatt_services_, instance_id_string)) + if (base::Contains(gatt_services_, instance_id_string)) return; std::unique_ptr<BluetoothRemoteGattServiceAndroid> service =
diff --git a/device/bluetooth/bluetooth_device_unittest.cc b/device/bluetooth/bluetooth_device_unittest.cc index e4fdd00..529eb2f 100644 --- a/device/bluetooth/bluetooth_device_unittest.cc +++ b/device/bluetooth/bluetooth_device_unittest.cc
@@ -287,9 +287,8 @@ EXPECT_EQ(base::UTF8ToUTF16(kTestDeviceName), device->GetNameForDisplay()); EXPECT_FALSE(device->IsPaired()); UUIDSet uuids = device->GetUUIDs(); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID(kTestUUIDGenericAccess))); - EXPECT_TRUE( - base::ContainsKey(uuids, BluetoothUUID(kTestUUIDGenericAttribute))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID(kTestUUIDGenericAccess))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID(kTestUUIDGenericAttribute))); } // Verifies that the device name can be populated by later advertisement
diff --git a/device/bluetooth/bluetooth_device_win_unittest.cc b/device/bluetooth/bluetooth_device_win_unittest.cc index 30e8cd2..025092d 100644 --- a/device/bluetooth/bluetooth_device_win_unittest.cc +++ b/device/bluetooth/bluetooth_device_win_unittest.cc
@@ -88,8 +88,8 @@ BluetoothDevice::UUIDSet uuids = device_->GetUUIDs(); EXPECT_EQ(2u, uuids.size()); - EXPECT_TRUE(base::ContainsKey(uuids, kTestAudioSdpUuid)); - EXPECT_TRUE(base::ContainsKey(uuids, kTestVideoSdpUuid)); + EXPECT_TRUE(base::Contains(uuids, kTestAudioSdpUuid)); + EXPECT_TRUE(base::Contains(uuids, kTestVideoSdpUuid)); uuids = empty_device_->GetUUIDs(); EXPECT_EQ(0u, uuids.size());
diff --git a/device/bluetooth/bluetooth_gatt_discoverer_winrt.cc b/device/bluetooth/bluetooth_gatt_discoverer_winrt.cc index 14fd46a..ebd294e 100644 --- a/device/bluetooth/bluetooth_gatt_discoverer_winrt.cc +++ b/device/bluetooth/bluetooth_gatt_discoverer_winrt.cc
@@ -303,8 +303,8 @@ return; } - DCHECK(!base::ContainsKey(service_to_characteristics_map_, - service_attribute_handle)); + DCHECK(!base::Contains(service_to_characteristics_map_, + service_attribute_handle)); auto& characteristics_list = service_to_characteristics_map_[service_attribute_handle]; if (!GetAsVector(characteristics.Get(), &characteristics_list)) { @@ -375,8 +375,8 @@ return; } - DCHECK(!base::ContainsKey(characteristic_to_descriptors_map_, - characteristic_attribute_handle)); + DCHECK(!base::Contains(characteristic_to_descriptors_map_, + characteristic_attribute_handle)); if (!GetAsVector(descriptors.Get(), &characteristic_to_descriptors_map_ [characteristic_attribute_handle])) { std::move(callback_).Run(false);
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc index 0e76e676..50415ac 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc
@@ -236,7 +236,7 @@ std::string instanceIdString = base::android::ConvertJavaStringToUTF8(env, instanceId); - DCHECK(!base::ContainsKey(descriptors_, instanceIdString)); + DCHECK(!base::Contains(descriptors_, instanceIdString)); AddDescriptor(BluetoothRemoteGattDescriptorAndroid::Create( instanceIdString, bluetooth_gatt_descriptor_wrapper, chrome_bluetooth_device));
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_android.cc b/device/bluetooth/bluetooth_remote_gatt_service_android.cc index a8e3957d..bf31b68 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_android.cc +++ b/device/bluetooth/bluetooth_remote_gatt_service_android.cc
@@ -176,7 +176,7 @@ std::string instance_id_string = base::android::ConvertJavaStringToUTF8(env, instance_id); - DCHECK(!base::ContainsKey(characteristics_, instance_id_string)); + DCHECK(!base::Contains(characteristics_, instance_id_string)); AddCharacteristic(BluetoothRemoteGattCharacteristicAndroid::Create( adapter_, this, instance_id_string, bluetooth_gatt_characteristic_wrapper, chrome_bluetooth_device));
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_win.cc b/device/bluetooth/bluetooth_remote_gatt_service_win.cc index 24ab750..8d0b5b9 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_win.cc +++ b/device/bluetooth/bluetooth_remote_gatt_service_win.cc
@@ -84,7 +84,7 @@ void BluetoothRemoteGattServiceWin::GattCharacteristicDiscoveryComplete( BluetoothRemoteGattCharacteristicWin* characteristic) { DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); - DCHECK(base::ContainsKey(characteristics_, characteristic->GetIdentifier())); + DCHECK(base::Contains(characteristics_, characteristic->GetIdentifier())); discovery_completed_included_characteristics_.insert( characteristic->GetIdentifier()); @@ -227,7 +227,7 @@ // characteristic's destructor. This will ensure that any call to // GetCharacteristics() won't contain an entry corresponding to |identifier|. // Note: `characteristics_.erase(identifier);` would not guarantee this. - DCHECK(base::ContainsKey(characteristics_, identifier)); + DCHECK(base::Contains(characteristics_, identifier)); auto iter = characteristics_.find(identifier); auto pair = std::move(*iter); characteristics_.erase(iter);
diff --git a/device/bluetooth/bluez/bluetooth_adapter_bluez.cc b/device/bluetooth/bluez/bluetooth_adapter_bluez.cc index 030b34eb..55dd9dd 100644 --- a/device/bluetooth/bluez/bluetooth_adapter_bluez.cc +++ b/device/bluetooth/bluez/bluetooth_adapter_bluez.cc
@@ -449,7 +449,7 @@ UUIDSet intersection; for (const BluetoothUUID& uuid : filter_uuids) { - if (base::ContainsKey(device_uuids, uuid)) { + if (base::Contains(device_uuids, uuid)) { intersection.insert(uuid); } }
diff --git a/device/bluetooth/bluez/bluetooth_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_bluez_unittest.cc index 9773d8e..b35e200 100644 --- a/device/bluetooth/bluez/bluetooth_bluez_unittest.cc +++ b/device/bluetooth/bluez/bluetooth_bluez_unittest.cc
@@ -1441,7 +1441,7 @@ EXPECT_EQ(-60, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); std::vector<std::string> uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1000")); discovery_sessions_[0]->Stop( base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)), @@ -1569,8 +1569,8 @@ EXPECT_EQ(-65, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); auto uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1000")); - EXPECT_TRUE(base::ContainsValue(uuids, "1002")); + EXPECT_TRUE(base::Contains(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1002")); discovery_sessions_[0]->Stop( base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)), @@ -1674,7 +1674,7 @@ EXPECT_EQ(-65, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); auto uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1002")); + EXPECT_TRUE(base::Contains(uuids, "1002")); discovery_sessions_[0]->Stop( base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)), @@ -1752,7 +1752,7 @@ EXPECT_EQ(-60, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); std::vector<std::string> uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1000")); discovery_sessions_[0]->Stop( base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)), @@ -1830,26 +1830,26 @@ EXPECT_EQ(-85, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); std::vector<std::string> uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1000")); } else if (i == 1) { auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter(); EXPECT_EQ("le", *filter->transport); EXPECT_EQ(-85, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); std::vector<std::string> uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1000")); - EXPECT_TRUE(base::ContainsValue(uuids, "1001")); - EXPECT_TRUE(base::ContainsValue(uuids, "1020")); + EXPECT_TRUE(base::Contains(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1001")); + EXPECT_TRUE(base::Contains(uuids, "1020")); } else if (i == 2) { auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter(); EXPECT_EQ("le", *filter->transport); EXPECT_EQ(-85, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); std::vector<std::string> uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1000")); - EXPECT_TRUE(base::ContainsValue(uuids, "1001")); - EXPECT_TRUE(base::ContainsValue(uuids, "1003")); - EXPECT_TRUE(base::ContainsValue(uuids, "1020")); + EXPECT_TRUE(base::Contains(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1001")); + EXPECT_TRUE(base::Contains(uuids, "1003")); + EXPECT_TRUE(base::Contains(uuids, "1020")); } } @@ -1875,10 +1875,10 @@ EXPECT_EQ(nullptr, filter->pathloss.get()); std::vector<std::string> uuids = *filter->uuids; EXPECT_EQ(3UL, uuids.size()); - EXPECT_FALSE(base::ContainsValue(uuids, "1000")); - EXPECT_TRUE(base::ContainsValue(uuids, "1001")); - EXPECT_TRUE(base::ContainsValue(uuids, "1003")); - EXPECT_TRUE(base::ContainsValue(uuids, "1020")); + EXPECT_FALSE(base::Contains(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1001")); + EXPECT_TRUE(base::Contains(uuids, "1003")); + EXPECT_TRUE(base::Contains(uuids, "1020")); } else if (i == 1) { auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter(); EXPECT_EQ("le", *filter->transport); @@ -1886,10 +1886,10 @@ EXPECT_EQ(nullptr, filter->pathloss.get()); std::vector<std::string> uuids = *filter->uuids; EXPECT_EQ(2UL, uuids.size()); - EXPECT_FALSE(base::ContainsValue(uuids, "1000")); - EXPECT_FALSE(base::ContainsValue(uuids, "1001")); - EXPECT_TRUE(base::ContainsValue(uuids, "1003")); - EXPECT_TRUE(base::ContainsValue(uuids, "1020")); + EXPECT_FALSE(base::Contains(uuids, "1000")); + EXPECT_FALSE(base::Contains(uuids, "1001")); + EXPECT_TRUE(base::Contains(uuids, "1003")); + EXPECT_TRUE(base::Contains(uuids, "1020")); } else if (i == 2) { auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter(); EXPECT_EQ("le", *filter->transport); @@ -1952,19 +1952,19 @@ EXPECT_EQ(-85, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); std::vector<std::string> uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1000")); - EXPECT_TRUE(base::ContainsValue(uuids, "1003")); - EXPECT_TRUE(base::ContainsValue(uuids, "1020")); + EXPECT_TRUE(base::Contains(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1003")); + EXPECT_TRUE(base::Contains(uuids, "1020")); } else if (i == 1 || i == 2) { auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter(); EXPECT_EQ("le", *filter->transport); EXPECT_EQ(-85, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); std::vector<std::string> uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1000")); - EXPECT_TRUE(base::ContainsValue(uuids, "1001")); - EXPECT_TRUE(base::ContainsValue(uuids, "1003")); - EXPECT_TRUE(base::ContainsValue(uuids, "1020")); + EXPECT_TRUE(base::Contains(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1001")); + EXPECT_TRUE(base::Contains(uuids, "1003")); + EXPECT_TRUE(base::Contains(uuids, "1020")); } } @@ -2032,7 +2032,7 @@ EXPECT_EQ(-15, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); std::vector<std::string> uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1000")); df = new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE); df->SetRSSI(-60); @@ -2053,9 +2053,9 @@ EXPECT_EQ(-60, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1000")); - EXPECT_TRUE(base::ContainsValue(uuids, "1001")); - EXPECT_TRUE(base::ContainsValue(uuids, "1020")); + EXPECT_TRUE(base::Contains(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1001")); + EXPECT_TRUE(base::Contains(uuids, "1020")); BluetoothDiscoveryFilter* df3 = new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_CLASSIC); @@ -2077,10 +2077,10 @@ EXPECT_EQ(-65, *filter->rssi); EXPECT_EQ(nullptr, filter->pathloss.get()); uuids = *filter->uuids; - EXPECT_TRUE(base::ContainsValue(uuids, "1000")); - EXPECT_TRUE(base::ContainsValue(uuids, "1001")); - EXPECT_TRUE(base::ContainsValue(uuids, "1003")); - EXPECT_TRUE(base::ContainsValue(uuids, "1020")); + EXPECT_TRUE(base::Contains(uuids, "1000")); + EXPECT_TRUE(base::Contains(uuids, "1001")); + EXPECT_TRUE(base::Contains(uuids, "1003")); + EXPECT_TRUE(base::Contains(uuids, "1020")); // start additionally classic scan adapter_->StartDiscoverySession( @@ -2133,8 +2133,8 @@ BluetoothDevice::UUIDSet uuids = devices[idx]->GetUUIDs(); EXPECT_EQ(2U, uuids.size()); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1800"))); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1801"))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID("1800"))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID("1801"))); EXPECT_EQ(BluetoothDevice::VENDOR_ID_USB, devices[idx]->GetVendorIDSource()); EXPECT_EQ(0x05ac, devices[idx]->GetVendorID()); @@ -2504,8 +2504,8 @@ BluetoothDevice::UUIDSet uuids = devices[idx]->GetUUIDs(); ASSERT_EQ(2U, uuids.size()); - ASSERT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1800"))); - ASSERT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1801"))); + ASSERT_TRUE(base::Contains(uuids, BluetoothUUID("1800"))); + ASSERT_TRUE(base::Contains(uuids, BluetoothUUID("1801"))); // Install an observer; expect the DeviceChanged method to be called when // we change the class of the device. @@ -2530,11 +2530,11 @@ // Fetching the value should give the new one. uuids = devices[idx]->GetUUIDs(); EXPECT_EQ(5U, uuids.size()); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1800"))); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1801"))); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("110c"))); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("110e"))); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("110a"))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID("1800"))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID("1801"))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID("110c"))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID("110e"))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID("110a"))); } TEST_F(BluetoothBlueZTest, DeviceInquiryRSSIInvalidated) { @@ -2771,7 +2771,7 @@ // Verify is a HID device and is not connectable. BluetoothDevice::UUIDSet uuids = device->GetUUIDs(); EXPECT_EQ(1U, uuids.size()); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1124"))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID("1124"))); EXPECT_FALSE(device->IsConnectable()); } @@ -3074,7 +3074,7 @@ // Verify is a HID device and is connectable. BluetoothDevice::UUIDSet uuids = device->GetUUIDs(); EXPECT_EQ(1U, uuids.size()); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1124"))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID("1124"))); EXPECT_TRUE(device->IsConnectable()); // Make sure the trusted property has been set to true. @@ -3131,7 +3131,7 @@ // Verify is a HID device and is connectable. BluetoothDevice::UUIDSet uuids = device->GetUUIDs(); EXPECT_EQ(1U, uuids.size()); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1124"))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID("1124"))); EXPECT_TRUE(device->IsConnectable()); // Make sure the trusted property has been set to true. @@ -3208,7 +3208,7 @@ // Verify is a HID device. BluetoothDevice::UUIDSet uuids = device->GetUUIDs(); EXPECT_EQ(1U, uuids.size()); - EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1124"))); + EXPECT_TRUE(base::Contains(uuids, BluetoothUUID("1124"))); // And usually not connectable. EXPECT_FALSE(device->IsConnectable());
diff --git a/device/bluetooth/chromeos/bluetooth_utils.cc b/device/bluetooth/chromeos/bluetooth_utils.cc index 8b9098c9..69194dd4e 100644 --- a/device/bluetooth/chromeos/bluetooth_utils.cc +++ b/device/bluetooth/chromeos/bluetooth_utils.cc
@@ -77,10 +77,10 @@ // For LE devices, check the service UUID to determine if it supports HID // or second factor authenticator (security key). case BLUETOOTH_TRANSPORT_LE: - if (base::ContainsKey(device->GetUUIDs(), - device::BluetoothUUID(kHIDServiceUUID)) || - base::ContainsKey(device->GetUUIDs(), - device::BluetoothUUID(kSecurityKeyServiceUUID))) { + if (base::Contains(device->GetUUIDs(), + device::BluetoothUUID(kHIDServiceUUID)) || + base::Contains(device->GetUUIDs(), + device::BluetoothUUID(kSecurityKeyServiceUUID))) { result.push_back(device); } break;
diff --git a/device/bluetooth/dbus/fake_bluetooth_device_client.cc b/device/bluetooth/dbus/fake_bluetooth_device_client.cc index 1d2c887f..d97dec0 100644 --- a/device/bluetooth/dbus/fake_bluetooth_device_client.cc +++ b/device/bluetooth/dbus/fake_bluetooth_device_client.cc
@@ -711,7 +711,7 @@ void FakeBluetoothDeviceClient::CreateDevice( const dbus::ObjectPath& adapter_path, const dbus::ObjectPath& device_path) { - if (base::ContainsValue(device_list_, device_path)) + if (base::Contains(device_list_, device_path)) return; std::unique_ptr<Properties> properties( @@ -846,7 +846,7 @@ const dbus::ObjectPath& adapter_path, const IncomingDeviceProperties& props) { dbus::ObjectPath device_path(props.device_path); - if (base::ContainsValue(device_list_, device_path)) + if (base::Contains(device_list_, device_path)) return; std::unique_ptr<Properties> properties( @@ -1902,7 +1902,7 @@ base::Base64Encode(base::RandBytesAsString(10), &id); base::RemoveChars(id, "+/=", &id); device_path = dbus::ObjectPath(adapter_path.value() + "/dev" + id); - } while (base::ContainsValue(device_list_, device_path)); + } while (base::Contains(device_list_, device_path)); std::unique_ptr<Properties> properties( new Properties(base::Bind(&FakeBluetoothDeviceClient::OnPropertyChanged,
diff --git a/device/bluetooth/dbus/fake_bluetooth_media_client.cc b/device/bluetooth/dbus/fake_bluetooth_media_client.cc index d33f380..e124b6bf 100644 --- a/device/bluetooth/dbus/fake_bluetooth_media_client.cc +++ b/device/bluetooth/dbus/fake_bluetooth_media_client.cc
@@ -80,7 +80,7 @@ // TODO(mcchou): Come up with some corresponding actions. VLOG(1) << "UnregisterEndpoint: " << endpoint_path.value(); - if (!base::ContainsKey(endpoints_, endpoint_path)) { + if (!base::Contains(endpoints_, endpoint_path)) { error_callback.Run(kFailedError, "Unknown media endpoint"); return; } @@ -130,7 +130,7 @@ bool FakeBluetoothMediaClient::IsRegistered( const dbus::ObjectPath& endpoint_path) { - return base::ContainsKey(endpoints_, endpoint_path); + return base::Contains(endpoints_, endpoint_path); } } // namespace bluez
diff --git a/docs/testing/writing_js_unit_tests.md b/docs/testing/writing_js_unit_tests.md new file mode 100644 index 0000000..50ad875 --- /dev/null +++ b/docs/testing/writing_js_unit_tests.md
@@ -0,0 +1,378 @@ +<!--* freshness: { owner: 'olsen' reviewed: '2019-06-07' } *--> + +<!-- Originally published June 7, 2019 --> + +# Writing a JavaScript unit test + +You have written some JS code and put it somewhere in chromium src. Now you want +to write unit tests for it. + +[TOC] + +## Testing JS code with no dependencies + +Let's say you have written a file `awesome.js`. Next you will write your unit +tests in a file in the same directory called `awesome_test.unitjs`. The +`.unitjs` suffix simply means a javascript unit test. (There are a couple of +other suffix options, but .unitjs is the most common, and it will do for most +purposes). + +### Writing the test itself + +Here is an example to show how your test might look: + +```js +/** Tests for awesome.js */ + +GEN_INCLUDE([ + 'awesome.js' // Include the file under test. +]); + +function AwesomeUnitTest() {} + +AwesomeUnitTest.prototype = { + __proto__: testing.Test.prototype +}; + +const EXPECTED_AWESOME_NUMBER = 1e6; + +TEST_F(AwesomeUnitTest, 'HowAwesomeExactly', function () { + // Some asserts to make sure the file under test is working as expected. + assertEquals(EXPECTED_AWESOME_NUMBER, awesome.find_awesome_number(), 'If this fails, contact Larry'); +}); +``` + +Since ECMAScript 6, there is an alternative but equivalent syntax that uses the +class keyword instead of prototype. Codesearch shows that existing unitjs tests +use either syntax. + +### Writing the BUILD rules + +Next you need to add a +[js2gtest](https://cs.chromium.org/chromium/src/chrome/test/base/js2gtest.gni) +rule in the same package. Let's say it's called `package_one`. Here is an +example to show how your BUILD rules might look: + +```build +js2gtest("package_one_unitjs_tests") { + test_type = "unit" + sources = [ + "awesome_test.unitjs", + # ... for simplicity, put all .unitjs files in this package into this one rule. + ] + gen_include_files = [ + "awesome.js", + ] +} + +source_set("unit_tests") { + testonly = true + deps = [":package_one_unitjs_tests"] +} +``` + +And finally, you will have to modify the huge `//chrome/test:unit_tests` build +rule to depend (directly or indirectly) on your new `//package_one:unit_tests` +target. + +Once this is done, you can build and run the tests like normal: + +```shell +chromium/src$ out/Default/unit_tests --gtest_filter="AwesomeUnitTest*" +``` + +## Testing JS code which depends on another library + +You may have some other way that the dependencies are being correctly included +in production. However, it will probably be simplest not to try and make the +`js2gtest` rule recognize the dependency management system you are using, but +instead just declare all JS dependencies explicitly when writing the test. The +way to do this is by adding the needed JS source files to both `GEN_INCLUDE` in +the test and `gen_include_files` in the BUILD rule. These files will be included +in the order specified in the JS file. These files that are included can also +have their own calls to GEN_INCLUDE to transitively include other files, if +needed - these would then all need to be listed in the gen_include_files list in +the BUILD rule. + +### Writing a test which depends on another library + +```js {highlight="lines:4"} +/** Tests for awesome.js */ + +GEN_INCLUDE([ + '//some/dependency.js', + 'awesome.js', +]); + +function AwesomeUnitTest() {} +// ... etc ... +``` + +### Writing the BUILD rule for a test that depends on another library + +```build {highlight="lines:7"} +js2gtest("package_one_unitjs_tests") { + test_type = "unit" + sources = [ + "awesome_test.unitjs", + ] + gen_include_files = [ + "//some/dependency.js", + "awesome.js", + ] +} +# ... etc ... +``` + +## Testing JS code which depends on the browser / the DOM {#browser-dep} + +The tests above are run using a V8 interpreter. However, they are not run from +within a browser. That means all JS language features are available, but no +browser features are available. Specifically, the browser context (the global +object called `window`) is left undefined, and anything to do with the DOM, the +UI, rendering, parsing, event handling, mouse clicks, HTML, XML, SVG, canvas, +etc is not supported. It may be that you need some of this - perhaps you are +trying to write and test a web-based UI, or perhaps your code just expects an +XML parser to be available. + +If you are creating an web-based UI, what you are now writing is called a +`webui` test. Ideally, you should read documentation specifically for writing +and testing web UI components. + +FIXME: Is there any documentation for writing and testing web UI components? + +If on the other hand, you are writing some JS functionality that just happens to +use a feature that is part of the browser, and not the language (such as the XML +parser), you should follow the instructions in this section. The current +best-practice is to write your unit test as before, but to declare it as a +`webui` test and add it to the `browser_tests` build rule. Ideally there would +be a different category for unit tests that don't have any UI and so aren't +webui, but simply need a particular browser feature, but using `webui` works for +now. + +### Changes to your test to make it a webui test + +```js {highlight="lines:4,7"} +AwesomeUnitTest.prototype = { + __proto__: testing.Test.prototype, + + browsePreload: DUMMY_URL, + + // No need to run these checks unless you are testing an actual user interface. + runAccessibilityChecks: false, +}; +``` + +### Changes to your build rule to make it a webui test + +```build {highlight="lines:2,9,12"} +js2gtest("package_one_unitjs_tests") { + test_type = "webui" + sources = [ + "awesome_test.unitjs", + ] + gen_include_files = [ + "awesome.js", + ] + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] +} + +source_set("browser_tests") { + testonly = true + deps = [":package_one_unitjs_tests"] +} +``` + +FIXME: It might be nice if "HAS_OUT_OF_PROC_TEST_RUNNER" was automatically +inferred from the test type. + +And the final change is to remove your test from the `//chrome/test:unit_tests` +build rule, and add it instead to the `//chrome/test:browser_tests`. As you +would expect, you now run your test like so: + +```shell +chromium/src$ out/Default/browser_tests --gtest_filter="AwesomeUnitTest*" +``` + +And now the browser context and global `window` object should be available in +your test. + +Note: If your test is declared as a `unit` test, it must be part of +`//chrome/test:unit_tests`, and if your test is declared as a `webui` test, it +must be part of `//chrome/test:browser_tests`. If your test is included in the +wrong build rule, it will not compile, since it will be missing some necessary +dependencies. + +## Troubleshooting + +### js2gtest.js: Error reading file + +Perhaps one of the files you are trying to read does not exist, has the wrong +name, or has not been properly declared in the list of `gen_include_files` in +`BUILD.gn`. The file that could not be found or read should be part of the error +message, but if for some reason it is not clear, you can narrow it down by +removing files from the `GEN_INCLUDE` directive one by one. + +### ReferenceError: window is not defined + +Or: document is not defined, DOMParser is not defined, frames is not defined, +alert is not defined... + +This sounds like your unit test depends on some functionality that is part of +the browser, and not part of the JS language itself. See the +[section about depending on the browser](#browser-dep) + +### Test passes locally but fails on the commit queue + +This is probably due to a dependency not being properly declared - for instance, +you have a file in the `GEN_INCLUDE` directive, that is not included in the list +of `gen_include_files` in `BUILD.gn`, When run locally, the test may be able to +find the appropriate file, but the swarming bots that run the submit queue will +not necessarily be able to find files that have not been explicitly declared as +dependencies. + +You can try running your test locally but in a more isolated way, so as to +reproduce the problem locally. Something like: + +```shell +chromium/src$ tools/mb/mb.py run //out/Default browser_tests -- --gtest_filter="AwesomeUnitTest*" +``` + +### Duplicate output file {#duplicate} + +The `js2gtest` rule copies various JS files to testdata, where they are read as +data when the test is run. This causes problems if two different js2gtest rule +instances both try to copy the same file to the same place in testdata. Having +two rules both copy the same source file to the same destination is a build +error - every file must be written only once. + +It should be safe to have multiple js2gtest rules which have files in common in +the `gen_include_files` list, since these files are not copied. But, it will +cause a build error to have multiple js2gtest rules which have files in common +in either the `sources` list or the `extra_js_files` list, since all of these +files are copied to testdata. + +To avoid this, only create one js2gtest rule per package which has all the +necessary sources in, and to include files from outside the package, use +gen_include_files and not extra_js_files. + +The duplicate output file build error could look something like this: + +``` +ERROR at //chrome/test/base/js2gtest.gni: Duplicate output file. + copy(copy_target_name) { + ^----------------------- +Two or more targets generate the same output: + test_data/ui/webui/resources/js/cr.js +``` + +If you encounter such a build error and fix it, you could still end up with +warnings on subsequent builds - something like the following: + +``` +warning: multiple rules generate test_data/ui/webui/resources/js/cr.js. builds involving this target will not be correct; continuing anyway [-w dupbuild=warn] +``` + +Get rid of this warning by doing a clean build. + +## Advanced topics + +### GEN_INCLUDE alternative + +There is an alternative to `gen_include_files` that is called `extra_js_files`. +These are JS files that are not read during compilation, but are loaded at +runtime. Because they are not read at compile time, they can contain no +directives to be executed at compile time. + +Compare this to `gen_include_files` which are both read at compile time, and +included at runtime. This means they support compile time directives like `GEN` +and `GEN_INCLUDE` which can generate code and include further files - and those +further files could have their own directives, and so on. + +Whether or not compile time directives are needed or used, these two rules work +differently - extra_js_files copies source files into the `testdata` directory, +but gen_include_files leaves the source files where they are. + +Warning: Avoid using `extra_js_files` because all files listed there are copied +into the testdata directory, which can easily lead to the "duplicate output +file" build error described in the [previous section](#duplicate). + +However, if you find you need to use extra_js_files instead of +gen_include_files, this is how it is done: + +#### Changes to your test to make it use extra_js_files + +```js {highlight="lines:4-7"} +AwesomeUnitTest.prototype = { + __proto__: testing.Test.prototype, + + extraLibraries: [ + "awesome.js", + "//some/dependency.js", + ], +}; +``` + +#### Changes to your build rule to make it use extra_js_files + +```build {highlight="lines:6"} +js2gtest("package_one_unitjs_tests") { + test_type = "unit" + sources = [ + "awesome_test.unitjs", + ] + extra_js_files = [ + "awesome.js", + "//some/dependency.js" + ] +} +``` + +### Including custom C++ code in the generated C++ test + +There are a number of ways to add to the C++ code that is generated by your +.unitjs file. + +Calling +[GEN(code)](https://cs.chromium.org/chromium/src/chrome/test/base/js2gtest.js?q=function.GEN%5C%28) +in your .unitjs file will cause the C++ code to be included verbatim in the +generated C++ test. + +The function `TEST_F` (or alternative form `TEST_F_WITH_PREAMBLE`) can take a +[preamble](https://cs.chromium.org/chromium/src/chrome/test/base/js2gtest.js?q=preamble) +argument - the preamble is extra C++ code that is included in the generated C++ +test, immediately before the code which makes the interpreter run the JS part of +the test. + +You can define functions on your JS Test prototype, `testGenPreamble()` and +`testGenPostamble()`. The testGenPreamble function is used to generate code that +is included immediately before the JS part of your test, and the +testGenPostamble function is used to generate code that goes immediately after - +so you could for example put an "#ifdef" in the preamble and an "#endif" in the +postamble. If you define these functions, they should call GEN to output the +necessary C++ code. + +Since these are relatively complex to use, it may help you to codesearch for +examples. Here are some useful examples: + +[oobe_webui_browsertest.js](https://cs.chromium.org/chromium/src/chrome/test/data/chromeos/oobe_webui_browsertest.js) - +makes the browser fullscreen before running the JS test. + +[saml_password_attributes_test.unitjs](https://cs.chromium.org/chromium/src/chrome/browser/resources/chromeos/login/saml_password_attributes_test.unitjs) - +loads an XML file into a JS global variable before running the JS test. + +Another thing that will make your life a little bit easier is being able to +check the C++ code that is generated. Look for it in +`out/Default/path/to/package_one/awesome_test-gen.cc` or equivalent. + +Warning: Overuse of custom C++ code can make your test difficult to understand - +at this point you are running JS, that generates custom C++ - which will much +later be compiled and executed, in order to help set up the test environment, +within which the JS test itself will be run. + +Tip: To avoid this complexity, consider if it would be clearer to simply write a +C++ test directly, instead of generating the C++ test from a JS file. You can +always run JS code from a C++ test, even if the C++ test was not generated from +a JS file. You could even use the generated output from a js2gtest rule as a +starting point for writing a custom C++ test which you then check in. +
diff --git a/extensions/browser/api/audio/audio_service_chromeos.cc b/extensions/browser/api/audio/audio_service_chromeos.cc index c35e1cb..1128ab2 100644 --- a/extensions/browser/api/audio/audio_service_chromeos.cc +++ b/extensions/browser/api/audio/audio_service_chromeos.cc
@@ -200,10 +200,10 @@ bool accept_input = !(filter && filter->stream_types) || - base::ContainsValue(*filter->stream_types, api::audio::STREAM_TYPE_INPUT); - bool accept_output = !(filter && filter->stream_types) || - base::ContainsValue(*filter->stream_types, - api::audio::STREAM_TYPE_OUTPUT); + base::Contains(*filter->stream_types, api::audio::STREAM_TYPE_INPUT); + bool accept_output = + !(filter && filter->stream_types) || + base::Contains(*filter->stream_types, api::audio::STREAM_TYPE_OUTPUT); for (const auto& device : devices) { if (filter && filter->is_active && *filter->is_active != device.active)
diff --git a/extensions/browser/api/bluetooth/bluetooth_event_router.cc b/extensions/browser/api/bluetooth/bluetooth_event_router.cc index 27dec00..35bfd60 100644 --- a/extensions/browser/api/bluetooth/bluetooth_event_router.cc +++ b/extensions/browser/api/bluetooth/bluetooth_event_router.cc
@@ -208,7 +208,7 @@ BluetoothApiPairingDelegate* BluetoothEventRouter::GetPairingDelegate( const std::string& extension_id) { - return base::ContainsKey(pairing_delegate_map_, extension_id) + return base::Contains(pairing_delegate_map_, extension_id) ? pairing_delegate_map_[extension_id] : nullptr; } @@ -250,7 +250,7 @@ LOG(ERROR) << "Unable to get adapter for extension_id: " << extension_id; return; } - if (base::ContainsKey(pairing_delegate_map_, extension_id)) { + if (base::Contains(pairing_delegate_map_, extension_id)) { // For WebUI there may be more than one page open to the same url // (e.g. chrome://settings). These will share the same pairing delegate. BLUETOOTH_LOG(EVENT) << "Pairing delegate already exists for extension_id: " @@ -267,7 +267,7 @@ void BluetoothEventRouter::RemovePairingDelegate( const std::string& extension_id) { - if (base::ContainsKey(pairing_delegate_map_, extension_id)) { + if (base::Contains(pairing_delegate_map_, extension_id)) { BluetoothApiPairingDelegate* delegate = pairing_delegate_map_[extension_id]; if (adapter_.get()) adapter_->RemovePairingDelegate(delegate);
diff --git a/extensions/browser/api/declarative/declarative_rule_unittest.cc b/extensions/browser/api/declarative/declarative_rule_unittest.cc index 87f7195..3d36fd7 100644 --- a/extensions/browser/api/declarative/declarative_rule_unittest.cc +++ b/extensions/browser/api/declarative/declarative_rule_unittest.cc
@@ -119,7 +119,7 @@ bool IsFulfilled(const MatchData& match_data) const { if (condition_set_id != -1 && - !base::ContainsKey(match_data.url_matches, condition_set_id)) + !base::Contains(match_data.url_matches, condition_set_id)) return false; return match_data.value <= max_value; }
diff --git a/extensions/browser/api/declarative/deduping_factory.h b/extensions/browser/api/declarative/deduping_factory.h index 542d8b1..cb96e0f 100644 --- a/extensions/browser/api/declarative/deduping_factory.h +++ b/extensions/browser/api/declarative/deduping_factory.h
@@ -107,7 +107,7 @@ const std::string& instance_type, typename DedupingFactory<BaseClassT>::Parameterized parameterized, FactoryMethod factory_method) { - DCHECK(!base::ContainsKey(factory_methods_, instance_type)); + DCHECK(!base::Contains(factory_methods_, instance_type)); factory_methods_[instance_type] = factory_method; if (parameterized == IS_PARAMETERIZED) parameterized_types_.insert(instance_type); @@ -134,7 +134,7 @@ // We can take a shortcut for objects that are not parameterized. For those // only a single instance may ever exist so we can simplify the creation // logic. - if (!base::ContainsKey(parameterized_types_, instance_type)) { + if (!base::Contains(parameterized_types_, instance_type)) { if (prototypes.empty()) { scoped_refptr<const BaseClassT> new_object = (*factory_method)(instance_type, value, error, bad_message);
diff --git a/extensions/browser/api/declarative/rules_registry.cc b/extensions/browser/api/declarative/rules_registry.cc index 8b8367b..b85a68c 100644 --- a/extensions/browser/api/declarative/rules_registry.cc +++ b/extensions/browser/api/declarative/rules_registry.cc
@@ -344,7 +344,7 @@ void RulesRegistry::ProcessChangedRules(const std::string& extension_id) { DCHECK_CURRENTLY_ON(owner_thread()); - DCHECK(base::ContainsKey(process_changed_rules_requested_, extension_id)); + DCHECK(base::Contains(process_changed_rules_requested_, extension_id)); process_changed_rules_requested_[extension_id] = NOT_SCHEDULED_FOR_PROCESSING; std::vector<const api::events::Rule*> new_rules;
diff --git a/extensions/browser/api/declarative_net_request/file_sequence_helper.cc b/extensions/browser/api/declarative_net_request/file_sequence_helper.cc index aa55d5e3..5475c9e 100644 --- a/extensions/browser/api/declarative_net_request/file_sequence_helper.cc +++ b/extensions/browser/api/declarative_net_request/file_sequence_helper.cc
@@ -144,7 +144,7 @@ std::vector<dnr_api::Rule> result = std::move(current_rules); base::EraseIf(result, [&ids_to_remove](const dnr_api::Rule& rule) { - return base::ContainsKey(ids_to_remove, rule.id); + return base::Contains(ids_to_remove, rule.id); }); return result;
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_condition.cc b/extensions/browser/api/declarative_webrequest/webrequest_condition.cc index 0b589d6..ce6e4819 100644 --- a/extensions/browser/api/declarative_webrequest/webrequest_condition.cc +++ b/extensions/browser/api/declarative_webrequest/webrequest_condition.cc
@@ -98,12 +98,12 @@ // Check URL attributes if present. if (url_matcher_conditions_.get() && - !base::ContainsKey(request_data.url_match_ids, - url_matcher_conditions_->id())) + !base::Contains(request_data.url_match_ids, + url_matcher_conditions_->id())) return false; if (first_party_url_matcher_conditions_.get() && - !base::ContainsKey(request_data.first_party_url_match_ids, - first_party_url_matcher_conditions_->id())) + !base::Contains(request_data.first_party_url_match_ids, + first_party_url_matcher_conditions_->id())) return false; // All condition attributes must be fulfilled for a fulfilled condition.
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute.cc b/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute.cc index 0f263fa..77b6059 100644 --- a/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute.cc +++ b/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute.cc
@@ -183,7 +183,7 @@ const WebRequestData& request_data) const { if (!(request_data.stage & GetStages())) return false; - return base::ContainsValue(types_, request_data.request->web_request_type); + return base::Contains(types_, request_data.request->web_request_type); } WebRequestConditionAttribute::Type @@ -266,9 +266,9 @@ content_type, &mime_type, &charset, &had_charset, NULL); if (inclusive_) { - return base::ContainsValue(content_types_, mime_type); + return base::Contains(content_types_, mime_type); } else { - return !base::ContainsValue(content_types_, mime_type); + return !base::Contains(content_types_, mime_type); } }
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc b/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc index 211d168b..bb551be 100644 --- a/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc +++ b/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc
@@ -129,7 +129,7 @@ if (!rule->tags().empty() && !ignore_tags[extension_id].empty()) { bool ignore_rule = false; for (const std::string& tag : rule->tags()) - ignore_rule |= base::ContainsKey(ignore_tags[extension_id], tag); + ignore_rule |= base::Contains(ignore_tags[extension_id], tag); if (ignore_rule) continue; } @@ -367,7 +367,7 @@ for (const auto& url_match : url_matches) { auto rule_trigger = rule_triggers_.find(url_match); CHECK(rule_trigger != rule_triggers_.end()); - if (!base::ContainsKey(*result, rule_trigger->second) && + if (!base::Contains(*result, rule_trigger->second) && rule_trigger->second->conditions().IsFulfilled(url_match, request_data)) result->insert(rule_trigger->second); }
diff --git a/extensions/browser/api/document_scan/document_scan_api.cc b/extensions/browser/api/document_scan/document_scan_api.cc index 3681514..d11321dc 100644 --- a/extensions/browser/api/document_scan/document_scan_api.cc +++ b/extensions/browser/api/document_scan/document_scan_api.cc
@@ -48,7 +48,7 @@ if (params_->options.mime_types) { std::vector<std::string>& mime_types = *params_->options.mime_types; for (; scanner_i != scanner_descriptions.end(); ++scanner_i) { - if (base::ContainsValue(mime_types, scanner_i->image_mime_type)) { + if (base::Contains(mime_types, scanner_i->image_mime_type)) { break; } }
diff --git a/extensions/browser/api/file_system/file_system_api.cc b/extensions/browser/api/file_system/file_system_api.cc index 1ce53a3..176fedf 100644 --- a/extensions/browser/api/file_system/file_system_api.cc +++ b/extensions/browser/api/file_system/file_system_api.cc
@@ -636,8 +636,7 @@ // If we still need to find suggested_extension, hunt for it inside the // extensions returned from GetFileTypesFromAcceptOption. - if (need_suggestion && - base::ContainsValue(extensions, suggested_extension)) { + if (need_suggestion && base::Contains(extensions, suggested_extension)) { need_suggestion = false; } }
diff --git a/extensions/browser/api/hid/hid_device_manager.cc b/extensions/browser/api/hid/hid_device_manager.cc index a6d7c12..672d07c 100644 --- a/extensions/browser/api/hid/hid_device_manager.cc +++ b/extensions/browser/api/hid/hid_device_manager.cc
@@ -227,7 +227,7 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_LT(next_resource_id_, std::numeric_limits<int>::max()); int new_id = next_resource_id_++; - DCHECK(!base::ContainsKey(resource_ids_, device->guid)); + DCHECK(!base::Contains(resource_ids_, device->guid)); resource_ids_[device->guid] = new_id; devices_[new_id] = std::move(device);
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc b/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc index f36bdce8..8417f22 100644 --- a/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc +++ b/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc
@@ -704,7 +704,7 @@ allowed_paths.push_back( test_dir_.GetPath().AppendASCII("deprecated_value_store")); } - EXPECT_TRUE(base::ContainsValue(allowed_paths, root)) + EXPECT_TRUE(base::Contains(allowed_paths, root)) << "Unexpected value store path " << root.value(); return std::make_unique<LocalValueStoreCache>( @@ -1328,13 +1328,13 @@ EXPECT_TRUE(new_item); EXPECT_EQ(2u, items.size()); - EXPECT_TRUE(base::ContainsValue(items, migrated_item_id)); - EXPECT_TRUE(base::ContainsValue(items, initial_item_id)); + EXPECT_TRUE(base::Contains(items, migrated_item_id)); + EXPECT_TRUE(base::Contains(items, initial_item_id)); GetAllItems(&items); ASSERT_EQ(2u, items.size()); - EXPECT_TRUE(base::ContainsValue(items, migrated_item_id)); - EXPECT_TRUE(base::ContainsValue(items, new_item->id())); + EXPECT_TRUE(base::Contains(items, migrated_item_id)); + EXPECT_TRUE(base::Contains(items, new_item->id())); } TEST_F(LockScreenItemStorageTest,
diff --git a/extensions/browser/api/management/management_api.cc b/extensions/browser/api/management/management_api.cc index e028420..0ff0806 100644 --- a/extensions/browser/api/management/management_api.cc +++ b/extensions/browser/api/management/management_api.cc
@@ -733,7 +733,7 @@ GetAvailableLaunchTypes(*extension, delegate); management::LaunchType app_launch_type = params->launch_type; - if (!base::ContainsValue(available_launch_types, app_launch_type)) { + if (!base::Contains(available_launch_types, app_launch_type)) { return RespondNow(Error(keys::kLaunchTypeNotAvailableError)); }
diff --git a/extensions/browser/api/messaging/message_service.cc b/extensions/browser/api/messaging/message_service.cc index 2793ff0..fdcf326e4 100644 --- a/extensions/browser/api/messaging/message_service.cc +++ b/extensions/browser/api/messaging/message_service.cc
@@ -735,7 +735,7 @@ PendingMessage(source_port_id, message)); // A channel should only be holding pending messages because it is in one // of these states. - DCHECK(!base::ContainsKey(pending_lazy_context_channels_, channel_id)); + DCHECK(!base::Contains(pending_lazy_context_channels_, channel_id)); return; } EnqueuePendingMessageForLazyBackgroundLoad(source_port_id,
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos.cc b/extensions/browser/api/networking_private/networking_private_chromeos.cc index 9b89e85..a3f0864 100644 --- a/extensions/browser/api/networking_private/networking_private_chromeos.cc +++ b/extensions/browser/api/networking_private/networking_private_chromeos.cc
@@ -682,7 +682,7 @@ ::onc::network_type::kEthernet, ::onc::network_type::kWiFi, ::onc::network_type::kWimax, ::onc::network_type::kCellular}; for (const char* technology : technology_types) { - if (base::ContainsKey(technologies_found, technology)) + if (base::Contains(technologies_found, technology)) continue; AppendDeviceState(technology, nullptr /* device */, device_state_list.get());
diff --git a/extensions/browser/api/socket/udp_socket.cc b/extensions/browser/api/socket/udp_socket.cc index eedd1713..7d63bee 100644 --- a/extensions/browser/api/socket/udp_socket.cc +++ b/extensions/browser/api/socket/udp_socket.cc
@@ -323,7 +323,7 @@ } std::string normalized_address = ip.ToString(); - if (base::ContainsValue(multicast_groups_, normalized_address)) { + if (base::Contains(multicast_groups_, normalized_address)) { std::move(callback).Run(net::ERR_ADDRESS_INVALID); return; }
diff --git a/extensions/browser/api/storage/storage_api_unittest.cc b/extensions/browser/api/storage/storage_api_unittest.cc index 2e056eb8b..561e1b4f 100644 --- a/extensions/browser/api/storage/storage_api_unittest.cc +++ b/extensions/browser/api/storage/storage_api_unittest.cc
@@ -140,10 +140,10 @@ RunSetFunction("key", "value"); EXPECT_EQ(2u, event_observer.events().size()); - EXPECT_TRUE(base::ContainsKey(event_observer.events(), - api::storage::OnChanged::kEventName)); + EXPECT_TRUE(base::Contains(event_observer.events(), + api::storage::OnChanged::kEventName)); EXPECT_TRUE( - base::ContainsKey(event_observer.events(), "storage.local.onChanged")); + base::Contains(event_observer.events(), "storage.local.onChanged")); } } // namespace extensions
diff --git a/extensions/browser/api/system_display/system_display_apitest.cc b/extensions/browser/api/system_display/system_display_apitest.cc index 446a499..a42934f 100644 --- a/extensions/browser/api/system_display/system_display_apitest.cc +++ b/extensions/browser/api/system_display/system_display_apitest.cc
@@ -103,7 +103,7 @@ } bool OverscanCalibrationStart(const std::string& id) override { - if (base::ContainsKey(overscan_started_, id)) + if (base::Contains(overscan_started_, id)) return false; overscan_started_.insert(id); return true; @@ -112,21 +112,21 @@ bool OverscanCalibrationAdjust( const std::string& id, const api::system_display::Insets& delta) override { - if (!base::ContainsKey(overscan_started_, id)) + if (!base::Contains(overscan_started_, id)) return false; overscan_adjusted_.insert(id); return true; } bool OverscanCalibrationReset(const std::string& id) override { - if (!base::ContainsKey(overscan_started_, id)) + if (!base::Contains(overscan_started_, id)) return false; overscan_adjusted_.erase(id); return true; } bool OverscanCalibrationComplete(const std::string& id) override { - if (!base::ContainsKey(overscan_started_, id)) + if (!base::Contains(overscan_started_, id)) return false; overscan_started_.erase(id); return true; @@ -141,11 +141,11 @@ bool unified_desktop_enabled() const { return unified_desktop_enabled_; } bool calibration_started(const std::string& id) const { - return base::ContainsKey(overscan_started_, id); + return base::Contains(overscan_started_, id); } bool calibration_changed(const std::string& id) const { - return base::ContainsKey(overscan_adjusted_, id); + return base::Contains(overscan_adjusted_, id); } const api::system_display::MirrorMode& mirror_mode() const {
diff --git a/extensions/browser/api/usb/usb_device_manager.cc b/extensions/browser/api/usb/usb_device_manager.cc index 8a9112b..e65d7c8 100644 --- a/extensions/browser/api/usb/usb_device_manager.cc +++ b/extensions/browser/api/usb/usb_device_manager.cc
@@ -225,7 +225,7 @@ device::mojom::UsbDeviceInfoPtr device_info) { DCHECK(device_info); // Update the device list. - DCHECK(!base::ContainsKey(devices_, device_info->guid)); + DCHECK(!base::Contains(devices_, device_info->guid)); std::string guid = device_info->guid; auto result = devices_.insert(std::make_pair(std::move(guid), std::move(device_info))); @@ -242,7 +242,7 @@ device::mojom::UsbDeviceInfoPtr device_info) { DCHECK(device_info); // Update the device list. - DCHECK(base::ContainsKey(devices_, device_info->guid)); + DCHECK(base::Contains(devices_, device_info->guid)); devices_.erase(device_info->guid); DispatchEvent(usb::OnDeviceRemoved::kEventName, *device_info);
diff --git a/extensions/browser/api/vpn_provider/vpn_service.cc b/extensions/browser/api/vpn_provider/vpn_service.cc index 722dfd40..d868923 100644 --- a/extensions/browser/api/vpn_provider/vpn_service.cc +++ b/extensions/browser/api/vpn_provider/vpn_service.cc
@@ -368,7 +368,7 @@ } const std::string key = GetKey(extension_id, configuration_name); - if (base::ContainsKey(key_to_configuration_map_, key)) { + if (base::Contains(key_to_configuration_map_, key)) { failure.Run(std::string(), std::string("Name not unique.")); return; } @@ -414,7 +414,7 @@ const FailureCallback& failure) { // The ID is the configuration name for now. This may change in the future. const std::string key = GetKey(extension_id, configuration_id); - if (!base::ContainsKey(key_to_configuration_map_, key)) { + if (!base::Contains(key_to_configuration_map_, key)) { failure.Run(std::string(), std::string("Unauthorized access.")); return; } @@ -487,7 +487,7 @@ const std::string& extension_id, const std::string& configuration_name) { const std::string key = GetKey(extension_id, configuration_name); - return base::ContainsKey(key_to_configuration_map_, key); + return base::Contains(key_to_configuration_map_, key); } bool VpnService::VerifyConfigIsConnectedForTesting( @@ -635,7 +635,7 @@ pepper_vpn_provider_proxy) { // The ID is the configuration name for now. This may change in the future. const std::string key = GetKey(extension_id, configuration_id); - if (!base::ContainsKey(key_to_configuration_map_, key)) { + if (!base::Contains(key_to_configuration_map_, key)) { failure.Run(std::string(), std::string("Unauthorized access. " "The configuration does not exist."));
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc index 91b9768..e915e9fa 100644 --- a/extensions/browser/api/web_request/web_request_api.cc +++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -1963,7 +1963,7 @@ bool ExtensionWebRequestEventRouter::HasAnyExtraHeadersListenerImpl( void* browser_context) { - return base::ContainsKey(extra_headers_listener_count_, browser_context); + return base::Contains(extra_headers_listener_count_, browser_context); } void ExtensionWebRequestEventRouter::UpdateExtraHeadersListenerOnUI( @@ -2070,8 +2070,7 @@ } const std::vector<WebRequestResourceType>& types = listener->filter.types; - if (!types.empty() && - !base::ContainsValue(types, request->web_request_type)) { + if (!types.empty() && !base::Contains(types, request->web_request_type)) { continue; } @@ -2337,7 +2336,7 @@ Listeners& listeners = listeners_[browser_context][event_name]; for (const auto& listener : listeners) { - if (!base::ContainsKey(listener->blocked_requests, request_id)) + if (!base::Contains(listener->blocked_requests, request_id)) continue; std::string delegate_info = l10n_util::GetStringFUTF8( IDS_LOAD_STATE_PARAMETER_EXTENSION,
diff --git a/extensions/browser/api/web_request/web_request_api_helpers.cc b/extensions/browser/api/web_request/web_request_api_helpers.cc index 5b53610..1ea4fff2 100644 --- a/extensions/browser/api/web_request/web_request_api_helpers.cc +++ b/extensions/browser/api/web_request/web_request_api_helpers.cc
@@ -949,7 +949,7 @@ const std::string& value = modification.value(); // We must not modify anything that has been deleted before. - if (base::ContainsKey(*removed_headers, key)) { + if (base::Contains(*removed_headers, key)) { extension_conflicts = true; break; } @@ -970,7 +970,7 @@ // We must not modify anything that has been set to a *different* // value before. - if (base::ContainsKey(*set_headers, key)) { + if (base::Contains(*set_headers, key)) { std::string current_value; if (!request_headers->GetHeader(key, ¤t_value) || current_value != value) { @@ -985,7 +985,7 @@ // modified before. { for (const std::string& key : delta.deleted_request_headers) { - if (base::ContainsKey(*set_headers, base::ToLowerASCII(key))) { + if (base::Contains(*set_headers, base::ToLowerASCII(key))) { extension_conflicts = true; break; } @@ -1002,7 +1002,7 @@ std::string key = base::ToLowerASCII(modification.name()); if (!request_headers->HasHeader(key)) { added_headers.insert(key); - } else if (!base::ContainsKey(added_headers, key)) { + } else if (!base::Contains(added_headers, key)) { // Note: |key| will only be present in |added_headers| if this is an // identical edit. overridden_headers.insert(key);
diff --git a/extensions/browser/app_window/app_window_geometry_cache.cc b/extensions/browser/app_window/app_window_geometry_cache.cc index a17057e..57db19c9 100644 --- a/extensions/browser/app_window/app_window_geometry_cache.cc +++ b/extensions/browser/app_window/app_window_geometry_cache.cc
@@ -56,7 +56,7 @@ if (extension_data[window_id].bounds == bounds && extension_data[window_id].window_state == window_state && extension_data[window_id].screen_bounds == screen_bounds && - !base::ContainsKey(unsynced_extensions_, extension_id)) + !base::Contains(unsynced_extensions_, extension_id)) return; base::Time now = base::Time::Now();
diff --git a/extensions/browser/app_window/app_window_registry.cc b/extensions/browser/app_window/app_window_registry.cc index 4a59d05..cc11d60 100644 --- a/extensions/browser/app_window/app_window_registry.cc +++ b/extensions/browser/app_window/app_window_registry.cc
@@ -182,7 +182,7 @@ } void AppWindowRegistry::AddAppWindowToList(AppWindow* app_window) { - if (base::ContainsValue(app_windows_, app_window)) + if (base::Contains(app_windows_, app_window)) return; app_windows_.push_back(app_window); }
diff --git a/extensions/browser/content_hash_fetcher_unittest.cc b/extensions/browser/content_hash_fetcher_unittest.cc index 02ec8aa..6e643d3 100644 --- a/extensions/browser/content_hash_fetcher_unittest.cc +++ b/extensions/browser/content_hash_fetcher_unittest.cc
@@ -306,8 +306,7 @@ ASSERT_NE(nullptr, result.get()); EXPECT_TRUE(result->success); EXPECT_FALSE(result->was_cancelled); - EXPECT_TRUE( - base::ContainsKey(result->mismatch_paths, script_path.BaseName())); + EXPECT_TRUE(base::Contains(result->mismatch_paths, script_path.BaseName())); // Make sure the verified_contents.json file was written into the extension's // install dir.
diff --git a/extensions/browser/content_verifier.cc b/extensions/browser/content_verifier.cc index 36fc369..52480ce 100644 --- a/extensions/browser/content_verifier.cc +++ b/extensions/browser/content_verifier.cc
@@ -696,10 +696,10 @@ // Background pages, scripts and content scripts should always be verified // regardless of their file type. - if (base::ContainsKey(background_or_content_paths, relative_unix_path)) + if (base::Contains(background_or_content_paths, relative_unix_path)) return true; - if (base::ContainsKey(browser_images, relative_unix_path)) + if (base::Contains(browser_images, relative_unix_path)) continue; base::FilePath full_path = @@ -723,8 +723,8 @@ // _locales/<some locale>/messages.json - if so then skip it. if (full_path.BaseName() == messages_file && full_path.DirName().DirName() == locales_dir && - base::ContainsKey(*all_locales, - full_path.DirName().BaseName().MaybeAsASCII())) { + base::Contains(*all_locales, + full_path.DirName().BaseName().MaybeAsASCII())) { continue; } }
diff --git a/extensions/browser/event_listener_map.cc b/extensions/browser/event_listener_map.cc index d7d18d5..29a399e 100644 --- a/extensions/browser/event_listener_map.cc +++ b/extensions/browser/event_listener_map.cc
@@ -346,7 +346,7 @@ } bool EventListenerMap::IsFilteredEvent(const Event& event) const { - return base::ContainsKey(filtered_events_, event.event_name); + return base::Contains(filtered_events_, event.event_name); } } // namespace extensions
diff --git a/extensions/browser/events/lazy_event_dispatcher.cc b/extensions/browser/events/lazy_event_dispatcher.cc index fc3aa96..fe30c55 100644 --- a/extensions/browser/events/lazy_event_dispatcher.cc +++ b/extensions/browser/events/lazy_event_dispatcher.cc
@@ -53,7 +53,7 @@ bool LazyEventDispatcher::HasAlreadyDispatched( const LazyContextId& dispatch_context) const { - return base::ContainsKey(dispatched_ids_, dispatch_context); + return base::Contains(dispatched_ids_, dispatch_context); } bool LazyEventDispatcher::QueueEventDispatch(
diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc index ea8e8b37..3c54b852 100644 --- a/extensions/browser/extension_registrar.cc +++ b/extensions/browser/extension_registrar.cc
@@ -355,7 +355,7 @@ // even if it's not permanently installed. unloaded_extension_paths_[extension->id()] = extension->path(); - DCHECK(!base::ContainsKey(reloading_extensions_, extension->id())) + DCHECK(!base::Contains(reloading_extensions_, extension->id())) << "Enabled extension shouldn't be marked for reloading"; registry_->AddTerminated(extension); @@ -513,7 +513,7 @@ // For orphaned devtools, we will reconnect devtools to it later in // DidCreateRenderViewForBackgroundPage(). bool has_orphaned_dev_tools = - base::ContainsKey(orphaned_dev_tools_, extension->id()); + base::Contains(orphaned_dev_tools_, extension->id()); // Reloading component extension does not trigger install, so RuntimeAPI won't // be able to detect its loading. Therefore, we need to spin up its lazy
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.cc index 8a68ece..ad188c0 100644 --- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.cc +++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.cc
@@ -74,7 +74,7 @@ int32_t render_process_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); auto& map = *GetProcessIdToHelperMap(); - if (!base::ContainsKey(map, render_process_id)) { + if (!base::Contains(map, render_process_id)) { auto* process_host = content::RenderProcessHost::FromID(render_process_id); if (!process_host) return nullptr;
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc index 31f32ff6..1a9beda 100644 --- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc +++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc
@@ -50,8 +50,8 @@ const std::string& mime_type, const std::string& stream_id, const std::string& internal_id) { - DCHECK(!base::ContainsKey(*GetMimeHandlerViewEmbeddersMap(), - frame_tree_node_id)); + DCHECK( + !base::Contains(*GetMimeHandlerViewEmbeddersMap(), frame_tree_node_id)); GetMimeHandlerViewEmbeddersMap()->insert_or_assign( frame_tree_node_id, base::WrapUnique(new MimeHandlerViewEmbedder( frame_tree_node_id, resource_url, mime_type,
diff --git a/extensions/browser/image_sanitizer_unittest.cc b/extensions/browser/image_sanitizer_unittest.cc index 44e311f..a14e2b6 100644 --- a/extensions/browser/image_sanitizer_unittest.cc +++ b/extensions/browser/image_sanitizer_unittest.cc
@@ -268,7 +268,7 @@ EXPECT_TRUE(base::GetFileSize(full_path, &file_size)); EXPECT_GT(file_size, 0); - ASSERT_TRUE(base::ContainsKey(*decoded_images(), path)); + ASSERT_TRUE(base::Contains(*decoded_images(), path)); EXPECT_FALSE((*decoded_images())[path].drawsNothing()); } // No extra images should have been reported.
diff --git a/extensions/browser/lazy_background_task_queue.cc b/extensions/browser/lazy_background_task_queue.cc index c0a5fe3..523134f 100644 --- a/extensions/browser/lazy_background_task_queue.cc +++ b/extensions/browser/lazy_background_task_queue.cc
@@ -233,7 +233,7 @@ content::BrowserContext* browser_context, const Extension* extension) { PendingTasksKey key(browser_context, extension->id()); - if (!base::ContainsKey(pending_tasks_, key)) + if (!base::Contains(pending_tasks_, key)) return; ProcessManager* pm = ProcessManager::Get(browser_context);
diff --git a/extensions/browser/renderer_startup_helper.cc b/extensions/browser/renderer_startup_helper.cc index a930cfa..1e368fe 100644 --- a/extensions/browser/renderer_startup_helper.cc +++ b/extensions/browser/renderer_startup_helper.cc
@@ -151,8 +151,8 @@ ExtensionRegistry::Get(browser_context_)->enabled_extensions(); for (const auto& ext : extensions) { // OnLoadedExtension should have already been called for the extension. - DCHECK(base::ContainsKey(extension_process_map_, ext->id())); - DCHECK(!base::ContainsKey(extension_process_map_[ext->id()], process)); + DCHECK(base::Contains(extension_process_map_, ext->id())); + DCHECK(!base::Contains(extension_process_map_[ext->id()], process)); if (!IsExtensionVisibleToContext(*ext, renderer_context)) continue; @@ -174,8 +174,8 @@ for (const ExtensionId& id : iter->second) { // The extension should be loaded in the process. DCHECK(extensions.Contains(id)); - DCHECK(base::ContainsKey(extension_process_map_, id)); - DCHECK(base::ContainsKey(extension_process_map_[id], process)); + DCHECK(base::Contains(extension_process_map_, id)); + DCHECK(base::Contains(extension_process_map_[id], process)); process->Send(new ExtensionMsg_ActivateExtension(id)); } } @@ -202,7 +202,7 @@ content::RenderProcessHost* process) { // The extension should have been loaded already. Dump without crashing to // debug crbug.com/528026. - if (!base::ContainsKey(extension_process_map_, extension.id())) { + if (!base::Contains(extension_process_map_, extension.id())) { #if DCHECK_IS_ON() NOTREACHED() << "Extension " << extension.id() << "activated before loading"; @@ -215,8 +215,8 @@ if (!IsExtensionVisibleToContext(extension, process->GetBrowserContext())) return; - if (base::ContainsKey(initialized_processes_, process)) { - DCHECK(base::ContainsKey(extension_process_map_[extension.id()], process)); + if (base::Contains(initialized_processes_, process)) { + DCHECK(base::Contains(extension_process_map_[extension.id()], process)); process->Send(new ExtensionMsg_ActivateExtension(extension.id())); } else { pending_active_extensions_[process].insert(extension.id()); @@ -227,7 +227,7 @@ // Extension was already loaded. // TODO(crbug.com/708230): Ensure that clients don't call this for an // already loaded extension and change this to a DCHECK. - if (base::ContainsKey(extension_process_map_, extension.id())) + if (base::Contains(extension_process_map_, extension.id())) return; // Mark the extension as loaded. @@ -274,13 +274,13 @@ // Extension is not loaded. // TODO(crbug.com/708230): Ensure that clients call this for a loaded // extension only and change this to a DCHECK. - if (!base::ContainsKey(extension_process_map_, extension.id())) + if (!base::Contains(extension_process_map_, extension.id())) return; const std::set<content::RenderProcessHost*>& loaded_process_set = extension_process_map_[extension.id()]; for (content::RenderProcessHost* process : loaded_process_set) { - DCHECK(base::ContainsKey(initialized_processes_, process)); + DCHECK(base::Contains(initialized_processes_, process)); process->Send(new ExtensionMsg_Unloaded(extension.id())); }
diff --git a/extensions/browser/renderer_startup_helper_unittest.cc b/extensions/browser/renderer_startup_helper_unittest.cc index 7afa40f..bcc5f85 100644 --- a/extensions/browser/renderer_startup_helper_unittest.cc +++ b/extensions/browser/renderer_startup_helper_unittest.cc
@@ -110,25 +110,24 @@ } bool IsProcessInitialized(content::RenderProcessHost* rph) { - return base::ContainsKey(helper_->initialized_processes_, rph); + return base::Contains(helper_->initialized_processes_, rph); } bool IsExtensionLoaded(const Extension& extension) { - return base::ContainsKey(helper_->extension_process_map_, extension.id()); + return base::Contains(helper_->extension_process_map_, extension.id()); } bool IsExtensionLoadedInProcess(const Extension& extension, content::RenderProcessHost* rph) { return IsExtensionLoaded(extension) && - base::ContainsKey(helper_->extension_process_map_[extension.id()], - rph); + base::Contains(helper_->extension_process_map_[extension.id()], rph); } bool IsExtensionPendingActivationInProcess(const Extension& extension, content::RenderProcessHost* rph) { - return base::ContainsKey(helper_->pending_active_extensions_, rph) && - base::ContainsKey(helper_->pending_active_extensions_[rph], - extension.id()); + return base::Contains(helper_->pending_active_extensions_, rph) && + base::Contains(helper_->pending_active_extensions_[rph], + extension.id()); } std::unique_ptr<RendererStartupHelper> helper_;
diff --git a/extensions/browser/service_worker_task_queue.cc b/extensions/browser/service_worker_task_queue.cc index a81018a..27e1a76 100644 --- a/extensions/browser/service_worker_task_queue.cc +++ b/extensions/browser/service_worker_task_queue.cc
@@ -324,8 +324,8 @@ int64_t version_id, int process_id, int thread_id) { - if (!base::ContainsKey(loaded_workers_, context_id) || - !base::ContainsKey(started_workers_, context_id)) { + if (!base::Contains(loaded_workers_, context_id) || + !base::Contains(started_workers_, context_id)) { // The worker hasn't finished starting (DidStartWorkerForScope) or hasn't // finished loading (DidStartServiceWorkerContext). // Wait for the next event, and run the tasks then.
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc index 7da47628..1373f0a 100644 --- a/extensions/browser/url_loader_factory_manager.cc +++ b/extensions/browser/url_loader_factory_manager.cc
@@ -317,7 +317,7 @@ const std::string& hash = extension.hashed_id().value(); DCHECK(IsValidHashedExtensionId(hash)); - return base::ContainsKey(GetExtensionsAllowlist(), hash); + return base::Contains(GetExtensionsAllowlist(), hash); } // Safe fallback for future extension manifest versions. @@ -435,7 +435,7 @@ content::WebContents::FromRenderFrameHost(found_frame)->GetOpener(); } if (!next_candidate || - base::ContainsKey(already_visited_frames, next_candidate)) { + base::Contains(already_visited_frames, next_candidate)) { break; }
diff --git a/extensions/browser/verified_contents.cc b/extensions/browser/verified_contents.cc index 9d8032b..489ec82 100644 --- a/extensions/browser/verified_contents.cc +++ b/extensions/browser/verified_contents.cc
@@ -246,13 +246,13 @@ const base::FilePath& relative_path) const { base::FilePath::StringType path = base::ToLowerASCII( relative_path.NormalizePathSeparatorsTo('/').value()); - if (base::ContainsKey(root_hashes_, path)) + if (base::Contains(root_hashes_, path)) return true; #if defined(OS_WIN) base::FilePath::StringType trimmed_path; if (TrimDotSpaceSuffix(path, &trimmed_path)) - return base::ContainsKey(root_hashes_, trimmed_path); + return base::Contains(root_hashes_, trimmed_path); #endif // defined(OS_WIN) return false; }
diff --git a/extensions/browser/zipfile_installer.cc b/extensions/browser/zipfile_installer.cc index 3fc0f68..b748b7a 100644 --- a/extensions/browser/zipfile_installer.cc +++ b/extensions/browser/zipfile_installer.cc
@@ -203,7 +203,7 @@ // Allow filenames with no extension. if (extension.empty()) return true; - return base::ContainsValue(kAllowedThemeFiletypes, extension); + return base::Contains(kAllowedThemeFiletypes, extension); } return !base::FilePath::CompareEqualIgnoreCase(file_path.FinalExtension(), FILE_PATH_LITERAL(".exe"));
diff --git a/extensions/common/extension_l10n_util.cc b/extensions/common/extension_l10n_util.cc index ee2fa5b..0f6a3ed 100644 --- a/extensions/common/extension_l10n_util.cc +++ b/extensions/common/extension_l10n_util.cc
@@ -472,7 +472,7 @@ if (subdir.empty()) return true; // Non-ASCII. - if (base::ContainsValue(subdir, '.')) + if (base::Contains(subdir, '.')) return true; if (all_locales.find(subdir) == all_locales.end())
diff --git a/extensions/common/extension_set.cc b/extensions/common/extension_set.cc index 217c2df..070acdf 100644 --- a/extensions/common/extension_set.cc +++ b/extensions/common/extension_set.cc
@@ -63,7 +63,7 @@ } bool ExtensionSet::Insert(const scoped_refptr<const Extension>& extension) { - bool was_present = base::ContainsKey(extensions_, extension->id()); + bool was_present = base::Contains(extensions_, extension->id()); extensions_[extension->id()] = extension; return !was_present; }
diff --git a/extensions/common/features/simple_feature.cc b/extensions/common/features/simple_feature.cc index 986a631..ee03ee41 100644 --- a/extensions/common/features/simple_feature.cc +++ b/extensions/common/features/simple_feature.cc
@@ -431,7 +431,7 @@ if (!IsValidHashedExtensionId(hashed_id)) return false; - return base::ContainsValue(list, hashed_id.value()); + return base::Contains(list, hashed_id.value()); } bool SimpleFeature::MatchesManifestLocation( @@ -454,14 +454,14 @@ if (session_types_.empty()) return true; - if (base::ContainsValue(session_types_, session_type)) + if (base::Contains(session_types_, session_type)) return true; // AUTOLAUNCHED_KIOSK session type is subset of KIOSK - accept auto-lauched // kiosk session if kiosk session is allowed. This is the only exception to // rejecting session type that is not present in |session_types_| return session_type == FeatureSessionType::AUTOLAUNCHED_KIOSK && - base::ContainsValue(session_types_, FeatureSessionType::KIOSK); + base::Contains(session_types_, FeatureSessionType::KIOSK); } Feature::Availability SimpleFeature::CheckDependencies( @@ -545,7 +545,7 @@ version_info::Channel channel, FeatureSessionType session_type) const { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (!platforms_.empty() && !base::ContainsValue(platforms_, platform)) + if (!platforms_.empty() && !base::Contains(platforms_, platform)) return CreateAvailability(INVALID_PLATFORM); if (channel_ && *channel_ < GetCurrentChannel()) { @@ -582,7 +582,7 @@ Manifest::Type type_to_check = (type == Manifest::TYPE_USER_SCRIPT) ? Manifest::TYPE_EXTENSION : type; if (!extension_types_.empty() && - !base::ContainsValue(extension_types_, type_to_check)) { + !base::Contains(extension_types_, type_to_check)) { return CreateAvailability(INVALID_TYPE, type); } @@ -622,7 +622,7 @@ // extension API calls, since there's no guarantee that the extension is // "active" in current renderer process when the API permission check is // done. - if (!contexts_.empty() && !base::ContainsValue(contexts_, context)) + if (!contexts_.empty() && !base::Contains(contexts_, context)) return CreateAvailability(INVALID_CONTEXT, context); // TODO(kalman): Consider checking |matches_| regardless of context type.
diff --git a/extensions/common/manifest_handler.cc b/extensions/common/manifest_handler.cc index 73bd75c..e0ba65d2 100644 --- a/extensions/common/manifest_handler.cc +++ b/extensions/common/manifest_handler.cc
@@ -236,7 +236,7 @@ CHECK(prereq_iter != handlers_.end()) << "Extension manifest handler depends on unrecognized key " << key; // Prerequisite is in our map. - if (base::ContainsKey(priority_map_, prereq_iter->second)) + if (base::Contains(priority_map_, prereq_iter->second)) unsatisfied--; } if (unsatisfied == 0) {
diff --git a/extensions/common/manifest_handlers/permissions_parser.cc b/extensions/common/manifest_handlers/permissions_parser.cc index c7821d9..fb3fdaff 100644 --- a/extensions/common/manifest_handlers/permissions_parser.cc +++ b/extensions/common/manifest_handlers/permissions_parser.cc
@@ -123,7 +123,7 @@ // Users should be able to enable file access for extensions with activeTab. if (!can_execute_script_everywhere && - base::ContainsKey(api_permissions, APIPermission::kActiveTab)) { + base::Contains(api_permissions, APIPermission::kActiveTab)) { extension->set_wants_file_access(true); }
diff --git a/extensions/common/message_bundle.cc b/extensions/common/message_bundle.cc index f870167..aeb728d 100644 --- a/extensions/common/message_bundle.cc +++ b/extensions/common/message_bundle.cc
@@ -113,7 +113,7 @@ // Add all reserved messages to the dictionary, but check for collisions. auto it = append_messages.begin(); for (; it != append_messages.end(); ++it) { - if (base::ContainsKey(dictionary_, it->first)) { + if (base::Contains(dictionary_, it->first)) { *error = ErrorUtils::FormatErrorMessage( errors::kReservedMessageFound, it->first); return false;
diff --git a/extensions/common/permissions/api_permission_set.cc b/extensions/common/permissions/api_permission_set.cc index fd2ae552..b4fedf6 100644 --- a/extensions/common/permissions/api_permission_set.cc +++ b/extensions/common/permissions/api_permission_set.cc
@@ -306,7 +306,7 @@ const std::set<APIPermission::ID>& permission_ids) const { PermissionIDSet subset; for (const auto& permission : permissions_) { - if (base::ContainsKey(permission_ids, permission.id())) { + if (base::Contains(permission_ids, permission.id())) { subset.permissions_.insert(permission); } }
diff --git a/extensions/common/permissions/permissions_data.cc b/extensions/common/permissions/permissions_data.cc index b09be07..fe5e92c 100644 --- a/extensions/common/permissions/permissions_data.cc +++ b/extensions/common/permissions/permissions_data.cc
@@ -83,7 +83,7 @@ const ExtensionsClient::ScriptingWhitelist& whitelist = ExtensionsClient::Get()->GetScriptingWhitelist(); - return base::ContainsValue(whitelist, extension_id); + return base::Contains(whitelist, extension_id); } bool PermissionsData::IsRestrictedUrl(const GURL& document_url,
diff --git a/extensions/common/permissions/permissions_info.cc b/extensions/common/permissions/permissions_info.cc index 008cd71..1e0e8dbf 100644 --- a/extensions/common/permissions/permissions_info.cc +++ b/extensions/common/permissions/permissions_info.cc
@@ -74,15 +74,15 @@ } void PermissionsInfo::RegisterAlias(const Alias& alias) { - DCHECK(base::ContainsKey(name_map_, alias.real_name)); - DCHECK(!base::ContainsKey(name_map_, alias.name)); + DCHECK(base::Contains(name_map_, alias.real_name)); + DCHECK(!base::Contains(name_map_, alias.name)); name_map_[alias.name] = name_map_[alias.real_name]; } void PermissionsInfo::RegisterPermission( std::unique_ptr<APIPermissionInfo> permission) { - DCHECK(!base::ContainsKey(id_map_, permission->id())); - DCHECK(!base::ContainsKey(name_map_, permission->name())); + DCHECK(!base::Contains(id_map_, permission->id())); + DCHECK(!base::Contains(name_map_, permission->name())); name_map_[permission->name()] = permission.get(); id_map_[permission->id()] = std::move(permission);
diff --git a/extensions/common/url_pattern_set_unittest.cc b/extensions/common/url_pattern_set_unittest.cc index 88e2972..852b1b2ca 100644 --- a/extensions/common/url_pattern_set_unittest.cc +++ b/extensions/common/url_pattern_set_unittest.cc
@@ -565,8 +565,8 @@ EXPECT_EQ(2UL, string_vector->size()); - EXPECT_TRUE(base::ContainsValue(*string_vector, "https://google.com/")); - EXPECT_TRUE(base::ContainsValue(*string_vector, "https://yahoo.com/")); + EXPECT_TRUE(base::Contains(*string_vector, "https://google.com/")); + EXPECT_TRUE(base::Contains(*string_vector, "https://yahoo.com/")); } } // namespace extensions
diff --git a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc index 8f1c1a6a..843bac9 100644 --- a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc +++ b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
@@ -297,7 +297,7 @@ // Refresh child tree id mappings. for (const ui::AXTreeID& tree_id : tree_.GetAllChildTreeIds()) { - DCHECK(!base::ContainsKey(child_tree_id_reverse_map, tree_id)); + DCHECK(!base::Contains(child_tree_id_reverse_map, tree_id)); child_tree_id_reverse_map.insert(std::make_pair(tree_id, this)); }
diff --git a/extensions/renderer/bindings/api_bindings_system_unittest.cc b/extensions/renderer/bindings/api_bindings_system_unittest.cc index 0df93d7..fc8b5ea 100644 --- a/extensions/renderer/bindings/api_bindings_system_unittest.cc +++ b/extensions/renderer/bindings/api_bindings_system_unittest.cc
@@ -159,7 +159,7 @@ const base::DictionaryValue& APIBindingsSystemTest::GetAPISchema( const std::string& api_name) { - EXPECT_TRUE(base::ContainsKey(api_schemas_, api_name)); + EXPECT_TRUE(base::Contains(api_schemas_, api_name)); return *api_schemas_[api_name]; }
diff --git a/extensions/renderer/feature_cache_unittest.cc b/extensions/renderer/feature_cache_unittest.cc index b36e57ce..afb9a55 100644 --- a/extensions/renderer/feature_cache_unittest.cc +++ b/extensions/renderer/feature_cache_unittest.cc
@@ -34,7 +34,7 @@ bool HasFeature(FeatureCache& cache, const FakeContext& context, const std::string& feature) { - return base::ContainsValue( + return base::Contains( cache.GetAvailableFeatures(context.context_type, context.extension, context.url), feature);
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc index de8c3c7..04e6e52d 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc
@@ -62,7 +62,7 @@ } int32_t routing_id = render_frame->GetRoutingID(); auto& map = *GetRenderFrameMap(); - if (base::ContainsKey(map, routing_id)) + if (base::Contains(map, routing_id)) return map[routing_id].get(); if (create_if_does_not_exits) { map[routing_id] =
diff --git a/extensions/renderer/native_renderer_messaging_service.cc b/extensions/renderer/native_renderer_messaging_service.cc index e186dfa..3906d5e 100644 --- a/extensions/renderer/native_renderer_messaging_service.cc +++ b/extensions/renderer/native_renderer_messaging_service.cc
@@ -352,7 +352,7 @@ v8::HandleScope handle_scope(script_context->isolate()); MessagingPerContextData* data = GetPerContextData<MessagingPerContextData>( script_context->v8_context(), kDontCreateIfMissing); - return data && base::ContainsKey(data->ports, port_id); + return data && base::Contains(data->ports, port_id); } void NativeRendererMessagingService::DispatchOnConnectToListeners( @@ -530,7 +530,7 @@ MessagingPerContextData* data = GetPerContextData<MessagingPerContextData>(context, kCreateIfMissing); DCHECK(data); - DCHECK(!base::ContainsKey(data->ports, port_id)); + DCHECK(!base::Contains(data->ports, port_id)); gin::Handle<GinPort> port_handle = gin::CreateHandle( isolate, @@ -553,7 +553,7 @@ MessagingPerContextData* data = GetPerContextData<MessagingPerContextData>( script_context->v8_context(), kDontCreateIfMissing); DCHECK(data); - DCHECK(base::ContainsKey(data->ports, port_id)); + DCHECK(base::Contains(data->ports, port_id)); GinPort* port = nullptr; gin::Converter<GinPort*>::FromV8(context->GetIsolate(),
diff --git a/extensions/renderer/one_time_message_handler.cc b/extensions/renderer/one_time_message_handler.cc index 0904bbb..ee5a652 100644 --- a/extensions/renderer/one_time_message_handler.cc +++ b/extensions/renderer/one_time_message_handler.cc
@@ -155,8 +155,8 @@ kDontCreateIfMissing); if (!data) return false; - return port_id.is_opener ? base::ContainsKey(data->openers, port_id) - : base::ContainsKey(data->receivers, port_id); + return port_id.is_opener ? base::Contains(data->openers, port_id) + : base::Contains(data->receivers, port_id); } void OneTimeMessageHandler::SendMessage( @@ -220,7 +220,7 @@ OneTimeMessageContextData* data = GetPerContextData<OneTimeMessageContextData>(context, kCreateIfMissing); DCHECK(data); - DCHECK(!base::ContainsKey(data->receivers, target_port_id)); + DCHECK(!base::Contains(data->receivers, target_port_id)); OneTimeReceiver& receiver = data->receivers[target_port_id]; receiver.sender.Reset(isolate, sender); receiver.routing_id = RoutingIdForScriptContext(script_context);
diff --git a/extensions/renderer/resource_bundle_source_map.cc b/extensions/renderer/resource_bundle_source_map.cc index 22dda472..f087859 100644 --- a/extensions/renderer/resource_bundle_source_map.cc +++ b/extensions/renderer/resource_bundle_source_map.cc
@@ -89,7 +89,7 @@ } bool ResourceBundleSourceMap::Contains(const std::string& name) const { - return base::ContainsKey(resource_map_, name); + return base::Contains(resource_map_, name); } } // namespace extensions
diff --git a/extensions/renderer/script_context.cc b/extensions/renderer/script_context.cc index 0bfe1ac4..cfb1d90 100644 --- a/extensions/renderer/script_context.cc +++ b/extensions/renderer/script_context.cc
@@ -362,7 +362,7 @@ // Avoid an infinite loop - see https://crbug.com/568432 and // https://crbug.com/883526. - if (base::ContainsKey(already_visited_frames, parent)) + if (base::Contains(already_visited_frames, parent)) return document_url; parent_document = parent && parent->IsWebLocalFrame()
diff --git a/gpu/ipc/service/gpu_watchdog_thread.cc b/gpu/ipc/service/gpu_watchdog_thread.cc index 857e92b..b51f7ac2 100644 --- a/gpu/ipc/service/gpu_watchdog_thread.cc +++ b/gpu/ipc/service/gpu_watchdog_thread.cc
@@ -479,8 +479,7 @@ crash_keys::available_physical_memory_in_mb.Set( base::NumberToString(available_physical_memory)); - ui::gl::ShaderTracking* shader_tracking = - ui::gl::ShaderTracking::GetInstance(); + gl::ShaderTracking* shader_tracking = gl::ShaderTracking::GetInstance(); if (shader_tracking) { std::string shaders[2]; shader_tracking->GetShaders(shaders, shaders + 1);
diff --git a/ios/chrome/browser/app_startup_parameters.mm b/ios/chrome/browser/app_startup_parameters.mm index e9ccd89..11ba0724 100644 --- a/ios/chrome/browser/app_startup_parameters.mm +++ b/ios/chrome/browser/app_startup_parameters.mm
@@ -61,8 +61,8 @@ } // Currently only Payment Request parameters are supported. - if (base::ContainsKey(parameters, payments::kPaymentRequestIDExternal) && - base::ContainsKey(parameters, payments::kPaymentRequestDataExternal)) { + if (base::Contains(parameters, payments::kPaymentRequestIDExternal) && + base::Contains(parameters, payments::kPaymentRequestDataExternal)) { _externalURLParams = parameters; _completePaymentRequest = YES; }
diff --git a/ios/chrome/browser/autofill/form_structure_browsertest.mm b/ios/chrome/browser/autofill/form_structure_browsertest.mm index 575501b..5b1d2f3f 100644 --- a/ios/chrome/browser/autofill/form_structure_browsertest.mm +++ b/ios/chrome/browser/autofill/form_structure_browsertest.mm
@@ -242,7 +242,7 @@ // DISABLED_DataDrivenHeuristics. TEST_P(FormStructureBrowserTest, DataDrivenHeuristics) { bool is_expected_to_pass = - !base::ContainsKey(GetFailingTestNames(), GetParam().BaseName().value()); + !base::Contains(GetFailingTestNames(), GetParam().BaseName().value()); RunOneDataDrivenTest(GetParam(), GetIOSOutputDirectory(), is_expected_to_pass); }
diff --git a/ios/chrome/browser/bookmarks/bookmarks_utils.cc b/ios/chrome/browser/bookmarks/bookmarks_utils.cc index f3bb3f003..62d97f9 100644 --- a/ios/chrome/browser/bookmarks/bookmarks_utils.cc +++ b/ios/chrome/browser/bookmarks/bookmarks_utils.cc
@@ -72,7 +72,7 @@ bool IsPrimaryPermanentNode(const BookmarkNode* node, BookmarkModel* model) { std::vector<const BookmarkNode*> primary_nodes(PrimaryPermanentNodes(model)); - return base::ContainsValue(primary_nodes, node); + return base::Contains(primary_nodes, node); } const BookmarkNode* RootLevelFolderForNode(const BookmarkNode* node, @@ -84,7 +84,7 @@ const std::vector<const BookmarkNode*> root_folders(RootLevelFolders(model)); const BookmarkNode* top = node; - while (top && !base::ContainsValue(root_folders, top)) { + while (top && !base::Contains(root_folders, top)) { top = top->parent(); } return top;
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm index d74d3ae..e472186c 100644 --- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm +++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
@@ -256,7 +256,7 @@ const base::FilePath& partition_path) const { DCHECK(initialized_); AppRequestContext* context = nullptr; - if (base::ContainsKey(app_request_context_map_, partition_path)) { + if (base::Contains(app_request_context_map_, partition_path)) { context = app_request_context_map_[partition_path]; } else { context = AcquireIsolatedAppRequestContext(main_context); @@ -269,7 +269,7 @@ void ChromeBrowserStateIOData::SetCookieStoreForPartitionPath( std::unique_ptr<net::CookieStore> cookie_store, const base::FilePath& partition_path) { - DCHECK(base::ContainsKey(app_request_context_map_, partition_path)); + DCHECK(base::Contains(app_request_context_map_, partition_path)); app_request_context_map_[partition_path]->SetCookieStore( std::move(cookie_store)); }
diff --git a/ios/chrome/browser/metrics/ukm_egtest.mm b/ios/chrome/browser/metrics/ukm_egtest.mm index d64f6b5ea..1f6bfce 100644 --- a/ios/chrome/browser/metrics/ukm_egtest.mm +++ b/ios/chrome/browser/metrics/ukm_egtest.mm
@@ -68,7 +68,7 @@ static bool HasDummySource(ukm::SourceId source_id) { auto* service = ukm_service(); - return service && base::ContainsKey(service->sources(), source_id); + return service && base::Contains(service->sources(), source_id); } static void RecordDummySource(ukm::SourceId source_id) {
diff --git a/ios/chrome/browser/payments/ios_payment_instrument_finder.mm b/ios/chrome/browser/payments/ios_payment_instrument_finder.mm index bd74073..c45cd80 100644 --- a/ios/chrome/browser/payments/ios_payment_instrument_finder.mm +++ b/ios/chrome/browser/payments/ios_payment_instrument_finder.mm
@@ -67,7 +67,7 @@ for (const GURL& method : queried_url_payment_method_identifiers) { // Ensure that the payment method is recognized by looking for an // "app-name://" scheme to query for its presence. - if (!base::ContainsKey(enum_map, method.spec())) + if (!base::Contains(enum_map, method.spec())) continue; // If there is an app that can handle |scheme| on this device, this payment
diff --git a/ios/chrome/browser/reading_list/url_downloader.cc b/ios/chrome/browser/reading_list/url_downloader.cc index cf22044..7fc4e33f 100644 --- a/ios/chrome/browser/reading_list/url_downloader.cc +++ b/ios/chrome/browser/reading_list/url_downloader.cc
@@ -83,7 +83,7 @@ } void URLDownloader::DownloadOfflineURL(const GURL& url) { - if (!base::ContainsValue(tasks_, std::make_pair(DOWNLOAD, url))) { + if (!base::Contains(tasks_, std::make_pair(DOWNLOAD, url))) { tasks_.push_back(std::make_pair(DOWNLOAD, url)); HandleNextTask(); }
diff --git a/ios/chrome/browser/reading_list/url_downloader_unittest.mm b/ios/chrome/browser/reading_list/url_downloader_unittest.mm index 1cc8de9..42e66bcd 100644 --- a/ios/chrome/browser/reading_list/url_downloader_unittest.mm +++ b/ios/chrome/browser/reading_list/url_downloader_unittest.mm
@@ -253,7 +253,7 @@ // Wait for all asynchronous tasks to complete. task_environment_.RunUntilIdle(); - ASSERT_TRUE(!base::ContainsValue(downloader_->downloaded_files_, url)); + ASSERT_TRUE(!base::Contains(downloader_->downloaded_files_, url)); ASSERT_EQ(1ul, downloader_->downloaded_files_.size()); ASSERT_EQ(1ul, downloader_->removed_files_.size()); ASSERT_FALSE(downloader_->CheckExistenceOfOfflineURLPagePath(url)); @@ -272,8 +272,8 @@ // Wait for all asynchronous tasks to complete. task_environment_.RunUntilIdle(); - ASSERT_TRUE(base::ContainsValue(downloader_->downloaded_files_, url)); - ASSERT_TRUE(base::ContainsValue(downloader_->removed_files_, url)); + ASSERT_TRUE(base::Contains(downloader_->downloaded_files_, url)); + ASSERT_TRUE(base::Contains(downloader_->removed_files_, url)); ASSERT_TRUE(downloader_->CheckExistenceOfOfflineURLPagePath(url)); }
diff --git a/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm b/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm index c41dfca..43741c4 100644 --- a/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm
@@ -463,27 +463,10 @@ return; base::RecordAction(base::UserMetricsAction( "Signin_AccountSettings_GoogleActivityControlsClicked")); - UINavigationController* settingsDetails = - ios::GetChromeBrowserProvider() - ->GetChromeIdentityService() - ->CreateWebAndAppSettingDetailsController( - [self authService] -> GetAuthenticatedIdentity(), self); - UIImage* closeIcon = [ChromeIcon closeIcon]; - SEL action = @selector(closeGoogleActivitySettings:); - [settingsDetails.topViewController navigationItem].leftBarButtonItem = - [ChromeIcon templateBarButtonItemWithImage:closeIcon - target:self - action:action]; - [self presentViewController:settingsDetails animated:YES completion:nil]; - - // Keep a weak reference on the settings details, to be able to dismiss it - // when the primary account is removed. - _settingsDetails = settingsDetails; -} - -- (void)closeGoogleActivitySettings:(id)sender { - DCHECK(_settingsDetails); - [self dismissViewControllerAnimated:YES completion:nil]; + ios::GetChromeBrowserProvider() + ->GetChromeIdentityService() + ->PresentWebAndAppSettingDetailsController( + [self authService] -> GetAuthenticatedIdentity(), self, YES); } #pragma mark - Authentication operations
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm index 79a0161..0188f8d 100644 --- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm +++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm
@@ -49,11 +49,11 @@ ManageSyncSettingsTableViewController* viewController; // Mediator. @property(nonatomic, strong) ManageSyncSettingsMediator* mediator; -// Web and app activity view controller. -@property(nonatomic, weak) - UINavigationController* webAndAppSettingDetailsController; // Sync service. @property(nonatomic, assign, readonly) syncer::SyncService* syncService; +// Dismiss callback for Web and app setting details view. +@property(nonatomic, copy) ios::DismissWebAndAppSettingDetailsControllerBlock + dismissWebAndAppSettingDetailsControllerBlock; @end @@ -88,20 +88,12 @@ #pragma mark - Private -// Called by the close button of the Web and app activity view controller. -- (void)closeGoogleActivitySettings:(id)sender { - DCHECK(self.webAndAppSettingDetailsController); - [self.navigationController dismissViewControllerAnimated:YES completion:nil]; - self.webAndAppSettingDetailsController = nil; -} - // Closes the Manage sync settings view controller. - (void)closeManageSyncSettings { if (self.viewController.navigationController) { - if (self.webAndAppSettingDetailsController) { - [self.navigationController dismissViewControllerAnimated:NO - completion:nil]; - self.webAndAppSettingDetailsController = nil; + if (self.dismissWebAndAppSettingDetailsControllerBlock) { + self.dismissWebAndAppSettingDetailsControllerBlock(NO); + self.dismissWebAndAppSettingDetailsControllerBlock = nil; } [self.navigationController popToViewController:self.viewController animated:NO]; @@ -150,22 +142,12 @@ AuthenticationServiceFactory::GetForBrowserState(self.browserState); base::RecordAction(base::UserMetricsAction( "Signin_AccountSettings_GoogleActivityControlsClicked")); - DCHECK(!self.webAndAppSettingDetailsController); - self.webAndAppSettingDetailsController = + self.dismissWebAndAppSettingDetailsControllerBlock = ios::GetChromeBrowserProvider() ->GetChromeIdentityService() - ->CreateWebAndAppSettingDetailsController( - authService->GetAuthenticatedIdentity(), self); - UIImage* closeIcon = [ChromeIcon closeIcon]; - SEL action = @selector(closeGoogleActivitySettings:); - [self.webAndAppSettingDetailsController.topViewController navigationItem] - .leftBarButtonItem = [ChromeIcon templateBarButtonItemWithImage:closeIcon - target:self - action:action]; - [self.navigationController - presentViewController:self.webAndAppSettingDetailsController - animated:YES - completion:nil]; + ->PresentWebAndAppSettingDetailsController( + authService->GetAuthenticatedIdentity(), self.viewController, + YES); } - (void)openDataFromChromeSyncWebPage {
diff --git a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm index c0b0af4..7766b1f 100644 --- a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm
@@ -155,9 +155,12 @@ - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; - // TODO(crbug.com/931173): This is a workaround to fix the vertical alignment - // of the back button. Remove once the UIKit bug is fixed. - [self.navigationController.navigationBar setNeedsLayout]; + if (@available(iOS 13, *)) { + } else { + // This is a workaround to fix the vertical alignment of the back button. + // The bug has been fixed in iOS 13. See crbug.com/931173 if needed. + [self.navigationController.navigationBar setNeedsLayout]; + } } #pragma mark - UITableViewDelegate
diff --git a/ios/chrome/browser/voice/speech_input_locale_config_impl.mm b/ios/chrome/browser/voice/speech_input_locale_config_impl.mm index dda5926..910c8868 100644 --- a/ios/chrome/browser/voice/speech_input_locale_config_impl.mm +++ b/ios/chrome/browser/voice/speech_input_locale_config_impl.mm
@@ -85,7 +85,7 @@ bool SpeechInputLocaleConfigImpl::IsTextToSpeechEnabledForCode( const std::string& locale_code) const { std::string language = GetLanguageComponentForLocaleCode(locale_code); - return base::ContainsValue(text_to_speech_languages_, language); + return base::Contains(text_to_speech_languages_, language); } SpeechInputLocale SpeechInputLocaleConfigImpl::GetMatchingLocale(
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h index b12eddb..19e57cf 100644 --- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h +++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
@@ -112,12 +112,18 @@ id<ChromeIdentityBrowserOpener> browser_opener); // Returns a new Web and App Setting Details controller to present. + // Deprecated, crbug.com/905680. + // Please use PresentWebAndAppSettingDetailsController(). virtual UINavigationController* CreateWebAndAppSettingDetailsController( ChromeIdentity* identity, id<ChromeIdentityBrowserOpener> browser_opener); - // Not implemented yet. Please use CreateWebAndAppSettingDetailsController(). - // See: crbug.com/905680. + // Presents a new Web and App Setting Details view. + // |identity| the identity used to present the view. + // |viewController| the view to present the setting details. + // |animated| the view is presented with animation if YES. + // Returns a block to dismiss the presented view. This block can be ignored if + // not needed. virtual DismissWebAndAppSettingDetailsControllerBlock PresentWebAndAppSettingDetailsController(ChromeIdentity* identity, UIViewController* viewController,
diff --git a/ios/web/common/origin_util.mm b/ios/web/common/origin_util.mm index 2b993b8ef..52a0c46 100644 --- a/ios/web/common/origin_util.mm +++ b/ios/web/common/origin_util.mm
@@ -28,7 +28,7 @@ return true; } - if (base::ContainsValue(url::GetSecureSchemes(), url.scheme())) + if (base::Contains(url::GetSecureSchemes(), url.scheme())) return true; if (net::IsLocalhost(url))
diff --git a/ios/web/webui/url_data_manager_ios.cc b/ios/web/webui/url_data_manager_ios.cc index 483c9f5..3415ac26 100644 --- a/ios/web/webui/url_data_manager_ios.cc +++ b/ios/web/webui/url_data_manager_ios.cc
@@ -135,7 +135,7 @@ base::AutoLock lock(GetDeleteLock()); if (!data_sources_) return false; - return base::ContainsValue(*data_sources_, data_source); + return base::Contains(*data_sources_, data_source); } } // namespace web
diff --git a/ios/web/webui/url_data_manager_ios_backend.mm b/ios/web/webui/url_data_manager_ios_backend.mm index b8dfc04..bd1f3d2c 100644 --- a/ios/web/webui/url_data_manager_ios_backend.mm +++ b/ios/web/webui/url_data_manager_ios_backend.mm
@@ -60,7 +60,7 @@ std::vector<std::string> additional_schemes; DCHECK(GetWebClient()->IsAppSpecificURL(url) || (GetWebClient()->GetAdditionalWebUISchemes(&additional_schemes), - base::ContainsValue(additional_schemes, url.scheme()))); + base::Contains(additional_schemes, url.scheme()))); if (!url.is_valid()) { NOTREACHED();
diff --git a/ipc/ipc_channel_proxy.cc b/ipc/ipc_channel_proxy.cc index 11ac875..5abff39 100644 --- a/ipc/ipc_channel_proxy.cc +++ b/ipc/ipc_channel_proxy.cc
@@ -340,7 +340,7 @@ DCHECK(default_listener_task_runner_->BelongsToCurrentThread()); DCHECK(task_runner); base::AutoLock lock(listener_thread_task_runners_lock_); - if (!base::ContainsKey(listener_thread_task_runners_, routing_id)) + if (!base::Contains(listener_thread_task_runners_, routing_id)) listener_thread_task_runners_.insert({routing_id, std::move(task_runner)}); } @@ -348,7 +348,7 @@ void ChannelProxy::Context::RemoveListenerTaskRunner(int32_t routing_id) { DCHECK(default_listener_task_runner_->BelongsToCurrentThread()); base::AutoLock lock(listener_thread_task_runners_lock_); - if (base::ContainsKey(listener_thread_task_runners_, routing_id)) + if (base::Contains(listener_thread_task_runners_, routing_id)) listener_thread_task_runners_.erase(routing_id); }
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc index f15eafd..acba960 100644 --- a/media/renderers/video_resource_updater.cc +++ b/media/renderers/video_resource_updater.cc
@@ -284,9 +284,8 @@ viz::bitmap_allocation::AllocateSharedBitmap( resource_size(), viz::ResourceFormat::RGBA_8888); shared_mapping_ = std::move(shm.mapping); - shared_bitmap_reporter_->DidAllocateSharedBitmap( - viz::bitmap_allocation::ToMojoHandle(std::move(shm.region)), - shared_bitmap_id_); + shared_bitmap_reporter_->DidAllocateSharedBitmap(std::move(shm.region), + shared_bitmap_id_); } ~SoftwarePlaneResource() override { shared_bitmap_reporter_->DidDeleteSharedBitmap(shared_bitmap_id_);
diff --git a/media/renderers/video_resource_updater_unittest.cc b/media/renderers/video_resource_updater_unittest.cc index fdeeb77..8e4edf88 100644 --- a/media/renderers/video_resource_updater_unittest.cc +++ b/media/renderers/video_resource_updater_unittest.cc
@@ -8,6 +8,7 @@ #include <stdint.h> #include "base/bind.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/test/scoped_task_environment.h" #include "components/viz/client/client_resource_provider.h" #include "components/viz/client/shared_bitmap_reporter.h" @@ -26,7 +27,7 @@ ~FakeSharedBitmapReporter() override = default; // viz::SharedBitmapReporter implementation. - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) override { DCHECK_EQ(shared_bitmaps_.count(id), 0u); shared_bitmaps_.insert(id);
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc index 51e4171f..80efe7a3 100644 --- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc +++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
@@ -299,7 +299,7 @@ controller_->SyncWatch(&response_received); // Make sure that this instance hasn't been destroyed. if (weak_self) { - DCHECK(base::ContainsKey(sync_responses_, request_id)); + DCHECK(base::Contains(sync_responses_, request_id)); auto iter = sync_responses_.find(request_id); DCHECK_EQ(&response_received, iter->second->response_received); if (response_received) {
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc index 3fc58449c..07a2748c0 100644 --- a/mojo/public/cpp/bindings/lib/multiplex_router.cc +++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -386,7 +386,7 @@ id = next_interface_id_value_++; if (set_interface_id_namespace_bit_) id |= kInterfaceIdNamespaceMask; - } while (base::ContainsKey(endpoints_, id)); + } while (base::Contains(endpoints_, id)); InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); endpoints_[id] = endpoint; @@ -438,7 +438,7 @@ return; MayAutoLock locker(&lock_); - DCHECK(base::ContainsKey(endpoints_, id)); + DCHECK(base::Contains(endpoints_, id)); InterfaceEndpoint* endpoint = endpoints_[id].get(); DCHECK(!endpoint->client()); DCHECK(!endpoint->closed()); @@ -462,7 +462,7 @@ DCHECK(client); MayAutoLock locker(&lock_); - DCHECK(base::ContainsKey(endpoints_, id)); + DCHECK(base::Contains(endpoints_, id)); InterfaceEndpoint* endpoint = endpoints_[id].get(); endpoint->AttachClient(client, std::move(runner)); @@ -481,7 +481,7 @@ DCHECK(IsValidInterfaceId(id)); MayAutoLock locker(&lock_); - DCHECK(base::ContainsKey(endpoints_, id)); + DCHECK(base::Contains(endpoints_, id)); InterfaceEndpoint* endpoint = endpoints_[id].get(); endpoint->DetachClient(); @@ -549,7 +549,7 @@ if (endpoints_.size() == 0) return false; - return !base::ContainsKey(endpoints_, kMasterInterfaceId); + return !base::Contains(endpoints_, kMasterInterfaceId); } void MultiplexRouter::EnableBatchDispatch() {
diff --git a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc b/mojo/public/cpp/bindings/lib/sync_handle_registry.cc index 2ae6353..b91d5f9 100644 --- a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc +++ b/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
@@ -36,7 +36,7 @@ const HandleCallback& callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (base::ContainsKey(handles_, handle)) + if (base::Contains(handles_, handle)) return false; MojoResult result = wait_set_.AddHandle(handle, handle_signals); @@ -49,7 +49,7 @@ void SyncHandleRegistry::UnregisterHandle(const Handle& handle) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!base::ContainsKey(handles_, handle)) + if (!base::Contains(handles_, handle)) return; MojoResult result = wait_set_.RemoveHandle(handle);
diff --git a/net/base/expiring_cache_unittest.cc b/net/base/expiring_cache_unittest.cc index f1414f9..1f3c5d38 100644 --- a/net/base/expiring_cache_unittest.cc +++ b/net/base/expiring_cache_unittest.cc
@@ -119,16 +119,16 @@ } EXPECT_EQ(10U, cache.size()); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "valid0")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "valid1")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "valid2")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "valid3")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "valid4")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "expired0")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "expired1")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "expired2")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "negative0")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "negative1")); + EXPECT_TRUE(base::Contains(cache.entries_, "valid0")); + EXPECT_TRUE(base::Contains(cache.entries_, "valid1")); + EXPECT_TRUE(base::Contains(cache.entries_, "valid2")); + EXPECT_TRUE(base::Contains(cache.entries_, "valid3")); + EXPECT_TRUE(base::Contains(cache.entries_, "valid4")); + EXPECT_TRUE(base::Contains(cache.entries_, "expired0")); + EXPECT_TRUE(base::Contains(cache.entries_, "expired1")); + EXPECT_TRUE(base::Contains(cache.entries_, "expired2")); + EXPECT_TRUE(base::Contains(cache.entries_, "negative0")); + EXPECT_TRUE(base::Contains(cache.entries_, "negative1")); // Shrink the new max constraints bound and compact. The "negative" and // "expired" entries should be dropped. @@ -136,16 +136,16 @@ cache.Compact(now); EXPECT_EQ(5U, cache.size()); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "valid0")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "valid1")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "valid2")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "valid3")); - EXPECT_TRUE(base::ContainsKey(cache.entries_, "valid4")); - EXPECT_FALSE(base::ContainsKey(cache.entries_, "expired0")); - EXPECT_FALSE(base::ContainsKey(cache.entries_, "expired1")); - EXPECT_FALSE(base::ContainsKey(cache.entries_, "expired2")); - EXPECT_FALSE(base::ContainsKey(cache.entries_, "negative0")); - EXPECT_FALSE(base::ContainsKey(cache.entries_, "negative1")); + EXPECT_TRUE(base::Contains(cache.entries_, "valid0")); + EXPECT_TRUE(base::Contains(cache.entries_, "valid1")); + EXPECT_TRUE(base::Contains(cache.entries_, "valid2")); + EXPECT_TRUE(base::Contains(cache.entries_, "valid3")); + EXPECT_TRUE(base::Contains(cache.entries_, "valid4")); + EXPECT_FALSE(base::Contains(cache.entries_, "expired0")); + EXPECT_FALSE(base::Contains(cache.entries_, "expired1")); + EXPECT_FALSE(base::Contains(cache.entries_, "expired2")); + EXPECT_FALSE(base::Contains(cache.entries_, "negative0")); + EXPECT_FALSE(base::Contains(cache.entries_, "negative1")); // Shrink further -- this time the compact will start dropping valid entries // to make space.
diff --git a/net/base/features.cc b/net/base/features.cc index ae53c9071..502fdeac 100644 --- a/net/base/features.cc +++ b/net/base/features.cc
@@ -13,7 +13,7 @@ base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kCapRefererHeaderLength = { - "CapRefererHeaderLength", base::FEATURE_DISABLED_BY_DEFAULT}; + "CapRefererHeaderLength", base::FEATURE_ENABLED_BY_DEFAULT}; const base::FeatureParam<int> kMaxRefererHeaderLength = { &kCapRefererHeaderLength, "MaxRefererHeaderLength", 4096};
diff --git a/net/base/filename_util_internal.cc b/net/base/filename_util_internal.cc index 46dc33a..b8ce2e0 100644 --- a/net/base/filename_util_internal.cc +++ b/net/base/filename_util_internal.cc
@@ -55,7 +55,7 @@ // "foo.jpg" to "foo.jpeg". std::vector<base::FilePath::StringType> all_mime_extensions; GetExtensionsForMimeType(mime_type, &all_mime_extensions); - if (base::ContainsValue(all_mime_extensions, extension)) + if (base::Contains(all_mime_extensions, extension)) return extension; // Get the "final" extension. In most cases, this is the same as the @@ -69,7 +69,7 @@ // If there's a double extension, and the second extension is in the // list of valid extensions for the given type, keep the double extension. // This avoids renaming things like "foo.tar.gz" to "foo.gz". - if (base::ContainsValue(all_mime_extensions, final_extension)) + if (base::Contains(all_mime_extensions, final_extension)) return extension; return preferred_mime_extension; }
diff --git a/net/base/mime_util_unittest.cc b/net/base/mime_util_unittest.cc index 6c224ed..ade4192 100644 --- a/net/base/mime_util_unittest.cc +++ b/net/base/mime_util_unittest.cc
@@ -330,7 +330,7 @@ test.contained_result, test.contained_result + strlen(test.contained_result)); - bool found = base::ContainsValue(extensions, contained_result); + bool found = base::Contains(extensions, contained_result); ASSERT_TRUE(found) << "Must find at least the contained result within " << test.mime_type;
diff --git a/net/base/network_throttle_manager_impl.cc b/net/base/network_throttle_manager_impl.cc index d5043bc..0c0e7ec 100644 --- a/net/base/network_throttle_manager_impl.cc +++ b/net/base/network_throttle_manager_impl.cc
@@ -240,8 +240,8 @@ break; } - DCHECK(!base::ContainsValue(blocked_throttles_, throttle)); - DCHECK(!base::ContainsValue(outstanding_throttles_, throttle)); + DCHECK(!base::Contains(blocked_throttles_, throttle)); + DCHECK(!base::Contains(outstanding_throttles_, throttle)); // Unblock the throttles if there's some chance there's a throttle to // unblock.
diff --git a/net/cert/x509_certificate.cc b/net/cert/x509_certificate.cc index f196769..a5d1616 100644 --- a/net/cert/x509_certificate.cc +++ b/net/cert/x509_certificate.cc
@@ -439,13 +439,13 @@ std::string normalized_cert_issuer; if (!GetNormalizedCertIssuer(cert_buffer_.get(), &normalized_cert_issuer)) return false; - if (base::ContainsValue(normalized_issuers, normalized_cert_issuer)) + if (base::Contains(normalized_issuers, normalized_cert_issuer)) return true; for (const auto& intermediate : intermediate_ca_certs_) { if (!GetNormalizedCertIssuer(intermediate.get(), &normalized_cert_issuer)) return false; - if (base::ContainsValue(normalized_issuers, normalized_cert_issuer)) + if (base::Contains(normalized_issuers, normalized_cert_issuer)) return true; } return false; @@ -488,7 +488,7 @@ base::StringPiece ip_addr_string( reinterpret_cast<const char*>(host_info.address), host_info.AddressLength()); - return base::ContainsValue(cert_san_ip_addrs, ip_addr_string); + return base::Contains(cert_san_ip_addrs, ip_addr_string); } // |reference_domain| is the remainder of |host| after the leading host
diff --git a/net/cert_net/nss_ocsp.cc b/net/cert_net/nss_ocsp.cc index 9fa92efec..826d297 100644 --- a/net/cert_net/nss_ocsp.cc +++ b/net/cert_net/nss_ocsp.cc
@@ -519,12 +519,12 @@ } void OCSPIOLoop::AddRequest(OCSPRequestSession* request) { - DCHECK(!base::ContainsKey(requests_, request)); + DCHECK(!base::Contains(requests_, request)); requests_.insert(request); } void OCSPIOLoop::RemoveRequest(OCSPRequestSession* request) { - DCHECK(base::ContainsKey(requests_, request)); + DCHECK(base::Contains(requests_, request)); requests_.erase(request); }
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index 5772e2a..a13fb0f 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc
@@ -523,7 +523,7 @@ bool CookieMonster::IsCookieableScheme(const std::string& scheme) { DCHECK(thread_checker_.CalledOnValidThread()); - return base::ContainsValue(cookieable_schemes_, scheme); + return base::Contains(cookieable_schemes_, scheme); } const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http", "https",
diff --git a/net/cookies/parse_cookie_line_fuzzer.cc b/net/cookies/parse_cookie_line_fuzzer.cc index 984a081..beb8401 100644 --- a/net/cookies/parse_cookie_line_fuzzer.cc +++ b/net/cookies/parse_cookie_line_fuzzer.cc
@@ -22,40 +22,46 @@ const std::string cookie_line = GetArbitraryString(&data_provider); net::ParsedCookie parsed_cookie(cookie_line); - // Call zero or one of ParsedCookie's mutator methods. - switch (data_provider.ConsumeIntegralInRange(0, 10)) { - case 0: - break; + // Call zero or one of ParsedCookie's mutator methods. Should not call + // anything other than SetName/SetValue when !IsValid(). + const uint8_t action = data_provider.ConsumeIntegralInRange(0, 10); + switch (action) { case 1: parsed_cookie.SetName(GetArbitraryString(&data_provider)); break; case 2: parsed_cookie.SetValue(GetArbitraryString(&data_provider)); break; - case 3: - parsed_cookie.SetPath(GetArbitraryString(&data_provider)); - break; - case 4: - parsed_cookie.SetDomain(GetArbitraryString(&data_provider)); - break; - case 5: - parsed_cookie.SetExpires(GetArbitraryString(&data_provider)); - break; - case 6: - parsed_cookie.SetMaxAge(GetArbitraryString(&data_provider)); - break; - case 7: - parsed_cookie.SetIsSecure(data_provider.ConsumeBool()); - break; - case 8: - parsed_cookie.SetIsHttpOnly(data_provider.ConsumeBool()); - break; - case 9: - parsed_cookie.SetSameSite(GetArbitraryString(&data_provider)); - break; - case 10: - parsed_cookie.SetPriority(GetArbitraryString(&data_provider)); - break; + } + + if (parsed_cookie.IsValid()) { + switch (action) { + case 3: + if (parsed_cookie.IsValid()) + parsed_cookie.SetPath(GetArbitraryString(&data_provider)); + break; + case 4: + parsed_cookie.SetDomain(GetArbitraryString(&data_provider)); + break; + case 5: + parsed_cookie.SetExpires(GetArbitraryString(&data_provider)); + break; + case 6: + parsed_cookie.SetMaxAge(GetArbitraryString(&data_provider)); + break; + case 7: + parsed_cookie.SetIsSecure(data_provider.ConsumeBool()); + break; + case 8: + parsed_cookie.SetIsHttpOnly(data_provider.ConsumeBool()); + break; + case 9: + parsed_cookie.SetSameSite(GetArbitraryString(&data_provider)); + break; + case 10: + parsed_cookie.SetPriority(GetArbitraryString(&data_provider)); + break; + } } // Check that serialize/deserialize inverse property holds for valid cookies. @@ -63,8 +69,17 @@ const std::string serialized = parsed_cookie.ToCookieLine(); net::ParsedCookie reparsed_cookie(serialized); const std::string reserialized = reparsed_cookie.ToCookieLine(); - CHECK(reparsed_cookie.IsValid()); - CHECK_EQ(serialized, reserialized); + + // RFC6265 requires semicolons to be followed by spaces. Because our parser + // permits this rule to be broken, but follows the rule in ToCookieLine(), + // it's possible to serialize a string that's longer than the original + // input. If the serialized string exceeds kMaxCookieSize, the parser will + // reject it. For this fuzzer, we are considering this situation a false + // positive. + if (serialized.size() <= net::ParsedCookie::kMaxCookieSize) { + CHECK(reparsed_cookie.IsValid()); + CHECK_EQ(serialized, reserialized); + } } return 0;
diff --git a/net/disk_cache/simple/simple_backend_impl.cc b/net/disk_cache/simple/simple_backend_impl.cc index e8eab5d2..76d510d 100644 --- a/net/disk_cache/simple/simple_backend_impl.cc +++ b/net/disk_cache/simple/simple_backend_impl.cc
@@ -819,12 +819,19 @@ } else { bool mtime_result = disk_cache::simple_util::GetMTime(path, &result.cache_dir_mtime); - DCHECK(mtime_result); - if (!result.max_size) { + if (!mtime_result) { + // Something deleted the directory between when we set it up and the + // mstat; this is not uncommon on some test fixtures which erase their + // tempdir while some worker threads may still be running. + LOG(ERROR) << "Simple Cache Backend: cache directory inaccessible right " + "after creation; path: " + << path.LossyDisplayName(); + result.net_error = net::ERR_FAILED; + } else if (!result.max_size) { int64_t available = base::SysInfo::AmountOfFreeDiskSpace(path); result.max_size = disk_cache::PreferredCacheSize(available); + DCHECK(result.max_size); } - DCHECK(result.max_size); } return result; }
diff --git a/net/http/http_auth_handler_factory.cc b/net/http/http_auth_handler_factory.cc index d44ad9c6..d3242e0 100644 --- a/net/http/http_auth_handler_factory.cc +++ b/net/http/http_auth_handler_factory.cc
@@ -147,17 +147,17 @@ std::unique_ptr<HttpAuthHandlerRegistryFactory> registry_factory( new HttpAuthHandlerRegistryFactory()); - if (base::ContainsKey(auth_schemes_set, kBasicAuthScheme)) { + if (base::Contains(auth_schemes_set, kBasicAuthScheme)) { registry_factory->RegisterSchemeFactory( kBasicAuthScheme, new HttpAuthHandlerBasic::Factory()); } - if (base::ContainsKey(auth_schemes_set, kDigestAuthScheme)) { + if (base::Contains(auth_schemes_set, kDigestAuthScheme)) { registry_factory->RegisterSchemeFactory( kDigestAuthScheme, new HttpAuthHandlerDigest::Factory()); } - if (base::ContainsKey(auth_schemes_set, kNtlmAuthScheme)) { + if (base::Contains(auth_schemes_set, kNtlmAuthScheme)) { HttpAuthHandlerNTLM::Factory* ntlm_factory = new HttpAuthHandlerNTLM::Factory(); #if defined(OS_WIN) @@ -167,7 +167,7 @@ } #if BUILDFLAG(USE_KERBEROS) - if (base::ContainsKey(auth_schemes_set, kNegotiateAuthScheme)) { + if (base::Contains(auth_schemes_set, kNegotiateAuthScheme)) { HttpAuthHandlerNegotiate::Factory* negotiate_factory = new HttpAuthHandlerNegotiate::Factory(negotiate_auth_system_factory); #if defined(OS_WIN)
diff --git a/net/http/http_cache_lookup_manager.cc b/net/http/http_cache_lookup_manager.cc index 6fd010f..db6240b 100644 --- a/net/http/http_cache_lookup_manager.cc +++ b/net/http/http_cache_lookup_manager.cc
@@ -71,7 +71,7 @@ GURL pushed_url = push_helper->GetURL(); // There's a pending lookup transaction sent over already. - if (base::ContainsKey(lookup_transactions_, pushed_url)) + if (base::Contains(lookup_transactions_, pushed_url)) return; auto lookup = std::make_unique<LookupTransaction>(std::move(push_helper),
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index d3ed27d..e66c2ce 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -293,14 +293,14 @@ void HttpNetworkSession::AddResponseDrainer( std::unique_ptr<HttpResponseBodyDrainer> drainer) { - DCHECK(!base::ContainsKey(response_drainers_, drainer.get())); + DCHECK(!base::Contains(response_drainers_, drainer.get())); HttpResponseBodyDrainer* drainer_ptr = drainer.get(); response_drainers_[drainer_ptr] = std::move(drainer); } void HttpNetworkSession::RemoveResponseDrainer( HttpResponseBodyDrainer* drainer) { - DCHECK(base::ContainsKey(response_drainers_, drainer)); + DCHECK(base::Contains(response_drainers_, drainer)); response_drainers_[drainer].release(); response_drainers_.erase(drainer); }
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc index f18530db..c6c7148 100644 --- a/net/http/http_server_properties_impl.cc +++ b/net/http/http_server_properties_impl.cc
@@ -92,7 +92,7 @@ url::SchemeHostPort canonical_server(kCanonicalScheme, canonical_suffix, kCanonicalPort); // If we already have a valid canonical server, we're done. - if (base::ContainsKey(canonical_alt_svc_map_, canonical_server) && + if (base::Contains(canonical_alt_svc_map_, canonical_server) && (alternative_service_map_.Peek( canonical_alt_svc_map_[canonical_server]) != alternative_service_map_.end())) {
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc index 3bca1d7..1413fd4 100644 --- a/net/http/http_stream_factory.cc +++ b/net/http/http_stream_factory.cc
@@ -256,8 +256,8 @@ PreconnectingProxyServer preconnecting_proxy_server(proxy_info.proxy_server(), privacy_mode); - if (base::ContainsKey(preconnecting_proxy_servers_, - preconnecting_proxy_server)) { + if (base::Contains(preconnecting_proxy_servers_, + preconnecting_proxy_server)) { UMA_HISTOGRAM_EXACT_LINEAR("Net.PreconnectSkippedToProxyServers", 1, 2); // Skip preconnect to the proxy server since we are already preconnecting // (probably via some other job). See https://crbug.com/682041 for details.
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc index 0994bf1..45e062f5 100644 --- a/net/http/http_stream_factory_job.cc +++ b/net/http/http_stream_factory_job.cc
@@ -362,10 +362,10 @@ // handled by the socket pools, using an HttpProxyConnectJob. if (proxy_info.is_quic()) return !using_ssl; - return (base::ContainsKey(session->params().origins_to_force_quic_on, - HostPortPair()) || - base::ContainsKey(session->params().origins_to_force_quic_on, - destination)) && + return (base::Contains(session->params().origins_to_force_quic_on, + HostPortPair()) || + base::Contains(session->params().origins_to_force_quic_on, + destination)) && proxy_info.is_direct() && origin_url.SchemeIs(url::kHttpsScheme); }
diff --git a/net/http/http_stream_factory_job_controller.cc b/net/http/http_stream_factory_job_controller.cc index ad0ad9d..3ec5177 100644 --- a/net/http/http_stream_factory_job_controller.cc +++ b/net/http/http_stream_factory_job_controller.cc
@@ -1243,7 +1243,7 @@ return true; std::string lowered_host = base::ToLowerASCII(host); - return base::ContainsKey(host_whitelist, lowered_host); + return base::Contains(host_whitelist, lowered_host); } } // namespace net
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc index b7a2bca..275553cd 100644 --- a/net/http/transport_security_state.cc +++ b/net/http/transport_security_state.cc
@@ -218,7 +218,7 @@ bool HashesIntersect(const HashValueVector& a, const HashValueVector& b) { for (const auto& hash : a) { - if (base::ContainsValue(b, hash)) + if (base::Contains(b, hash)) return true; } return false;
diff --git a/net/log/net_log.cc b/net/log/net_log.cc index 88b3fa8..d0074d7d 100644 --- a/net/log/net_log.cc +++ b/net/log/net_log.cc
@@ -191,7 +191,7 @@ bool NetLog::HasObserver(ThreadSafeObserver* observer) { lock_.AssertAcquired(); - return base::ContainsValue(observers_, observer); + return base::Contains(observers_, observer); } // static
diff --git a/net/quic/platform/impl/quic_map_util_impl.h b/net/quic/platform/impl/quic_map_util_impl.h index 2efde24..c25e1c4 100644 --- a/net/quic/platform/impl/quic_map_util_impl.h +++ b/net/quic/platform/impl/quic_map_util_impl.h
@@ -11,12 +11,12 @@ template <class Collection, class Key> bool QuicContainsKeyImpl(const Collection& collection, const Key& key) { - return base::ContainsKey(collection, key); + return base::Contains(collection, key); } template <typename Collection, typename Value> bool QuicContainsValueImpl(const Collection& collection, const Value& value) { - return base::ContainsValue(collection, value); + return base::Contains(collection, value); } } // namespace quic
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index c216b1f..be2baea 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -1012,12 +1012,12 @@ return; } - DCHECK(!base::ContainsKey(handles_, handle)); + DCHECK(!base::Contains(handles_, handle)); handles_.insert(handle); } void QuicChromiumClientSession::RemoveHandle(Handle* handle) { - DCHECK(base::ContainsKey(handles_, handle)); + DCHECK(base::Contains(handles_, handle)); handles_.erase(handle); }
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 9dfa951..cb11203 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -1284,7 +1284,7 @@ if (active_sessions_.empty()) return false; - if (base::ContainsKey(active_sessions_, session_key)) + if (base::Contains(active_sessions_, session_key)) return true; for (const auto& key_value : active_sessions_) { @@ -1450,7 +1450,7 @@ const quic::QuicServerId& server_id(key.server_id()); DCHECK(!HasActiveSession(key.session_key())); for (const IPEndPoint& address : address_list) { - if (!base::ContainsKey(ip_aliases_, address)) + if (!base::Contains(ip_aliases_, address)) continue; const SessionSet& sessions = ip_aliases_[address]; @@ -1515,7 +1515,7 @@ } ProcessGoingAwaySession(session, all_sessions_[session].server_id(), false); if (!aliases.empty()) { - DCHECK(base::ContainsKey(session_peer_ip_, session)); + DCHECK(base::Contains(session_peer_ip_, session)); const IPEndPoint peer_address = session_peer_ip_[session]; ip_aliases_[peer_address].erase(session); if (ip_aliases_[peer_address].empty()) @@ -1729,16 +1729,16 @@ // TODO(rtenneti): crbug.com/498823 - delete active_sessions_.empty() check. if (active_sessions_.empty()) return false; - return base::ContainsKey(active_sessions_, session_key); + return base::Contains(active_sessions_, session_key); } bool QuicStreamFactory::HasActiveJob(const QuicSessionKey& session_key) const { - return base::ContainsKey(active_jobs_, session_key); + return base::Contains(active_jobs_, session_key); } bool QuicStreamFactory::HasActiveCertVerifierJob( const quic::QuicServerId& server_id) const { - return base::ContainsKey(active_cert_verifier_jobs_, server_id); + return base::Contains(active_cert_verifier_jobs_, server_id); } int QuicStreamFactory::ConfigureSocket(DatagramClientSocket* socket, @@ -1921,7 +1921,7 @@ writer->set_delegate(*session); (*session)->Initialize(); - bool closed_during_initialize = !base::ContainsKey(all_sessions_, *session) || + bool closed_during_initialize = !base::Contains(all_sessions_, *session) || !(*session)->connection()->connected(); UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ClosedDuringInitializeSession", closed_during_initialize); @@ -1946,9 +1946,9 @@ session_aliases_[session].insert(key); const IPEndPoint peer_address = ToIPEndPoint(session->connection()->peer_address()); - DCHECK(!base::ContainsKey(ip_aliases_[peer_address], session)); + DCHECK(!base::Contains(ip_aliases_[peer_address], session)); ip_aliases_[peer_address].insert(session); - DCHECK(!base::ContainsKey(session_peer_ip_, session)); + DCHECK(!base::Contains(session_peer_ip_, session)); session_peer_ip_[session] = peer_address; }
diff --git a/net/reporting/reporting_cache_impl.cc b/net/reporting/reporting_cache_impl.cc index 01f343d..004a6bc 100644 --- a/net/reporting/reporting_cache_impl.cc +++ b/net/reporting/reporting_cache_impl.cc
@@ -53,7 +53,7 @@ // all remaining reports (doomed or not). for (auto it = reports_.begin(); it != reports_.end(); ++it) { ReportingReport* report = it->second.get(); - if (!base::ContainsKey(doomed_reports_, report)) + if (!base::Contains(doomed_reports_, report)) report->outcome = ReportingReport::Outcome::ERASED_REPORTING_SHUT_DOWN; report->RecordOutcome(now); } @@ -84,7 +84,7 @@ DCHECK_NE(nullptr, to_evict); // The newly-added report isn't pending, so even if all other reports are // pending, the cache should have a report to evict. - DCHECK(!base::ContainsKey(pending_reports_, to_evict)); + DCHECK(!base::Contains(pending_reports_, to_evict)); reports_[to_evict]->outcome = ReportingReport::Outcome::ERASED_EVICTED; RemoveReportInternal(to_evict); } @@ -96,7 +96,7 @@ std::vector<const ReportingReport*>* reports_out) const { reports_out->clear(); for (const auto& it : reports_) { - if (!base::ContainsKey(doomed_reports_, it.first)) + if (!base::Contains(doomed_reports_, it.first)) reports_out->push_back(it.second.get()); } } @@ -131,9 +131,9 @@ if (report->body) { report_dict.SetKey("body", report->body->Clone()); } - if (base::ContainsKey(doomed_reports_, report)) { + if (base::Contains(doomed_reports_, report)) { report_dict.SetKey("status", base::Value("doomed")); - } else if (base::ContainsKey(pending_reports_, report)) { + } else if (base::Contains(pending_reports_, report)) { report_dict.SetKey("status", base::Value("pending")); } else { report_dict.SetKey("status", base::Value("queued")); @@ -147,8 +147,8 @@ std::vector<const ReportingReport*>* reports_out) const { reports_out->clear(); for (const auto& it : reports_) { - if (!base::ContainsKey(pending_reports_, it.first) && - !base::ContainsKey(doomed_reports_, it.first)) { + if (!base::Contains(pending_reports_, it.first) && + !base::Contains(doomed_reports_, it.first)) { reports_out->push_back(it.second.get()); } } @@ -169,7 +169,7 @@ for (const ReportingReport* report : reports) { size_t erased = pending_reports_.erase(report); DCHECK_EQ(1u, erased); - if (base::ContainsKey(doomed_reports_, report)) { + if (base::Contains(doomed_reports_, report)) { reports_to_remove.push_back(report); doomed_reports_.erase(report); } @@ -182,7 +182,7 @@ void ReportingCacheImpl::IncrementReportsAttempts( const std::vector<const ReportingReport*>& reports) { for (const ReportingReport* report : reports) { - DCHECK(base::ContainsKey(reports_, report)); + DCHECK(base::Contains(reports_, report)); reports_[report]->attempts++; } @@ -216,10 +216,10 @@ ReportingReport::Outcome outcome) { for (const ReportingReport* report : reports) { reports_[report]->outcome = outcome; - if (base::ContainsKey(pending_reports_, report)) { + if (base::Contains(pending_reports_, report)) { doomed_reports_.insert(report); } else { - DCHECK(!base::ContainsKey(doomed_reports_, report)); + DCHECK(!base::Contains(doomed_reports_, report)); RemoveReportInternal(report); } } @@ -232,7 +232,7 @@ for (auto it = reports_.begin(); it != reports_.end(); ++it) { ReportingReport* report = it->second.get(); report->outcome = outcome; - if (!base::ContainsKey(pending_reports_, report)) + if (!base::Contains(pending_reports_, report)) reports_to_remove.push_back(report); else doomed_reports_.insert(report); @@ -250,12 +250,12 @@ bool ReportingCacheImpl::IsReportPendingForTesting( const ReportingReport* report) const { - return base::ContainsKey(pending_reports_, report); + return base::Contains(pending_reports_, report); } bool ReportingCacheImpl::IsReportDoomedForTesting( const ReportingReport* report) const { - return base::ContainsKey(doomed_reports_, report); + return base::Contains(doomed_reports_, report); } void ReportingCacheImpl::OnParsedHeader( @@ -411,7 +411,7 @@ // Client for a superdomain of |origin| const OriginClient& client = client_it->second; // Check if |client| has a group with the requested name. - if (!base::ContainsKey(client.endpoint_group_names, group_name)) + if (!base::Contains(client.endpoint_group_names, group_name)) continue; ReportingEndpointGroupKey group_key(client.origin, group_name); @@ -576,7 +576,7 @@ for (const auto& it : reports_) { const ReportingReport* report = it.first; - if (base::ContainsKey(pending_reports_, report)) + if (base::Contains(pending_reports_, report)) continue; if (!earliest_queued || report->queued < earliest_queued->queued) { earliest_queued = report; @@ -601,7 +601,7 @@ total_endpoint_group_count += SanityCheckOriginClient(domain, client); // We have not seen a duplicate client with the same origin. - DCHECK(!base::ContainsKey(origins_in_cache, client.origin)); + DCHECK(!base::Contains(origins_in_cache, client.origin)); origins_in_cache.insert(client.origin); } @@ -672,7 +672,7 @@ // We have not seen a duplicate endpoint with the same URL in this // group. - DCHECK(!base::ContainsKey(endpoint_urls_in_group, endpoint.info.url)); + DCHECK(!base::Contains(endpoint_urls_in_group, endpoint.info.url)); endpoint_urls_in_group.insert(endpoint.info.url); ++endpoint_count_in_group; @@ -693,14 +693,14 @@ DCHECK_LE(0, endpoint.info.weight); // The endpoint is in the |endpoint_its_by_url_| index. - DCHECK(base::ContainsKey(endpoint_its_by_url_, endpoint.info.url)); + DCHECK(base::Contains(endpoint_its_by_url_, endpoint.info.url)); auto url_range = endpoint_its_by_url_.equal_range(endpoint.info.url); std::vector<EndpointMap::iterator> endpoint_its_for_url; for (auto index_it = url_range.first; index_it != url_range.second; ++index_it) { endpoint_its_for_url.push_back(index_it->second); } - DCHECK(base::ContainsValue(endpoint_its_for_url, endpoint_it)); + DCHECK(base::Contains(endpoint_its_for_url, endpoint_it)); #endif // DCHECK_IS_ON() } @@ -822,7 +822,7 @@ const auto group_range = endpoints_.equal_range(group_key); for (auto it = group_range.first; it != group_range.second;) { - if (base::ContainsKey(endpoints_to_keep_urls, it->second.info.url)) { + if (base::Contains(endpoints_to_keep_urls, it->second.info.url)) { ++it; continue; }
diff --git a/net/reporting/reporting_delivery_agent.cc b/net/reporting/reporting_delivery_agent.cc index 2745caf..31bfde7a 100644 --- a/net/reporting/reporting_delivery_agent.cc +++ b/net/reporting/reporting_delivery_agent.cc
@@ -170,7 +170,7 @@ const url::Origin& report_origin = origin_group.first; const std::string& group = origin_group.second; - if (base::ContainsKey(pending_origin_groups_, origin_group)) + if (base::Contains(pending_origin_groups_, origin_group)) continue; const ReportingEndpoint endpoint =
diff --git a/net/reporting/reporting_endpoint_manager.cc b/net/reporting/reporting_endpoint_manager.cc index ec6f3863..ed3452d 100644 --- a/net/reporting/reporting_endpoint_manager.cc +++ b/net/reporting/reporting_endpoint_manager.cc
@@ -50,7 +50,7 @@ int total_weight = 0; for (const ReportingEndpoint endpoint : endpoints) { - if (base::ContainsKey(endpoint_backoff_, endpoint.info.url) && + if (base::Contains(endpoint_backoff_, endpoint.info.url) && endpoint_backoff_[endpoint.info.url]->ShouldRejectRequest()) { continue; } @@ -102,7 +102,7 @@ } void InformOfEndpointRequest(const GURL& endpoint, bool succeeded) override { - if (!base::ContainsKey(endpoint_backoff_, endpoint)) { + if (!base::Contains(endpoint_backoff_, endpoint)) { endpoint_backoff_[endpoint] = std::make_unique<BackoffEntry>( &policy().endpoint_backoff_policy, tick_clock()); }
diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc index 3a1fb846..a69add8a5 100644 --- a/net/socket/transport_client_socket_pool.cc +++ b/net/socket/transport_client_socket_pool.cc
@@ -225,14 +225,14 @@ void TransportClientSocketPool::AddHigherLayeredPool( HigherLayeredPool* higher_pool) { CHECK(higher_pool); - CHECK(!base::ContainsKey(higher_pools_, higher_pool)); + CHECK(!base::Contains(higher_pools_, higher_pool)); higher_pools_.insert(higher_pool); } void TransportClientSocketPool::RemoveHigherLayeredPool( HigherLayeredPool* higher_pool) { CHECK(higher_pool); - CHECK(base::ContainsKey(higher_pools_, higher_pool)); + CHECK(base::Contains(higher_pools_, higher_pool)); higher_pools_.erase(higher_pool); } @@ -329,11 +329,11 @@ rv = RequestSocketInternal(group_id, request); if (rv < 0 && rv != ERR_IO_PENDING) { // We're encountering a synchronous error. Give up. - if (!base::ContainsKey(group_map_, group_id)) + if (!base::Contains(group_map_, group_id)) deleted_group = true; break; } - if (!base::ContainsKey(group_map_, group_id)) { + if (!base::Contains(group_map_, group_id)) { // Unexpected. The group should only be getting deleted on synchronous // error. NOTREACHED(); @@ -537,7 +537,7 @@ RequestPriority priority) { auto group_it = group_map_.find(group_id); if (group_it == group_map_.end()) { - DCHECK(base::ContainsKey(pending_callback_map_, handle)); + DCHECK(base::Contains(pending_callback_map_, handle)); // The Request has already completed and been destroyed; nothing to // reprioritize. return; @@ -570,7 +570,7 @@ return; } - CHECK(base::ContainsKey(group_map_, group_id)); + CHECK(base::Contains(group_map_, group_id)); Group* group = GetOrCreateGroup(group_id); std::unique_ptr<Request> request = group->FindAndRemoveBoundRequest(handle); @@ -633,7 +633,7 @@ LoadState TransportClientSocketPool::GetLoadState( const GroupId& group_id, const ClientSocketHandle* handle) const { - if (base::ContainsKey(pending_callback_map_, handle)) + if (base::Contains(pending_callback_map_, handle)) return LOAD_STATE_CONNECTING; auto group_it = group_map_.find(group_id); @@ -798,7 +798,7 @@ } bool TransportClientSocketPool::HasGroup(const GroupId& group_id) const { - return base::ContainsKey(group_map_, group_id); + return base::Contains(group_map_, group_id); } void TransportClientSocketPool::CleanupIdleSockets(bool force) { @@ -1023,7 +1023,7 @@ void TransportClientSocketPool::OnAvailableSocketSlot(const GroupId& group_id, Group* group) { - DCHECK(base::ContainsKey(group_map_, group_id)); + DCHECK(base::Contains(group_map_, group_id)); if (group->IsEmpty()) { RemoveGroup(group_id); } else if (group->has_unbound_requests()) { @@ -1295,7 +1295,7 @@ CompletionOnceCallback callback, int rv, const SocketTag& socket_tag) { - CHECK(!base::ContainsKey(pending_callback_map_, handle)); + CHECK(!base::Contains(pending_callback_map_, handle)); pending_callback_map_[handle] = CallbackResultPair(std::move(callback), rv); if (rv == OK) { handle->socket()->ApplySocketTag(socket_tag);
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 6e71a07..e04bb62 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -959,12 +959,10 @@ NetLogEventType::HTTP2_SESSION, base::Bind(&NetLogSpdySessionCallback, &host_port_proxy_pair())); + DCHECK(base::Contains(initial_settings_, spdy::SETTINGS_HEADER_TABLE_SIZE)); DCHECK( - base::ContainsKey(initial_settings_, spdy::SETTINGS_HEADER_TABLE_SIZE)); - DCHECK(base::ContainsKey(initial_settings_, - spdy::SETTINGS_MAX_CONCURRENT_STREAMS)); - DCHECK( - base::ContainsKey(initial_settings_, spdy::SETTINGS_INITIAL_WINDOW_SIZE)); + base::Contains(initial_settings_, spdy::SETTINGS_MAX_CONCURRENT_STREAMS)); + DCHECK(base::Contains(initial_settings_, spdy::SETTINGS_INITIAL_WINDOW_SIZE)); if (greased_http2_frame_) { // See https://tools.ietf.org/html/draft-bishop-httpbis-grease-00 @@ -1335,7 +1333,7 @@ } bool SpdySession::IsStreamActive(spdy::SpdyStreamId stream_id) const { - return base::ContainsKey(active_streams_, stream_id); + return base::Contains(active_streams_, stream_id); } LoadState SpdySession::GetLoadState() const {
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index 0d527b6..924c40c1a 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc
@@ -496,7 +496,7 @@ weak_ptr_factory_.GetWeakPtr(), request->key())); } - DCHECK(base::ContainsKey(iter->second.request_set, request)); + DCHECK(base::Contains(iter->second.request_set, request)); RemoveRequestInternal(iter, iter->second.request_set.find(request)); } @@ -563,7 +563,7 @@ void SpdySessionPool::MapKeyToAvailableSession( const SpdySessionKey& key, const base::WeakPtr<SpdySession>& session) { - DCHECK(base::ContainsKey(sessions_, session.get())); + DCHECK(base::Contains(sessions_, session.get())); std::pair<AvailableSessionMap::iterator, bool> result = available_sessions_.insert(std::make_pair(key, session)); CHECK(result.second);
diff --git a/net/tools/quic/quic_http_proxy_backend_stream.cc b/net/tools/quic/quic_http_proxy_backend_stream.cc index b247cf6..9aecf83 100644 --- a/net/tools/quic/quic_http_proxy_backend_stream.cc +++ b/net/tools/quic/quic_http_proxy_backend_stream.cc
@@ -147,7 +147,7 @@ // Ignore the spdy headers if (!key.empty() && key[0] != ':') { // Remove hop-by-hop headers - if (base::ContainsKey(kHopHeaders, key)) { + if (base::Contains(kHopHeaders, key)) { LOG(INFO) << "QUIC Proxy Ignoring Hop-by-hop Request Header: " << key << ":" << value; } else { @@ -371,7 +371,7 @@ if (header_name.compare("status") != 0) { if (header_name.compare("content-encoding") != 0) { // Remove hop-by-hop headers - if (base::ContainsKey(kHopHeaders, header_name)) { + if (base::Contains(kHopHeaders, header_name)) { LOG(INFO) << "Quic Proxy Ignoring Hop-by-hop Response Header: " << header_name << ":" << header_value; } else {
diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc index f805da8..a6c1740 100644 --- a/net/url_request/url_fetcher_core.cc +++ b/net/url_request/url_fetcher_core.cc
@@ -47,12 +47,12 @@ URLFetcherCore::Registry::~Registry() = default; void URLFetcherCore::Registry::AddURLFetcherCore(URLFetcherCore* core) { - DCHECK(!base::ContainsKey(fetchers_, core)); + DCHECK(!base::Contains(fetchers_, core)); fetchers_.insert(core); } void URLFetcherCore::Registry::RemoveURLFetcherCore(URLFetcherCore* core) { - DCHECK(base::ContainsKey(fetchers_, core)); + DCHECK(base::Contains(fetchers_, core)); fetchers_.erase(core); }
diff --git a/net/url_request/url_request_job_factory_impl.cc b/net/url_request/url_request_job_factory_impl.cc index c98a0b24..ad38c62 100644 --- a/net/url_request/url_request_job_factory_impl.cc +++ b/net/url_request/url_request_job_factory_impl.cc
@@ -36,7 +36,7 @@ return true; } - if (base::ContainsKey(protocol_handler_map_, scheme)) + if (base::Contains(protocol_handler_map_, scheme)) return false; protocol_handler_map_[scheme] = std::move(protocol_handler); return true; @@ -76,7 +76,7 @@ bool URLRequestJobFactoryImpl::IsHandledProtocol( const std::string& scheme) const { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return base::ContainsKey(protocol_handler_map_, scheme) || + return base::Contains(protocol_handler_map_, scheme) || URLRequestJobManager::GetInstance()->SupportsScheme(scheme); }
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 4646cf10..ecea7cb 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -8060,6 +8060,8 @@ // If the feature isn't enabled, a long `referer` will remain long. TestDelegate d; + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(features::kCapRefererHeaderLength); std::unique_ptr<URLRequest> req(default_context().CreateRequest( http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
diff --git a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc index e2bc055..7f8ac8e 100644 --- a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc +++ b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
@@ -7,7 +7,6 @@ #include "base/stl_util.h" #include "base/strings/pattern.h" #include "base/strings/strcat.h" -#include "base/threading/thread_id_name_manager.h" #include "base/trace_event/common/trace_event_common.h" #include "base/trace_event/trace_buffer.h" #include "base/trace_event/trace_log.h" @@ -170,9 +169,13 @@ interned_source_locations_(1000), process_id_(TraceLog::GetInstance()->process_id()), thread_id_(static_cast<int>(base::PlatformThread::CurrentId())), - privacy_filtering_enabled_(proto_writer_filtering_enabled) {} + privacy_filtering_enabled_(proto_writer_filtering_enabled) { + base::ThreadIdNameManager::GetInstance()->AddObserver(this); +} -TrackEventThreadLocalEventSink::~TrackEventThreadLocalEventSink() {} +TrackEventThreadLocalEventSink::~TrackEventThreadLocalEventSink() { + base::ThreadIdNameManager::GetInstance()->RemoveObserver(this); +} // static void TrackEventThreadLocalEventSink::ClearIncrementalState() { @@ -503,25 +506,29 @@ trace_writer_->Flush(); } -void TrackEventThreadLocalEventSink::DoResetIncrementalState( - base::trace_event::TraceEvent* trace_event, - bool explicit_timestamp) { - interned_event_categories_.ResetEmittedState(); - interned_event_names_.ResetEmittedState(); - interned_annotation_names_.ResetEmittedState(); - interned_source_locations_.ResetEmittedState(); - - // Emit a new thread descriptor in a separate packet, where we also set - // the |reset_incremental_state| field. +void TrackEventThreadLocalEventSink::OnThreadNameChanged(const char* name) { + if (thread_id_ != static_cast<int>(base::PlatformThread::CurrentId())) + return; auto trace_packet = trace_writer_->NewTracePacket(); - trace_packet->set_incremental_state_cleared(true); - auto* thread_descriptor = trace_packet->set_thread_descriptor(); + EmitThreadDescriptor(&trace_packet, nullptr, true, name); +} + +void TrackEventThreadLocalEventSink::EmitThreadDescriptor( + protozero::MessageHandle<perfetto::protos::pbzero::TracePacket>* + trace_packet, + base::trace_event::TraceEvent* trace_event, + bool explicit_timestamp, + const char* maybe_new_name) { + auto* thread_descriptor = (*trace_packet)->set_thread_descriptor(); thread_descriptor->set_pid(process_id_); thread_descriptor->set_tid(thread_id_); - const char* const maybe_new_name = - base::ThreadIdNameManager::GetInstance()->GetName(thread_id_); - if (maybe_new_name && base::StringPiece(thread_name_) != maybe_new_name) { + if (!maybe_new_name) { + maybe_new_name = + base::ThreadIdNameManager::GetInstance()->GetNameForCurrentThread(); + } + if (maybe_new_name && *maybe_new_name && + base::StringPiece(thread_name_) != maybe_new_name) { thread_name_ = maybe_new_name; thread_type_ = GetThreadType(maybe_new_name); } @@ -530,13 +537,13 @@ } thread_descriptor->set_chrome_thread_type(thread_type_); - if (explicit_timestamp) { + if (explicit_timestamp || !trace_event) { // Don't use a user-provided timestamp as a reference timestamp. last_timestamp_ = TRACE_TIME_TICKS_NOW(); } else { last_timestamp_ = trace_event->timestamp(); } - if (trace_event->thread_timestamp().is_null()) { + if (!trace_event || trace_event->thread_timestamp().is_null()) { last_thread_time_ = ThreadNow(); } else { // Thread timestamp is never user-provided. @@ -548,7 +555,21 @@ thread_descriptor->set_reference_thread_time_us( last_thread_time_.since_origin().InMicroseconds()); // TODO(eseckler): Fill in remaining fields in ThreadDescriptor. +} +void TrackEventThreadLocalEventSink::DoResetIncrementalState( + base::trace_event::TraceEvent* trace_event, + bool explicit_timestamp) { + interned_event_categories_.ResetEmittedState(); + interned_event_names_.ResetEmittedState(); + interned_annotation_names_.ResetEmittedState(); + interned_source_locations_.ResetEmittedState(); + + // Emit a new thread descriptor in a separate packet, where we also set + // the |incremental_state_cleared| flag. + auto trace_packet = trace_writer_->NewTracePacket(); + trace_packet->set_incremental_state_cleared(true); + EmitThreadDescriptor(&trace_packet, trace_event, explicit_timestamp); reset_incremental_state_ = false; }
diff --git a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h index b672375..5519857 100644 --- a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h +++ b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h
@@ -11,6 +11,7 @@ #include <utility> #include "base/component_export.h" +#include "base/threading/thread_id_name_manager.h" #include "base/time/time.h" #include "services/tracing/public/cpp/perfetto/interning_index.h" #include "services/tracing/public/cpp/perfetto/thread_local_event_sink.h" @@ -26,7 +27,8 @@ // ThreadLocalEventSink that emits TrackEvent protos. class COMPONENT_EXPORT(TRACING_CPP) TrackEventThreadLocalEventSink - : public ThreadLocalEventSink { + : public ThreadLocalEventSink, + public base::ThreadIdNameManager::Observer { public: TrackEventThreadLocalEventSink( std::unique_ptr<perfetto::StartupTraceWriter> trace_writer, @@ -47,9 +49,18 @@ const base::ThreadTicks& thread_now) override; void Flush() override; + // ThreadIdNameManager::Observer implementation: + void OnThreadNameChanged(const char* name) override; + private: static constexpr size_t kMaxCompleteEventDepth = 30; + void EmitThreadDescriptor( + protozero::MessageHandle<perfetto::protos::pbzero::TracePacket>* + trace_packet, + base::trace_event::TraceEvent* trace_event, + bool explicit_timestamp, + const char* maybe_new_name = nullptr); void DoResetIncrementalState(base::trace_event::TraceEvent* trace_event, bool explicit_timestamp);
diff --git a/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom b/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom index 4e91f18..2c767f91 100644 --- a/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom +++ b/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom
@@ -5,6 +5,7 @@ module viz.mojom; import "mojo/public/mojom/base/time.mojom"; +import "mojo/public/mojom/base/shared_memory.mojom"; import "services/viz/public/interfaces/compositing/begin_frame_args.mojom"; import "services/viz/public/interfaces/compositing/compositor_frame.mojom"; import "services/viz/public/interfaces/compositing/local_surface_id.mojom"; @@ -67,7 +68,8 @@ // The |id| can then be used in subsequent CompositorFrames given to // SubmitCompositorFrame. The |id| is a Mailbox type which doubles as a // SharedBitmapId for this case. - DidAllocateSharedBitmap(handle<shared_buffer> buffer, gpu.mojom.Mailbox id); + DidAllocateSharedBitmap(mojo_base.mojom.ReadOnlySharedMemoryRegion region, + gpu.mojom.Mailbox id); // Informs the display compositor that the client deleted a shared bitmap. This // allows the service to free the shared memory that was previously given to it
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 00a4ab24..cb4ff6b0 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1027,6 +1027,25 @@ ] } ], + "AutofillUseMobileLabelDisambiguation": [ + { + "platforms": [ + "android", + "ios" + ], + "experiments": [ + { + "name": "Enabled_ShowAll", + "params": { + "variant": "show-all" + }, + "enable_features": [ + "AutofillUseMobileLabelDisambiguation" + ] + } + ] + } + ], "AutomaticTabDiscarding": [ { "platforms": [
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index bacd5d5..57c25c1 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -148,6 +148,7 @@ "platform/modules/mediastream/web_media_stream_video_renderer.h", "platform/modules/mediastream/web_platform_media_stream_source.h", "platform/modules/mediastream/web_platform_media_stream_track.h", + "platform/modules/mediastream/webaudio_media_stream_source.h", "platform/modules/mediastream/webrtc_uma_histograms.h", "platform/modules/push_messaging/web_push_error.h", "platform/modules/push_messaging/web_push_subscription.h",
diff --git a/content/renderer/media/stream/webaudio_media_stream_source.h b/third_party/blink/public/platform/modules/mediastream/webaudio_media_stream_source.h similarity index 78% rename from content/renderer/media/stream/webaudio_media_stream_source.h rename to third_party/blink/public/platform/modules/mediastream/webaudio_media_stream_source.h index 99ab9b4..ace9be0 100644 --- a/content/renderer/media/stream/webaudio_media_stream_source.h +++ b/third_party/blink/public/platform/modules/mediastream/webaudio_media_stream_source.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 CONTENT_RENDERER_MEDIA_STREAM_WEBAUDIO_MEDIA_STREAM_SOURCE_H_ -#define CONTENT_RENDERER_MEDIA_STREAM_WEBAUDIO_MEDIA_STREAM_SOURCE_H_ +#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIASTREAM_WEBAUDIO_MEDIA_STREAM_SOURCE_H_ +#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIASTREAM_WEBAUDIO_MEDIA_STREAM_SOURCE_H_ #include <memory> @@ -12,21 +12,22 @@ #include "media/base/audio_push_fifo.h" #include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h" #include "third_party/blink/public/platform/web_audio_destination_consumer.h" +#include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_media_stream_source.h" #include "third_party/blink/public/platform/web_vector.h" -namespace content { +namespace blink { // Implements the WebAudioDestinationConsumer interface to provide a source of // audio data (i.e., the output from a graph of WebAudio nodes) to one or more // MediaStreamAudioTracks. Audio data is transported directly to the tracks in // 10 ms chunks. -class WebAudioMediaStreamSource final - : public blink::MediaStreamAudioSource, - public blink::WebAudioDestinationConsumer { +class BLINK_PLATFORM_EXPORT WebAudioMediaStreamSource final + : public MediaStreamAudioSource, + public WebAudioDestinationConsumer { public: WebAudioMediaStreamSource( - blink::WebMediaStreamSource* blink_source, + WebMediaStreamSource* blink_source, scoped_refptr<base::SingleThreadTaskRunner> task_runner); ~WebAudioMediaStreamSource() override; @@ -38,7 +39,7 @@ // concurrently across threads, but these methods could be called on any // thread. void SetFormat(size_t number_of_channels, float sample_rate) override; - void ConsumeAudio(const blink::WebVector<const float*>& audio_data, + void ConsumeAudio(const WebVector<const float*>& audio_data, size_t number_of_frames) override; // Called by AudioPushFifo zero or more times during the call to @@ -72,13 +73,13 @@ // DeliverRebufferedAudio(). base::TimeTicks current_reference_time_; - // This object registers with a blink::WebMediaStreamSource. We keep track of + // This object registers with a WebMediaStreamSource. We keep track of // that in order to be able to deregister before stopping this source. - blink::WebMediaStreamSource blink_source_; + WebMediaStreamSource blink_source_; DISALLOW_COPY_AND_ASSIGN(WebAudioMediaStreamSource); }; -} // namespace content +} // namespace blink -#endif // CONTENT_RENDERER_MEDIA_STREAM_WEBAUDIO_MEDIA_STREAM_SOURCE_H_ +#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIASTREAM_WEBAUDIO_MEDIA_STREAM_SOURCE_H_
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index c7b31b0..5728950 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1868,7 +1868,6 @@ "html/custom/custom_element_upgrade_sorter_test.cc", "html/forms/email_input_type_test.cc", "html/forms/external_popup_menu_test.cc", - "html/forms/file_chooser_test.cc", "html/forms/file_input_type_test.cc", "html/forms/form_controller_test.cc", "html/forms/form_data_test.cc", @@ -2154,6 +2153,7 @@ "streams/readable_stream_test.cc", "streams/stream_promise_resolver_test.cc", "streams/test_underlying_source.h", + "streams/transferable_streams_test.cc", "streams/transform_stream_test.cc", "streams/writable_stream_test.cc", "style/border_value_test.cc",
diff --git a/third_party/blink/renderer/core/html/forms/file_chooser.h b/third_party/blink/renderer/core/html/forms/file_chooser.h index 594ee1c..1042c13f5 100644 --- a/third_party/blink/renderer/core/html/forms/file_chooser.h +++ b/third_party/blink/renderer/core/html/forms/file_chooser.h
@@ -96,7 +96,7 @@ // mojom::blink::FileChooser callback void DidChooseFiles(mojom::blink::FileChooserResultPtr result); - Persistent<FileChooserClient> client_; + WeakPersistent<FileChooserClient> client_; mojom::blink::FileChooserParamsPtr params_; Persistent<ChromeClientImpl> chrome_client_impl_; mojom::blink::FileChooserPtr file_chooser_;
diff --git a/third_party/blink/renderer/core/html/forms/file_chooser_test.cc b/third_party/blink/renderer/core/html/forms/file_chooser_test.cc deleted file mode 100644 index 321cd9f..0000000 --- a/third_party/blink/renderer/core/html/forms/file_chooser_test.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2019 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 "third_party/blink/renderer/core/html/forms/file_chooser.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/core/frame/frame_test_helpers.h" -#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" -#include "third_party/blink/renderer/core/html/forms/mock_file_chooser.h" -#include "third_party/blink/renderer/core/page/chrome_client_impl.h" - -namespace blink { - -class FileChooserTest : public testing::Test { - protected: - void SetUp() override { web_view_ = helper_.Initialize(); } - - frame_test_helpers::WebViewHelper helper_; - WebViewImpl* web_view_; -}; - -TEST_F(FileChooserTest, NotGarbageCollected) { - LocalFrame* frame = helper_.LocalMainFrame()->GetFrame(); - auto* client = MakeGarbageCollected<MockFileChooserClient>(frame); - mojom::blink::FileChooserParams params; - params.title = g_empty_string; - scoped_refptr<FileChooser> chooser = FileChooser::Create(client, params); - ThreadState::Current()->CollectAllGarbageForTesting(); - // This tests the nullness of FileChooser::client_. - EXPECT_TRUE(chooser->FrameOrNull()); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/html/forms/mock_file_chooser.h b/third_party/blink/renderer/core/html/forms/mock_file_chooser.h index ff28ea1..2058d12 100644 --- a/third_party/blink/renderer/core/html/forms/mock_file_chooser.h +++ b/third_party/blink/renderer/core/html/forms/mock_file_chooser.h
@@ -74,28 +74,5 @@ base::OnceClosure reached_callback_; }; -// A FileChooserClient which makes FileChooser::OpenFileChooser() success. -class MockFileChooserClient - : public GarbageCollectedFinalized<MockFileChooserClient>, - public FileChooserClient { - USING_GARBAGE_COLLECTED_MIXIN(MockFileChooserClient); - - public: - explicit MockFileChooserClient(LocalFrame* frame) : frame_(frame) {} - void Trace(Visitor* visitor) override { - visitor->Trace(frame_); - FileChooserClient::Trace(visitor); - } - - private: - // FilesChosen() and WillOpenPopup() are never called in the test. - void FilesChosen(FileChooserFileInfoList, const base::FilePath&) override {} - void WillOpenPopup() override {} - - LocalFrame* FrameOrNull() const override { return frame_; } - - Member<LocalFrame> frame_; -}; - } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_MOCK_FILE_CHOOSER_H_
diff --git a/third_party/blink/renderer/core/layout/README.md b/third_party/blink/renderer/core/layout/README.md index 7b2723b..e9add9f 100644 --- a/third_party/blink/renderer/core/layout/README.md +++ b/third_party/blink/renderer/core/layout/README.md
@@ -150,8 +150,8 @@ ## Coordinate Spaces -Layout and Paint work with and frequently refer to three main coordinate spaces -(really two, with one variant): +Layout and Paint work with and frequently refer to four coordinate spaces +(really two, with two variants): * Physical coordinates: Corresponds to physical direction of the output per the physical display (screen, printed page). Generally used for painting, thus @@ -180,6 +180,10 @@ look up the writing mode of an object. Performing computation on values known to be in this space can save on the overhead required to unflip/reflip. +* Logical coordinates without flipping inline direction: those are "logical + block coordinates", without considering text direction. Examples are + "LogicalLeft" and "LogicalRight". + Example with `writing-mode: vertical-rl; direction: ltr`: 'top' / 'start' side
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc index de67530..ad4c52d 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -4533,7 +4533,7 @@ void LayoutBlockFlow::SimplifiedNormalFlowInlineLayout() { DCHECK(ChildrenInline()); - ListHashSet<RootInlineBox*> line_boxes; + LinkedHashSet<RootInlineBox*> line_boxes; for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.AtEnd(); walker.Advance()) { LayoutObject* o = walker.Current().GetLayoutObject(); @@ -4553,7 +4553,7 @@ // FIXME: Glyph overflow will get lost in this case, but not really a big // deal. GlyphOverflowAndFallbackFontsMap text_box_data_map; - for (ListHashSet<RootInlineBox*>::const_iterator it = line_boxes.begin(); + for (LinkedHashSet<RootInlineBox*>::const_iterator it = line_boxes.begin(); it != line_boxes.end(); ++it) { RootInlineBox* box = *it; box->ComputeOverflow(box->LineTop(), box->LineBottom(), text_box_data_map); @@ -4563,7 +4563,7 @@ bool LayoutBlockFlow::RecalcInlineChildrenLayoutOverflow() { DCHECK(ChildrenInline()); bool children_layout_overflow_changed = false; - ListHashSet<RootInlineBox*> line_boxes; + LinkedHashSet<RootInlineBox*> line_boxes; for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.AtEnd(); walker.Advance()) { LayoutObject* layout_object = walker.Current().GetLayoutObject(); @@ -4583,7 +4583,7 @@ // FIXME: Glyph overflow will get lost in this case, but not really a big // deal. GlyphOverflowAndFallbackFontsMap text_box_data_map; - for (ListHashSet<RootInlineBox*>::const_iterator it = line_boxes.begin(); + for (LinkedHashSet<RootInlineBox*>::const_iterator it = line_boxes.begin(); it != line_boxes.end(); ++it) { RootInlineBox* box = *it; box->ClearKnownToHaveNoOverflow();
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.h b/third_party/blink/renderer/core/layout/layout_box_model_object.h index 23e65eb6..c2488d7 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.h +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.h
@@ -79,7 +79,7 @@ // // In order to fully understand LayoutBoxModelObject and the inherited classes, // we need to introduce the concept of coordinate systems. -// There is 3 main coordinate systems: +// There are 4 coordinate systems: // - physical coordinates: it is the coordinate system used for painting and // correspond to physical direction as seen on the physical display (screen, // printed page). In CSS, 'top', 'right', 'bottom', 'left' are all in physical @@ -119,6 +119,10 @@ // (e.g. InlineStart, BlockEnd) or physical (e.g. Top, Left), or the return // type is PhysicalRect. // +// - logical coordinates without flipping inline direction: those are "logical +// block coordinates", without considering text direction. Examples are +// "LogicalLeft" and "LogicalRight". +// // For more, see Source/core/layout/README.md ### Coordinate Spaces. class CORE_EXPORT LayoutBoxModelObject : public LayoutObject { public:
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc index 2154985..61bc163 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
@@ -230,6 +230,29 @@ EXPECT_TRUE(CanOpenDateTimeChooser()); } +// A FileChooserClient which makes FileChooser::OpenFileChooser() success. +class MockFileChooserClient + : public GarbageCollectedFinalized<MockFileChooserClient>, + public FileChooserClient { + USING_GARBAGE_COLLECTED_MIXIN(MockFileChooserClient); + + public: + explicit MockFileChooserClient(LocalFrame* frame) : frame_(frame) {} + void Trace(Visitor* visitor) override { + visitor->Trace(frame_); + FileChooserClient::Trace(visitor); + } + + private: + // FilesChosen() and WillOpenPopup() are never called in the test. + void FilesChosen(FileChooserFileInfoList, const base::FilePath&) override {} + void WillOpenPopup() override {} + + LocalFrame* FrameOrNull() const override { return frame_; } + + Member<LocalFrame> frame_; +}; + class FileChooserQueueTest : public testing::Test { protected: void SetUp() override {
diff --git a/third_party/blink/renderer/core/streams/BUILD.gn b/third_party/blink/renderer/core/streams/BUILD.gn index 24a5a05..d8c60b6 100644 --- a/third_party/blink/renderer/core/streams/BUILD.gn +++ b/third_party/blink/renderer/core/streams/BUILD.gn
@@ -30,6 +30,8 @@ "stream_algorithms.h", "stream_promise_resolver.cc", "stream_promise_resolver.h", + "transferable_streams.cc", + "transferable_streams.h", "transform_stream.cc", "transform_stream.h", "transform_stream_default_controller.cc",
diff --git a/third_party/blink/renderer/core/streams/README.md b/third_party/blink/renderer/core/streams/README.md index 6856924..1b845c20 100644 --- a/third_party/blink/renderer/core/streams/README.md +++ b/third_party/blink/renderer/core/streams/README.md
@@ -26,6 +26,8 @@ writable_stream_default_writer.idl writable_stream_native.cc writable_stream_native.h + transferable_streams.cc + transferable_streams.h transform_stream_default_controller.cc transform_stream_default_controller.h transform_stream_native.cc
diff --git a/third_party/blink/renderer/core/streams/readable_stream.cc b/third_party/blink/renderer/core/streams/readable_stream.cc index 8b787d6..e1088481 100644 --- a/third_party/blink/renderer/core/streams/readable_stream.cc +++ b/third_party/blink/renderer/core/streams/readable_stream.cc
@@ -60,11 +60,9 @@ ReadableStream* ReadableStream::Deserialize(ScriptState* script_state, MessagePort* port, ExceptionState& exception_state) { - // TODO(ricea): Implementation serialization for the native implementation. if (RuntimeEnabledFeatures::StreamsNativeEnabled()) { - exception_state.ThrowTypeError( - "serialization disabled because StreamsNative feature is enabled"); - return nullptr; + return ReadableStreamNative::Deserialize(script_state, port, + exception_state); } return ReadableStreamWrapper::Deserialize(script_state, port,
diff --git a/third_party/blink/renderer/core/streams/readable_stream_native.cc b/third_party/blink/renderer/core/streams/readable_stream_native.cc index d957c75..1828317 100644 --- a/third_party/blink/renderer/core/streams/readable_stream_native.cc +++ b/third_party/blink/renderer/core/streams/readable_stream_native.cc
@@ -15,6 +15,7 @@ #include "third_party/blink/renderer/core/streams/readable_stream_reader.h" #include "third_party/blink/renderer/core/streams/stream_algorithms.h" #include "third_party/blink/renderer/core/streams/stream_promise_resolver.h" +#include "third_party/blink/renderer/core/streams/transferable_streams.h" #include "third_party/blink/renderer/core/streams/underlying_source_base.h" #include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h" #include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h" @@ -30,13 +31,6 @@ namespace blink { -struct ReadableStreamNative::PipeOptions { - PipeOptions() = default; - bool prevent_close = false; - bool prevent_abort = false; - bool prevent_cancel = false; -}; - // PipeToEngine implements PipeTo(). All standard steps in this class come from // https://streams.spec.whatwg.org/#readable-stream-pipe-to // @@ -1394,7 +1388,43 @@ void ReadableStreamNative::Serialize(ScriptState* script_state, MessagePort* port, ExceptionState& exception_state) { - // TODO(ricea): Implement this. + if (IsLocked(this)) { + exception_state.ThrowTypeError("Cannot transfer a locked stream"); + return; + } + + auto* writable = + CreateCrossRealmTransformWritable(script_state, port, exception_state); + if (exception_state.HadException()) { + return; + } + + auto promise = PipeTo(script_state, this, writable, PipeOptions()); + promise.MarkAsHandled(); +} + +ReadableStreamNative* ReadableStreamNative::Deserialize( + ScriptState* script_state, + MessagePort* port, + ExceptionState& exception_state) { + // We need to execute JavaScript to call "Then" on v8::Promises. We will not + // run author code. + v8::Isolate::AllowJavascriptExecutionScope allow_js( + script_state->GetIsolate()); + auto* readable = + CreateCrossRealmTransformReadable(script_state, port, exception_state); + if (exception_state.HadException()) { + return nullptr; + } + return readable; +} + +ScriptPromise ReadableStreamNative::PipeTo(ScriptState* script_state, + ReadableStreamNative* readable, + WritableStreamNative* destination, + PipeOptions pipe_options) { + auto* engine = MakeGarbageCollected<PipeToEngine>(script_state, pipe_options); + return engine->Start(readable, destination); } v8::Local<v8::Value> ReadableStreamNative::GetStoredError( @@ -1409,14 +1439,6 @@ ReadableStream::Trace(visitor); } -ScriptPromise ReadableStreamNative::PipeTo(ScriptState* script_state, - ReadableStreamNative* readable, - WritableStreamNative* destination, - PipeOptions pipe_options) { - auto* engine = MakeGarbageCollected<PipeToEngine>(script_state, pipe_options); - return engine->Start(readable, destination); -} - // // Abstract Operations Used By Controllers //
diff --git a/third_party/blink/renderer/core/streams/readable_stream_native.h b/third_party/blink/renderer/core/streams/readable_stream_native.h index b2af17d4..9cd1fea 100644 --- a/third_party/blink/renderer/core/streams/readable_stream_native.h +++ b/third_party/blink/renderer/core/streams/readable_stream_native.h
@@ -30,6 +30,13 @@ // See https://streams.spec.whatwg.org/#rs-model for background. class ReadableStreamNative : public ReadableStream { public: + struct PipeOptions { + PipeOptions() = default; + bool prevent_close = false; + bool prevent_abort = false; + bool prevent_cancel = false; + }; + enum State : uint8_t { kReadable, kClosed, kErrored }; // Implements ReadableStream::Create() when this implementation is enabled. @@ -146,6 +153,10 @@ void Serialize(ScriptState*, MessagePort* port, ExceptionState&) override; + static ReadableStreamNative* Deserialize(ScriptState*, + MessagePort* port, + ExceptionState&); + bool IsBroken() const override { return false; } // @@ -162,6 +173,12 @@ return stream->reader_; } + // https://streams.spec.whatwg.org/#readable-stream-pipe-to + static ScriptPromise PipeTo(ScriptState*, + ReadableStreamNative*, + WritableStreamNative*, + PipeOptions); + // // Functions exported for use by TransformStream. Not part of the standard. // @@ -190,7 +207,6 @@ friend class ReadableStreamDefaultController; friend class ReadableStreamReader; - struct PipeOptions; class PipeToEngine; class ReadHandleImpl; class TeeEngine; @@ -204,12 +220,6 @@ bool for_author_code, ExceptionState&); - // https://streams.spec.whatwg.org/#readable-stream-pipe-to - static ScriptPromise PipeTo(ScriptState*, - ReadableStreamNative*, - WritableStreamNative*, - PipeOptions); - // https://streams.spec.whatwg.org/#readable-stream-add-read-request static StreamPromiseResolver* AddReadRequest(ScriptState*, ReadableStreamNative*);
diff --git a/third_party/blink/renderer/core/streams/readable_stream_reader.h b/third_party/blink/renderer/core/streams/readable_stream_reader.h index 3d5f8d3..6099dca 100644 --- a/third_party/blink/renderer/core/streams/readable_stream_reader.h +++ b/third_party/blink/renderer/core/streams/readable_stream_reader.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_READER_H_ #include "third_party/blink/renderer/bindings/core/v8/script_value.h" +#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "v8/include/v8.h" @@ -25,7 +26,7 @@ // with the standard, ReadableStreamDefaultReader is implemented by the // ReadableStreamReader class. // TODO(ricea): Refactor this when implementing ReadableStreamBYOBReader. -class ReadableStreamReader : public ScriptWrappable { +class CORE_EXPORT ReadableStreamReader : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public:
diff --git a/third_party/blink/renderer/core/streams/readable_stream_test.cc b/third_party/blink/renderer/core/streams/readable_stream_test.cc index 656da9d..2217f82 100644 --- a/third_party/blink/renderer/core/streams/readable_stream_test.cc +++ b/third_party/blink/renderer/core/streams/readable_stream_test.cc
@@ -410,11 +410,6 @@ } TEST_P(ReadableStreamTest, Serialize) { - if (GetParam()) { - // Serialize() is not yet supported in the C++ implementation. - return; - } - ScopedTransferableStreamsForTest enabled(true); V8TestingScope scope;
diff --git a/third_party/blink/renderer/core/streams/transferable_streams.cc b/third_party/blink/renderer/core/streams/transferable_streams.cc new file mode 100644 index 0000000..ee7e1d25 --- /dev/null +++ b/third_party/blink/renderer/core/streams/transferable_streams.cc
@@ -0,0 +1,875 @@ +// Copyright 2019 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. + +// Functions for transferable streams. See design doc +// https://docs.google.com/document/d/1_KuZzg5c3pncLJPFa8SuVm23AP4tft6mzPCL5at3I9M/edit + +#include "third_party/blink/renderer/core/streams/transferable_streams.h" + +#include "base/stl_util.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" +#include "third_party/blink/renderer/core/dom/dom_exception.h" +#include "third_party/blink/renderer/core/dom/events/native_event_listener.h" +#include "third_party/blink/renderer/core/events/message_event.h" +#include "third_party/blink/renderer/core/messaging/message_port.h" +#include "third_party/blink/renderer/core/messaging/post_message_options.h" +#include "third_party/blink/renderer/core/streams/miscellaneous_operations.h" +#include "third_party/blink/renderer/core/streams/promise_handler.h" +#include "third_party/blink/renderer/core/streams/readable_stream_default_controller.h" +#include "third_party/blink/renderer/core/streams/readable_stream_native.h" +#include "third_party/blink/renderer/core/streams/stream_algorithms.h" +#include "third_party/blink/renderer/core/streams/stream_promise_resolver.h" +#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h" +#include "third_party/blink/renderer/core/streams/writable_stream_native.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "third_party/blink/renderer/platform/bindings/script_state.h" +#include "third_party/blink/renderer/platform/bindings/v8_binding.h" +#include "third_party/blink/renderer/platform/heap/heap.h" +#include "third_party/blink/renderer/platform/heap/visitor.h" +#include "third_party/blink/renderer/platform/wtf/assertions.h" +#include "v8/include/v8.h" + +// See the design doc at +// https://docs.google.com/document/d/1_KuZzg5c3pncLJPFa8SuVm23AP4tft6mzPCL5at3I9M/edit +// for explanation of how transferable streams are constructed from the "cross +// realm identity transform" implemented in this file. + +// The peer (the other end of the MessagePort) is untrusted as it may be +// compromised. This means we have to be very careful in unpacking the messages +// from the peer. LOG(WARNING) is used for cases where a message from the peer +// appears to be invalid. If this appears during ordinary testing it indicates a +// bug. +// +// The -vmodule=transferable_streams=3 command-line argument can be used for +// debugging of the protocol. + +namespace blink { + +namespace { + +// These are the types of messages that are sent between peers. +enum class MessageType { kPull, kCancel, kChunk, kClose, kAbort, kError }; + +// These are the different ways an error reason can be encoded. +enum class ErrorType { kTypeError, kJson, kDomException, kUndefined }; + +bool IsATypeError(ScriptState* script_state, v8::Local<v8::Object> object) { + // There isn't a 100% reliable way to identify a TypeError. + return object->IsNativeError() && + object->GetConstructorName() + ->Equals(script_state->GetContext(), + V8AtomicString(script_state->GetIsolate(), "TypeError")) + .ToChecked(); +} + +bool IsADOMException(v8::Isolate* isolate, v8::Local<v8::Object> object) { + return V8DOMException::HasInstance(object, isolate); +} + +// Creates a JavaScript object with a null prototype structured like {key1: +// value2, key2: value2}. This is used to create objects to be serialized by +// postMessage. +v8::Local<v8::Object> CreateKeyValueObject(v8::Isolate* isolate, + const char* key1, + v8::Local<v8::Value> value1, + const char* key2, + v8::Local<v8::Value> value2) { + v8::Local<v8::Name> names[] = {V8AtomicString(isolate, key1), + V8AtomicString(isolate, key2)}; + v8::Local<v8::Value> values[] = {value1, value2}; + static_assert(base::size(names) == base::size(values), + "names and values arrays must be the same size"); + return v8::Object::New(isolate, v8::Null(isolate), names, values, + base::size(names)); +} + +// Unpacks an object created by CreateKeyValueObject(). |value1| and |value2| +// are out parameters. Returns false on failure. +bool UnpackKeyValueObject(ScriptState* script_state, + v8::Local<v8::Object> object, + const char* key1, + v8::Local<v8::Value>* value1, + const char* key2, + v8::Local<v8::Value>* value2) { + auto* isolate = script_state->GetIsolate(); + v8::TryCatch try_catch(isolate); + auto context = script_state->GetContext(); + if (!object->Get(context, V8AtomicString(isolate, key1)).ToLocal(value1)) { + DLOG(WARNING) << "Error reading key: '" << key1 << "'"; + return false; + } + if (!object->Get(context, V8AtomicString(isolate, key2)).ToLocal(value2)) { + DLOG(WARNING) << "Error reading key: '" << key2 << "'"; + return false; + } + return true; +} + +// Send a message with type |type| and contents |value| over |port|. The type +// will be packed as a number with key "t", and the value will be packed with +// key "v". +void PackAndPostMessage(ScriptState* script_state, + MessagePort* port, + MessageType type, + v8::Local<v8::Value> value, + ExceptionState& exception_state) { + DVLOG(3) << "PackAndPostMessage sending message type " + << static_cast<int>(type); + auto* isolate = script_state->GetIsolate(); + v8::Local<v8::Object> packed = CreateKeyValueObject( + isolate, "t", v8::Number::New(isolate, static_cast<int>(type)), "v", + value); + port->postMessage(script_state, ScriptValue(script_state, packed), + PostMessageOptions::Create(), exception_state); +} + +// Packs an error into an {e: number, s: string} object for transmission by +// postMessage. Serializing the resulting object should never fail. +v8::Local<v8::Object> PackErrorType(v8::Isolate* isolate, + ErrorType type, + v8::Local<v8::String> string) { + auto error_as_number = v8::Number::New(isolate, static_cast<int>(type)); + return CreateKeyValueObject(isolate, "e", error_as_number, "s", string); +} + +// Overload for the common case where |string| is a compile-time constant. +v8::Local<v8::Object> PackErrorType(v8::Isolate* isolate, + ErrorType type, + const char* string) { + return PackErrorType(isolate, type, V8String(isolate, string)); +} + +// We'd like to able to transfer TypeError exceptions, but we can't, so we hack +// around it. PackReason() is guaranteed to succeed and the object produced is +// guaranteed to be serializable by postMessage(), however data may be lost. It +// is not very efficient, and has fairly arbitrary semantics. +// TODO(ricea): Replace once Errors are serializable. +v8::Local<v8::Value> PackReason(ScriptState* script_state, + v8::Local<v8::Value> reason) { + auto* isolate = script_state->GetIsolate(); + auto context = script_state->GetContext(); + if (reason->IsString() || reason->IsNumber() || reason->IsBoolean()) { + v8::TryCatch try_catch(isolate); + v8::Local<v8::String> stringified; + if (!v8::JSON::Stringify(context, reason).ToLocal(&stringified)) { + return PackErrorType(isolate, ErrorType::kTypeError, + "Cannot transfer message"); + } + + return PackErrorType(isolate, ErrorType::kJson, stringified); + } + + if (reason->IsFunction() || reason->IsSymbol() || + !(reason->IsObject() || reason->IsNull())) { + // Squash to undefined + return PackErrorType(isolate, ErrorType::kUndefined, ""); + } + + if (IsATypeError(script_state, reason.As<v8::Object>())) { + v8::TryCatch try_catch(isolate); + // "message" on TypeError is a normal property, meaning that if it + // is set, it is set on the object itself. We can take advantage of + // this to avoid executing user JavaScript in the case when the + // TypeError was generated internally. + v8::Local<v8::Value> descriptor; + if (!reason.As<v8::Object>() + ->GetOwnPropertyDescriptor(context, + V8AtomicString(isolate, "message")) + .ToLocal(&descriptor)) { + return PackErrorType(isolate, ErrorType::kTypeError, + "Cannot transfer message"); + } + if (descriptor->IsUndefined()) { + return PackErrorType(isolate, ErrorType::kTypeError, ""); + } + v8::Local<v8::Value> message; + CHECK(descriptor->IsObject()); + if (!descriptor.As<v8::Object>() + ->Get(context, V8AtomicString(isolate, "value")) + .ToLocal(&message)) { + message = V8String(isolate, "Cannot transfer message"); + } else if (!message->IsString()) { + message = V8String(isolate, ""); + } + return PackErrorType(isolate, ErrorType::kTypeError, + message.As<v8::String>()); + } + + if (IsADOMException(isolate, reason.As<v8::Object>())) { + DOMException* dom_exception = + V8DOMException::ToImpl(reason.As<v8::Object>()); + String message = dom_exception->message(); + String name = dom_exception->name(); + v8::Local<v8::Value> packed = CreateKeyValueObject( + isolate, "m", V8String(isolate, message), "n", V8String(isolate, name)); + // It should be impossible for this to fail, except for out-of-memory. + v8::Local<v8::String> packed_string = + v8::JSON::Stringify(context, packed).ToLocalChecked(); + return PackErrorType(isolate, ErrorType::kDomException, packed_string); + } + + v8::TryCatch try_catch(isolate); + v8::Local<v8::Value> json; + if (!v8::JSON::Stringify(context, reason).ToLocal(&json)) { + return PackErrorType(isolate, ErrorType::kTypeError, + "Cannot transfer message"); + } + + return PackErrorType(isolate, ErrorType::kJson, json.As<v8::String>()); +} + +// Converts an object created by PackReason() back into a clone of the original +// object, minus any data that was discarded by PackReason(). +bool UnpackReason(ScriptState* script_state, + v8::Local<v8::Value> packed_reason, + v8::Local<v8::Value>* reason) { + // We need to be robust against malformed input because it could come from a + // compromised renderer. + if (!packed_reason->IsObject()) { + DLOG(WARNING) << "packed_reason is not an object"; + return false; + } + + v8::Local<v8::Value> encoder_value; + v8::Local<v8::Value> string_value; + if (!UnpackKeyValueObject(script_state, packed_reason.As<v8::Object>(), "e", + &encoder_value, "s", &string_value)) { + return false; + } + + if (!encoder_value->IsNumber()) { + DLOG(WARNING) << "encoder_value is not a number"; + return false; + } + + int encoder = encoder_value.As<v8::Number>()->Value(); + if (!string_value->IsString()) { + DLOG(WARNING) << "string_value is not a string"; + return false; + } + + v8::Local<v8::String> string = string_value.As<v8::String>(); + auto* isolate = script_state->GetIsolate(); + auto context = script_state->GetContext(); + switch (static_cast<ErrorType>(encoder)) { + case ErrorType::kJson: { + v8::TryCatch try_catch(isolate); + if (!v8::JSON::Parse(context, string).ToLocal(reason)) { + DLOG(WARNING) << "JSON Parse failed. Content: " << ToCoreString(string); + return false; + } + return true; + } + + case ErrorType::kTypeError: + *reason = v8::Exception::TypeError(string); + return true; + + case ErrorType::kDomException: { + v8::TryCatch try_catch(isolate); + v8::Local<v8::Value> packed_exception; + if (!v8::JSON::Parse(context, string).ToLocal(&packed_exception)) { + DLOG(WARNING) << "Packed DOMException JSON parse failed"; + return false; + } + + if (!packed_exception->IsObject()) { + DLOG(WARNING) << "Packed DOMException is not an object"; + return false; + } + + v8::Local<v8::Value> message; + v8::Local<v8::Value> name; + if (!UnpackKeyValueObject(script_state, packed_exception.As<v8::Object>(), + "m", &message, "n", &name)) { + DLOG(WARNING) << "Failed unpacking packed DOMException"; + return false; + } + + if (!message->IsString()) { + DLOG(WARNING) << "DOMException message is not a string"; + return false; + } + + if (!name->IsString()) { + DLOG(WARNING) << "DOMException name is not a string"; + return false; + } + + auto ToBlink = [](v8::Local<v8::Value> value) { + return ToBlinkString<String>(value.As<v8::String>(), kDoNotExternalize); + }; + *reason = ToV8(DOMException::Create(ToBlink(message), ToBlink(name)), + script_state); + return true; + } + + case ErrorType::kUndefined: + *reason = v8::Undefined(isolate); + return true; + + default: + DLOG(WARNING) << "Invalid ErrorType: " << encoder; + return false; + } +} + +// Base class for CrossRealmTransformWritable and CrossRealmTransformReadable. +// Contains common methods that are used when handling MessagePort events. +class CrossRealmTransformStream + : public GarbageCollected<CrossRealmTransformStream> { + public: + // Neither of the subclasses require finalization, so no destructor. + + virtual ScriptState* GetScriptState() const = 0; + virtual MessagePort* GetMessagePort() const = 0; + + // HandleMessage() is called by CrossRealmTransformMessageListener to handle + // an incoming message from the MessagePort. + virtual void HandleMessage(MessageType type, v8::Local<v8::Value> value) = 0; + + // HandleError() is called by CrossRealmTransformErrorListener when an error + // event is fired on the message port. It should error the stream. + virtual void HandleError(v8::Local<v8::Value> error) = 0; + + virtual void Trace(Visitor*) {} +}; + +// Handles MessageEvents from the MessagePort. +class CrossRealmTransformMessageListener final : public NativeEventListener { + public: + explicit CrossRealmTransformMessageListener(CrossRealmTransformStream* target) + : target_(target) {} + + void Invoke(ExecutionContext*, Event* event) override { + // TODO(ricea): Find a way to guarantee this cast is safe. + MessageEvent* message = static_cast<MessageEvent*>(event); + ScriptState* script_state = target_->GetScriptState(); + // The deserializer code called by message->data() looks up the ScriptState + // from the current context, so we need to make sure it is set. + ScriptState::Scope scope(script_state); + v8::Local<v8::Value> data = message->data(script_state).V8Value(); + if (!data->IsObject()) { + DLOG(WARNING) << "Invalid message from peer ignored (not object)"; + return; + } + + v8::Local<v8::Value> type; + v8::Local<v8::Value> value; + if (!UnpackKeyValueObject(script_state, data.As<v8::Object>(), "t", &type, + "v", &value)) { + DLOG(WARNING) << "Invalid message from peer ignored"; + return; + } + + if (!type->IsNumber()) { + DLOG(WARNING) << "Invalid message from peer ignored (type is not number)"; + return; + } + + int type_value = type.As<v8::Number>()->Value(); + DVLOG(3) << "MessageListener saw message type " << type_value; + target_->HandleMessage(static_cast<MessageType>(type_value), value); + } + + void Trace(Visitor* visitor) override { + visitor->Trace(target_); + NativeEventListener::Trace(visitor); + } + + private: + const Member<CrossRealmTransformStream> target_; +}; + +// Handles "error" events from the MessagePort. +class CrossRealmTransformErrorListener final : public NativeEventListener { + public: + explicit CrossRealmTransformErrorListener(CrossRealmTransformStream* target) + : target_(target) {} + + void Invoke(ExecutionContext*, Event*) override { + ScriptState* script_state = target_->GetScriptState(); + const auto* error = + DOMException::Create("chunk could not be cloned", "DataCloneError"); + auto* message_port = target_->GetMessagePort(); + v8::Local<v8::Value> error_value = ToV8(error, script_state); + ExceptionState exception_state(script_state->GetIsolate(), + ExceptionState::kUnknownContext, "", ""); + + PackAndPostMessage(script_state, message_port, MessageType::kError, + PackReason(script_state, error_value), exception_state); + if (exception_state.HadException()) { + DLOG(WARNING) << "Ignoring postMessage failure in error listener"; + exception_state.ClearException(); + } + + message_port->close(); + target_->HandleError(error_value); + } + + void Trace(Visitor* visitor) override { + visitor->Trace(target_); + NativeEventListener::Trace(visitor); + } + + private: + const Member<CrossRealmTransformStream> target_; +}; + +// Class for data associated with the writable side of the cross realm transform +// stream. +class CrossRealmTransformWritable final : public CrossRealmTransformStream { + public: + CrossRealmTransformWritable(ScriptState* script_state, MessagePort* port) + : script_state_(script_state), + message_port_(port), + backpressure_promise_( + MakeGarbageCollected<StreamPromiseResolver>(script_state)) {} + + WritableStreamNative* CreateWritableStream(ExceptionState&); + + ScriptState* GetScriptState() const override { return script_state_; } + MessagePort* GetMessagePort() const override { return message_port_; } + void HandleMessage(MessageType type, v8::Local<v8::Value> value) override; + void HandleError(v8::Local<v8::Value> error) override; + + void Trace(Visitor* visitor) override { + visitor->Trace(script_state_); + visitor->Trace(message_port_); + visitor->Trace(backpressure_promise_); + visitor->Trace(controller_); + CrossRealmTransformStream::Trace(visitor); + } + + private: + class WriteAlgorithm; + class CloseAlgorithm; + class AbortAlgorithm; + + const Member<ScriptState> script_state_; + const Member<MessagePort> message_port_; + Member<StreamPromiseResolver> backpressure_promise_; + Member<WritableStreamDefaultController> controller_; +}; + +class CrossRealmTransformWritable::WriteAlgorithm final + : public StreamAlgorithm { + public: + explicit WriteAlgorithm(CrossRealmTransformWritable* writable) + : writable_(writable) {} + + // Sends the chunk to the readable side, possibly after waiting for + // backpressure. + v8::Local<v8::Promise> Run(ScriptState* script_state, + int argc, + v8::Local<v8::Value> argv[]) override { + DCHECK_EQ(argc, 1); + auto chunk = argv[0]; + + if (!writable_->backpressure_promise_) { + return DoWrite(script_state, chunk); + } + + auto* isolate = script_state->GetIsolate(); + return StreamThenPromise( + script_state->GetContext(), + writable_->backpressure_promise_->V8Promise(isolate), + MakeGarbageCollected<DoWriteOnResolve>(script_state, chunk, this)); + } + + void Trace(Visitor* visitor) override { + visitor->Trace(writable_); + StreamAlgorithm::Trace(visitor); + } + + private: + // A promise handler which calls DoWrite() when the promise resolves. + class DoWriteOnResolve final : public PromiseHandlerWithValue { + public: + DoWriteOnResolve(ScriptState* script_state, + v8::Local<v8::Value> chunk, + WriteAlgorithm* target) + : PromiseHandlerWithValue(script_state), + chunk_(script_state->GetIsolate(), chunk), + target_(target) {} + + v8::Local<v8::Value> CallWithLocal(v8::Local<v8::Value>) override { + ScriptState* script_state = GetScriptState(); + return target_->DoWrite(script_state, + chunk_.NewLocal(script_state->GetIsolate())); + } + + void Trace(Visitor* visitor) override { + visitor->Trace(chunk_); + visitor->Trace(target_); + PromiseHandlerWithValue::Trace(visitor); + } + + private: + const TraceWrapperV8Reference<v8::Value> chunk_; + const Member<WriteAlgorithm> target_; + }; + + // Sends a chunk over the message port to the readable side. + v8::Local<v8::Promise> DoWrite(ScriptState* script_state, + v8::Local<v8::Value> chunk) { + writable_->backpressure_promise_ = + MakeGarbageCollected<StreamPromiseResolver>(script_state); + ExceptionState exception_state(script_state->GetIsolate(), + ExceptionState::kUnknownContext, "", ""); + PackAndPostMessage(script_state, writable_->message_port_, + MessageType::kChunk, chunk, exception_state); + if (exception_state.HadException()) { + auto exception = exception_state.GetException(); + exception_state.ClearException(); + + PackAndPostMessage( + script_state, writable_->message_port_, MessageType::kError, + PackReason(writable_->script_state_, exception), exception_state); + if (exception_state.HadException()) { + DLOG(WARNING) << "Disregarding exception while sending error"; + exception_state.ClearException(); + } + + writable_->message_port_->close(); + return PromiseReject(script_state, exception); + } + + return PromiseResolveWithUndefined(script_state); + } + + const Member<CrossRealmTransformWritable> writable_; +}; + +class CrossRealmTransformWritable::CloseAlgorithm final + : public StreamAlgorithm { + public: + explicit CloseAlgorithm(CrossRealmTransformWritable* writable) + : writable_(writable) {} + + // Sends a close message to the readable side and closes the message port. + v8::Local<v8::Promise> Run(ScriptState* script_state, + int argc, + v8::Local<v8::Value> argv[]) override { + DCHECK_EQ(argc, 0); + ExceptionState exception_state(script_state->GetIsolate(), + ExceptionState::kUnknownContext, "", ""); + PackAndPostMessage( + script_state, writable_->message_port_, MessageType::kClose, + v8::Undefined(script_state->GetIsolate()), exception_state); + if (exception_state.HadException()) { + DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kClose"; + exception_state.ClearException(); + } + + writable_->message_port_->close(); + return PromiseResolveWithUndefined(script_state); + } + + void Trace(Visitor* visitor) override { + visitor->Trace(writable_); + StreamAlgorithm::Trace(visitor); + } + + private: + const Member<CrossRealmTransformWritable> writable_; +}; + +class CrossRealmTransformWritable::AbortAlgorithm final + : public StreamAlgorithm { + public: + explicit AbortAlgorithm(CrossRealmTransformWritable* writable) + : writable_(writable) {} + + // Sends an abort message to the readable side and closes the message port. + v8::Local<v8::Promise> Run(ScriptState* script_state, + int argc, + v8::Local<v8::Value> argv[]) override { + DCHECK_EQ(argc, 1); + auto reason = argv[0]; + ExceptionState exception_state(script_state->GetIsolate(), + ExceptionState::kUnknownContext, "", ""); + PackAndPostMessage( + script_state, writable_->message_port_, MessageType::kAbort, + PackReason(writable_->script_state_, reason), exception_state); + if (exception_state.HadException()) { + DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kAbort"; + exception_state.ClearException(); + } + writable_->message_port_->close(); + return PromiseResolveWithUndefined(script_state); + } + + void Trace(Visitor* visitor) override { + visitor->Trace(writable_); + StreamAlgorithm::Trace(visitor); + } + + private: + const Member<CrossRealmTransformWritable> writable_; +}; + +WritableStreamNative* CrossRealmTransformWritable::CreateWritableStream( + ExceptionState& exception_state) { + DCHECK(!controller_) << "CreateWritableStream() can only be called once"; + + message_port_->setOnmessage( + MakeGarbageCollected<CrossRealmTransformMessageListener>(this)); + message_port_->setOnmessageerror( + MakeGarbageCollected<CrossRealmTransformErrorListener>(this)); + + auto* stream = WritableStreamNative::Create( + script_state_, CreateTrivialStartAlgorithm(), + MakeGarbageCollected<WriteAlgorithm>(this), + MakeGarbageCollected<CloseAlgorithm>(this), + MakeGarbageCollected<AbortAlgorithm>(this), 1, + CreateDefaultSizeAlgorithm(), exception_state); + + if (exception_state.HadException()) { + return nullptr; + } + + controller_ = stream->Controller(); + return stream; +} + +void CrossRealmTransformWritable::HandleMessage(MessageType type, + v8::Local<v8::Value> value) { + switch (type) { + case MessageType::kPull: + DCHECK(backpressure_promise_); + backpressure_promise_->ResolveWithUndefined(script_state_); + backpressure_promise_ = nullptr; + return; + + case MessageType::kCancel: + case MessageType::kError: { + v8::Local<v8::Value> reason; + if (!UnpackReason(script_state_, value, &reason)) { + DLOG(WARNING) + << "Invalid message from peer ignored (unable to unpack value)"; + return; + } + WritableStreamDefaultController::ErrorIfNeeded(script_state_, controller_, + reason); + if (backpressure_promise_) { + backpressure_promise_->ResolveWithUndefined(script_state_); + backpressure_promise_ = nullptr; + } + return; + } + + default: + DLOG(WARNING) << "Invalid message from peer ignored (invalid type): " + << static_cast<int>(type); + return; + } +} + +void CrossRealmTransformWritable::HandleError(v8::Local<v8::Value> error) { + WritableStreamDefaultController::ErrorIfNeeded(script_state_, controller_, + error); +} + +// Class for data associated with the readable side of the cross realm transform +// stream. +class CrossRealmTransformReadable final : public CrossRealmTransformStream { + public: + CrossRealmTransformReadable(ScriptState* script_state, MessagePort* port) + : script_state_(script_state), + message_port_(port), + backpressure_promise_( + MakeGarbageCollected<StreamPromiseResolver>(script_state)) {} + + ReadableStreamNative* CreateReadableStream(ExceptionState&); + + ScriptState* GetScriptState() const override { return script_state_; } + MessagePort* GetMessagePort() const override { return message_port_; } + void HandleMessage(MessageType type, v8::Local<v8::Value> value) override; + void HandleError(v8::Local<v8::Value> error) override; + + void Trace(Visitor* visitor) override { + visitor->Trace(script_state_); + visitor->Trace(message_port_); + visitor->Trace(backpressure_promise_); + visitor->Trace(controller_); + CrossRealmTransformStream::Trace(visitor); + } + + private: + class PullAlgorithm; + class CancelAlgorithm; + + const Member<ScriptState> script_state_; + const Member<MessagePort> message_port_; + Member<StreamPromiseResolver> backpressure_promise_; + Member<ReadableStreamDefaultController> controller_; + bool finished_ = false; +}; + +class CrossRealmTransformReadable::PullAlgorithm final + : public StreamAlgorithm { + public: + explicit PullAlgorithm(CrossRealmTransformReadable* readable) + : readable_(readable) {} + + // Sends a pull message to the writable side and then waits for backpressure + // to clear. + v8::Local<v8::Promise> Run(ScriptState* script_state, + int argc, + v8::Local<v8::Value> argv[]) override { + DCHECK_EQ(argc, 0); + auto* isolate = script_state->GetIsolate(); + ExceptionState exception_state(isolate, ExceptionState::kUnknownContext, "", + ""); + + PackAndPostMessage( + script_state, readable_->message_port_, MessageType::kPull, + v8::Undefined(script_state->GetIsolate()), exception_state); + if (exception_state.HadException()) { + DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kClose"; + exception_state.ClearException(); + } + + return readable_->backpressure_promise_->V8Promise(isolate); + } + + void Trace(Visitor* visitor) override { + visitor->Trace(readable_); + StreamAlgorithm::Trace(visitor); + } + + private: + const Member<CrossRealmTransformReadable> readable_; +}; + +class CrossRealmTransformReadable::CancelAlgorithm final + : public StreamAlgorithm { + public: + explicit CancelAlgorithm(CrossRealmTransformReadable* readable) + : readable_(readable) {} + + // Sends a cancel message to the writable side and closes the message port. + v8::Local<v8::Promise> Run(ScriptState* script_state, + int argc, + v8::Local<v8::Value> argv[]) override { + DCHECK_EQ(argc, 1); + auto reason = argv[0]; + readable_->finished_ = true; + ExceptionState exception_state(script_state->GetIsolate(), + ExceptionState::kUnknownContext, "", ""); + + PackAndPostMessage(script_state, readable_->message_port_, + MessageType::kCancel, PackReason(script_state, reason), + exception_state); + if (exception_state.HadException()) { + DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kClose"; + exception_state.ClearException(); + } + + readable_->message_port_->close(); + return PromiseResolveWithUndefined(script_state); + } + + void Trace(Visitor* visitor) override { + visitor->Trace(readable_); + StreamAlgorithm::Trace(visitor); + } + + private: + const Member<CrossRealmTransformReadable> readable_; +}; + +ReadableStreamNative* CrossRealmTransformReadable::CreateReadableStream( + ExceptionState& exception_state) { + DCHECK(!controller_) << "CreateReadableStream can only be called once"; + + message_port_->setOnmessage( + MakeGarbageCollected<CrossRealmTransformMessageListener>(this)); + message_port_->setOnmessageerror( + MakeGarbageCollected<CrossRealmTransformErrorListener>(this)); + + auto* stream = ReadableStreamNative::Create( + script_state_, CreateTrivialStartAlgorithm(), + MakeGarbageCollected<PullAlgorithm>(this), + MakeGarbageCollected<CancelAlgorithm>(this), + /* highWaterMark = */ 0, CreateDefaultSizeAlgorithm(), exception_state); + + if (exception_state.HadException()) { + return nullptr; + } + + controller_ = stream->GetController(); + return stream; +} + +void CrossRealmTransformReadable::HandleMessage(MessageType type, + v8::Local<v8::Value> value) { + switch (type) { + case MessageType::kChunk: { + // This can't throw because we always use the default strategy size + // algorithm, which doesn't throw, and always returns a valid value of + // 1.0. + ReadableStreamDefaultController::Enqueue(script_state_, controller_, + value, ASSERT_NO_EXCEPTION); + + backpressure_promise_->ResolveWithUndefined(script_state_); + backpressure_promise_ = + MakeGarbageCollected<StreamPromiseResolver>(script_state_); + return; + } + + case MessageType::kClose: + finished_ = true; + ReadableStreamDefaultController::Close(script_state_, controller_); + message_port_->close(); + return; + + case MessageType::kAbort: + case MessageType::kError: { + finished_ = true; + v8::Local<v8::Value> reason; + if (!UnpackReason(script_state_, value, &reason)) { + DLOG(WARNING) + << "Invalid message from peer ignored (unable to unpack value)"; + return; + } + + ReadableStreamDefaultController::Error(script_state_, controller_, + reason); + message_port_->close(); + return; + } + + default: + DLOG(WARNING) << "Invalid message from peer ignored (invalid type): " + << static_cast<int>(type); + return; + } +} + +void CrossRealmTransformReadable::HandleError(v8::Local<v8::Value> error) { + ReadableStreamDefaultController::Error(script_state_, controller_, error); +} + +} // namespace + +CORE_EXPORT WritableStreamNative* CreateCrossRealmTransformWritable( + ScriptState* script_state, + MessagePort* port, + ExceptionState& exception_state) { + return MakeGarbageCollected<CrossRealmTransformWritable>(script_state, port) + ->CreateWritableStream(exception_state); +} + +CORE_EXPORT ReadableStreamNative* CreateCrossRealmTransformReadable( + ScriptState* script_state, + MessagePort* port, + ExceptionState& exception_state) { + return MakeGarbageCollected<CrossRealmTransformReadable>(script_state, port) + ->CreateReadableStream(exception_state); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/streams/transferable_streams.h b/third_party/blink/renderer/core/streams/transferable_streams.h new file mode 100644 index 0000000..62883f1 --- /dev/null +++ b/third_party/blink/renderer/core/streams/transferable_streams.h
@@ -0,0 +1,37 @@ +// Copyright 2019 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. + +// Functions used to build transferable streams. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFERABLE_STREAMS_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFERABLE_STREAMS_H_ + +#include "third_party/blink/renderer/core/core_export.h" + +namespace blink { + +class ExceptionState; +class MessagePort; +class ReadableStreamNative; +class ScriptState; +class WritableStreamNative; + +// Creates the writable side of a cross-realm identity transform stream, using +// |port| for communication. |port| must be entangled with another MessagePort +// which is passed to CreateCrossRealmTransformReadable(). +CORE_EXPORT WritableStreamNative* CreateCrossRealmTransformWritable( + ScriptState*, + MessagePort* port, + ExceptionState&); + +// Creates the readable side of a cross-realm identity transform stream. |port| +// is used symmetrically with CreateCrossRealmTransformWritable(). +CORE_EXPORT ReadableStreamNative* CreateCrossRealmTransformReadable( + ScriptState*, + MessagePort* port, + ExceptionState&); + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFERABLE_STREAMS_H_
diff --git a/third_party/blink/renderer/core/streams/transferable_streams_test.cc b/third_party/blink/renderer/core/streams/transferable_streams_test.cc new file mode 100644 index 0000000..3811b05 --- /dev/null +++ b/third_party/blink/renderer/core/streams/transferable_streams_test.cc
@@ -0,0 +1,129 @@ +// Copyright 2019 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 "third_party/blink/renderer/core/streams/transferable_streams.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/bindings/core/v8/script_function.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/bindings/core/v8/script_value.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_readable_stream_default_reader.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_writable_stream_default_writer.h" +#include "third_party/blink/renderer/core/messaging/message_channel.h" +#include "third_party/blink/renderer/core/streams/readable_stream_default_reader.h" +#include "third_party/blink/renderer/core/streams/readable_stream_native.h" +#include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h" +#include "third_party/blink/renderer/core/streams/writable_stream_native.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "third_party/blink/renderer/platform/heap/heap.h" +#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" + +namespace blink { + +namespace { + +// We only do minimal testing here. The functionality of transferable streams is +// tested in the layout tests. +TEST(TransferableStreamsTest, SmokeTest) { + V8TestingScope scope; + + auto* channel = + MakeGarbageCollected<MessageChannel>(scope.GetExecutionContext()); + auto* script_state = scope.GetScriptState(); + auto* writable = CreateCrossRealmTransformWritable( + script_state, channel->port1(), ASSERT_NO_EXCEPTION); + ASSERT_TRUE(writable); + auto* readable = CreateCrossRealmTransformReadable( + script_state, channel->port2(), ASSERT_NO_EXCEPTION); + ASSERT_TRUE(readable); + + auto* writer = V8WritableStreamDefaultWriter::ToImpl( + writable->getWriter(script_state, ASSERT_NO_EXCEPTION) + .V8Value() + .As<v8::Object>()); + auto* reader = V8ReadableStreamDefaultReader::ToImpl( + readable->getReader(script_state, ASSERT_NO_EXCEPTION) + .V8Value() + .As<v8::Object>()); + + writer->write(script_state, ScriptValue::CreateNull(script_state)); + + class ExpectNullResponse : public ScriptFunction { + public: + static v8::Local<v8::Function> Create(ScriptState* script_state, + bool* got_response) { + auto* self = + MakeGarbageCollected<ExpectNullResponse>(script_state, got_response); + return self->BindToV8Function(); + } + + ExpectNullResponse(ScriptState* script_state, bool* got_response) + : ScriptFunction(script_state), got_response_(got_response) {} + + private: + ScriptValue Call(ScriptValue value) override { + *got_response_ = true; + if (!value.IsObject()) { + ADD_FAILURE() << "iterator must be an object"; + return ScriptValue(); + } + bool done = false; + auto* script_state = GetScriptState(); + auto chunk_maybe = + V8UnpackIteratorResult(script_state, + value.V8Value() + ->ToObject(script_state->GetContext()) + .ToLocalChecked(), + &done); + EXPECT_FALSE(done); + v8::Local<v8::Value> chunk; + if (!chunk_maybe.ToLocal(&chunk)) { + ADD_FAILURE() << "V8UnpackIteratorResult failed"; + return ScriptValue(); + } + EXPECT_TRUE(chunk->IsNull()); + return ScriptValue(); + } + + bool* got_response_; + }; + + // TODO(ricea): This is copy-and-pasted from transform_stream_test.cc. Put it + // in a shared location. + class ExpectNotReached : public ScriptFunction { + public: + static v8::Local<v8::Function> Create(ScriptState* script_state) { + auto* self = MakeGarbageCollected<ExpectNotReached>(script_state); + return self->BindToV8Function(); + } + + explicit ExpectNotReached(ScriptState* script_state) + : ScriptFunction(script_state) {} + + private: + ScriptValue Call(ScriptValue) override { + ADD_FAILURE() << "ExpectNotReached was reached"; + return ScriptValue(); + } + }; + + bool got_response = false; + reader->read(script_state) + .Then(ExpectNullResponse::Create(script_state, &got_response), + ExpectNotReached::Create(script_state)); + + // Need to run the event loop to pass messages through the MessagePort. + test::RunPendingTasks(); + + // Resolve promises. + v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate()); + + EXPECT_TRUE(got_response); +} + +} // namespace + +} // namespace blink
diff --git a/third_party/blink/renderer/core/streams/writable_stream.cc b/third_party/blink/renderer/core/streams/writable_stream.cc index da3db6e..3d6f944 100644 --- a/third_party/blink/renderer/core/streams/writable_stream.cc +++ b/third_party/blink/renderer/core/streams/writable_stream.cc
@@ -57,7 +57,10 @@ WritableStream* WritableStream::Deserialize(ScriptState* script_state, MessagePort* port, ExceptionState& exception_state) { - // TODO(ricea): Switch on Blink feature. + if (RuntimeEnabledFeatures::StreamsNativeEnabled()) { + return WritableStreamNative::Deserialize(script_state, port, + exception_state); + } return WritableStreamWrapper::Deserialize(script_state, port, exception_state); }
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_writer.h b/third_party/blink/renderer/core/streams/writable_stream_default_writer.h index 1bb5bea..fbe239e 100644 --- a/third_party/blink/renderer/core/streams/writable_stream_default_writer.h +++ b/third_party/blink/renderer/core/streams/writable_stream_default_writer.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_DEFAULT_WRITER_H_ #include "base/optional.h" +#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "v8/include/v8.h" @@ -21,7 +22,7 @@ class WritableStreamNative; // https://streams.spec.whatwg.org/#default-writer-class -class WritableStreamDefaultWriter final : public ScriptWrappable { +class CORE_EXPORT WritableStreamDefaultWriter final : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public:
diff --git a/third_party/blink/renderer/core/streams/writable_stream_native.cc b/third_party/blink/renderer/core/streams/writable_stream_native.cc index 262a9833..c0ee787 100644 --- a/third_party/blink/renderer/core/streams/writable_stream_native.cc +++ b/third_party/blink/renderer/core/streams/writable_stream_native.cc
@@ -7,7 +7,9 @@ #include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/core/streams/miscellaneous_operations.h" #include "third_party/blink/renderer/core/streams/promise_handler.h" +#include "third_party/blink/renderer/core/streams/readable_stream_native.h" #include "third_party/blink/renderer/core/streams/stream_promise_resolver.h" +#include "third_party/blink/renderer/core/streams/transferable_streams.h" #include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h" #include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" @@ -215,6 +217,41 @@ return stream; } +void WritableStreamNative::Serialize(ScriptState* script_state, + MessagePort* port, + ExceptionState& exception_state) { + if (IsLocked(this)) { + exception_state.ThrowTypeError("Cannot transfer a locked stream"); + return; + } + + auto* readable = + CreateCrossRealmTransformReadable(script_state, port, exception_state); + if (exception_state.HadException()) { + return; + } + + auto promise = ReadableStreamNative::PipeTo( + script_state, readable, this, ReadableStreamNative::PipeOptions()); + promise.MarkAsHandled(); +} + +WritableStreamNative* WritableStreamNative::Deserialize( + ScriptState* script_state, + MessagePort* port, + ExceptionState& exception_state) { + // We need to execute JavaScript to call "Then" on v8::Promises. We will not + // run author code. + v8::Isolate::AllowJavascriptExecutionScope allow_js( + script_state->GetIsolate()); + auto* writable = + CreateCrossRealmTransformWritable(script_state, port, exception_state); + if (exception_state.HadException()) { + return nullptr; + } + return writable; +} + WritableStreamDefaultWriter* WritableStreamNative::AcquireDefaultWriter( ScriptState* script_state, WritableStreamNative* stream,
diff --git a/third_party/blink/renderer/core/streams/writable_stream_native.h b/third_party/blink/renderer/core/streams/writable_stream_native.h index 64f80fc2..e1848c6 100644 --- a/third_party/blink/renderer/core/streams/writable_stream_native.h +++ b/third_party/blink/renderer/core/streams/writable_stream_native.h
@@ -83,9 +83,11 @@ return stream->writer_; } - void Serialize(ScriptState*, MessagePort*, ExceptionState&) override { - // TODO(ricea): Implement this. - } + void Serialize(ScriptState*, MessagePort*, ExceptionState&) override; + + static WritableStreamNative* Deserialize(ScriptState*, + MessagePort*, + ExceptionState&); // // Methods used by ReadableStreamNative::PipeTo
diff --git a/third_party/blink/renderer/core/streams/writable_stream_test.cc b/third_party/blink/renderer/core/streams/writable_stream_test.cc index 5401cc7..e87946d1 100644 --- a/third_party/blink/renderer/core/streams/writable_stream_test.cc +++ b/third_party/blink/renderer/core/streams/writable_stream_test.cc
@@ -60,12 +60,6 @@ } TEST_P(WritableStreamTest, Serialize) { - // Disable the test when StreamsNative is enabled as WritableStreamNative - // doesn't support serialization yet. - // TODO(ricea): Re-enable this test when serialization is supported. - if (GetParam()) - return; - ScopedTransferableStreamsForTest enable_transferable_streams(true); V8TestingScope scope;
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 0850c24..a29cb66 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -482,6 +482,7 @@ "exported/mediastream/media_stream_audio_track.cc", "exported/mediastream/web_platform_media_stream_source.cc", "exported/mediastream/web_platform_media_stream_track.cc", + "exported/mediastream/webaudio_media_stream_source.cc", "exported/mediastream/webrtc_uma_histograms.cc", "exported/platform.cc", "exported/service_registry.cc",
diff --git a/third_party/blink/renderer/platform/bindings/script_wrappable.h b/third_party/blink/renderer/platform/bindings/script_wrappable.h index 45a60f97..2a9c4cc 100644 --- a/third_party/blink/renderer/platform/bindings/script_wrappable.h +++ b/third_party/blink/renderer/platform/bindings/script_wrappable.h
@@ -55,10 +55,21 @@ public: virtual ~ScriptWrappable() = default; - virtual void Trace(blink::Visitor*); + // The following methods may override lifetime of ScriptWrappable objects when + // needed. In particular if |HasPendingActivity| or |HasEventListeners| + // returns true *and* the child type also inherits from + // |ActiveScriptWrappable|, the objects will not be reclaimed by the GC, even + // if they are otherwise unreachable. + // + // Note: These methods are queried during garbage collection and *must not* + // allocate any new objects. + virtual bool HasPendingActivity() const { return false; } + virtual bool HasEventListeners() const { return false; } const char* NameInHeapSnapshot() const override; + virtual void Trace(blink::Visitor*); + template <typename T> T* ToImpl() { // All ScriptWrappables are managed by the Blink GC heap; check that @@ -98,11 +109,6 @@ const WrapperTypeInfo*, v8::Local<v8::Object> wrapper); - // Returns true if the instance needs to be kept alive even when the - // instance is unreachable from JavaScript. - virtual bool HasPendingActivity() const { return false; } - virtual bool HasEventListeners() const { return false; } - // Associates this instance with the given |wrapper| if this instance is not // yet associated with any wrapper. Returns true if the given wrapper is // associated with this instance, or false if this instance is already
diff --git a/content/renderer/media/stream/webaudio_media_stream_source.cc b/third_party/blink/renderer/platform/exported/mediastream/webaudio_media_stream_source.cc similarity index 87% rename from content/renderer/media/stream/webaudio_media_stream_source.cc rename to third_party/blink/renderer/platform/exported/mediastream/webaudio_media_stream_source.cc index 1f1b6dd..8d4398d 100644 --- a/content/renderer/media/stream/webaudio_media_stream_source.cc +++ b/third_party/blink/renderer/platform/exported/mediastream/webaudio_media_stream_source.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/stream/webaudio_media_stream_source.h" +#include "third_party/blink/public/platform/modules/mediastream/webaudio_media_stream_source.h" #include <utility> @@ -10,13 +10,12 @@ #include "base/bind_helpers.h" #include "base/logging.h" -namespace content { +namespace blink { WebAudioMediaStreamSource::WebAudioMediaStreamSource( - blink::WebMediaStreamSource* blink_source, + WebMediaStreamSource* blink_source, scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : blink::MediaStreamAudioSource(std::move(task_runner), - false /* is_remote */), + : MediaStreamAudioSource(std::move(task_runner), false /* is_remote */), is_registered_consumer_(false), fifo_(base::Bind(&WebAudioMediaStreamSource::DeliverRebufferedAudio, base::Unretained(this))), @@ -53,7 +52,7 @@ fifo_.frames_per_buffer()); // Take care of the discrete channel layout case. params.set_channels_for_discrete(number_of_channels); - blink::MediaStreamAudioSource::SetFormat(params); + MediaStreamAudioSource::SetFormat(params); if (!wrapper_bus_ || wrapper_bus_->channels() != params.channels()) wrapper_bus_ = media::AudioBus::CreateWrapper(params.channels()); @@ -84,7 +83,7 @@ } void WebAudioMediaStreamSource::ConsumeAudio( - const blink::WebVector<const float*>& audio_data, + const WebVector<const float*>& audio_data, size_t number_of_frames) { // TODO(miu): Plumbing is needed to determine the actual capture timestamp // of the audio, instead of just snapshotting TimeTicks::Now(), for proper @@ -108,8 +107,8 @@ current_reference_time_ + base::TimeDelta::FromMicroseconds( frame_delay * base::Time::kMicrosecondsPerSecond / - blink::MediaStreamAudioSource::GetAudioParameters().sample_rate()); - blink::MediaStreamAudioSource::DeliverDataToTracks(audio_bus, reference_time); + MediaStreamAudioSource::GetAudioParameters().sample_rate()); + MediaStreamAudioSource::DeliverDataToTracks(audio_bus, reference_time); } -} // namespace content +} // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/font_cache.cc b/third_party/blink/renderer/platform/fonts/font_cache.cc index 62e6790..32f740f 100644 --- a/third_party/blink/renderer/platform/fonts/font_cache.cc +++ b/third_party/blink/renderer/platform/fonts/font_cache.cc
@@ -110,6 +110,8 @@ const FontDescription& font_description, const FontFaceCreationParams& creation_params, AlternateFontName alternate_font_name) { + TRACE_EVENT0("fonts", "FontCache::GetFontPlatformData"); + if (!platform_init_) { platform_init_ = true; PlatformInit(); @@ -193,7 +195,7 @@ const FontDescription& font_description, const FontFaceCreationParams& creation_params, float font_size) { - TRACE_EVENT0("ui", "FontCache::ScaleFontPlatformData"); + TRACE_EVENT0("fonts,ui", "FontCache::ScaleFontPlatformData"); #if defined(OS_MACOSX) return CreateFontPlatformData(font_description, creation_params, font_size); @@ -295,6 +297,8 @@ UChar32 lookup_char, const SimpleFontData* font_data_to_substitute, FontFallbackPriority fallback_priority) { + TRACE_EVENT0("fonts", "FontCache::FallbackFontForCharacter"); + // In addition to PUA, do not perform fallback for non-characters either. Some // of these are sentinel characters to detect encodings and do appear on // websites. More details on @@ -313,7 +317,7 @@ } void FontCache::PurgePlatformFontDataCache() { - TRACE_EVENT0("ui", "FontCache::PurgePlatformFontDataCache"); + TRACE_EVENT0("fonts,ui", "FontCache::PurgePlatformFontDataCache"); Vector<FontCacheKey> keys_to_remove; keys_to_remove.ReserveInitialCapacity(font_platform_data_cache_.size()); for (auto& sized_fonts : font_platform_data_cache_) { @@ -332,7 +336,7 @@ } void FontCache::PurgeFallbackListShaperCache() { - TRACE_EVENT0("ui", "FontCache::PurgeFallbackListShaperCache"); + TRACE_EVENT0("fonts,ui", "FontCache::PurgeFallbackListShaperCache"); unsigned items = 0; FallbackListShaperCache::iterator iter; for (iter = fallback_list_shaper_cache_.begin(); @@ -379,7 +383,7 @@ } void FontCache::Invalidate() { - TRACE_EVENT0("ui", "FontCache::Invalidate"); + TRACE_EVENT0("fonts,ui", "FontCache::Invalidate"); font_platform_data_cache_.clear(); generation_++;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc index 2eb4228..e459e7a 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -579,7 +579,7 @@ Provider() ? Provider()->ResourceDispatcher() : nullptr; if (resource_dispatcher) { resource_dispatcher->DidAllocateSharedBitmap( - viz::bitmap_allocation::ToMojoHandle(std::move(shm.region)), + std::move(shm.region), SharedBitmapIdToGpuMailboxPtr(shared_bitmap_id_)); } }
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc index feb9021..33357b7e 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
@@ -388,10 +388,10 @@ } void CanvasResourceDispatcher::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, + base::ReadOnlySharedMemoryRegion region, ::gpu::mojom::blink::MailboxPtr id) { if (sink_) - sink_->DidAllocateSharedBitmap(std::move(buffer), std::move(id)); + sink_->DidAllocateSharedBitmap(std::move(region), std::move(id)); } void CanvasResourceDispatcher::DidDeleteSharedBitmap(
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h index 8d95154..323e932d 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_RESOURCE_DISPATCHER_H_ #include <memory> +#include "base/memory/read_only_shared_memory_region.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/resources/resource_id.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" @@ -71,7 +72,7 @@ void ReclaimResources( const WTF::Vector<viz::ReturnedResource>& resources) final; - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, ::gpu::mojom::blink::MailboxPtr id); void DidDeleteSharedBitmap(::gpu::mojom::blink::MailboxPtr id);
diff --git a/third_party/blink/renderer/platform/graphics/test/mock_compositor_frame_sink.h b/third_party/blink/renderer/platform/graphics/test/mock_compositor_frame_sink.h index 499d543..c764ddf 100644 --- a/third_party/blink/renderer/platform/graphics/test/mock_compositor_frame_sink.h +++ b/third_party/blink/renderer/platform/graphics/test/mock_compositor_frame_sink.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEST_MOCK_COMPOSITOR_FRAME_SINK_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEST_MOCK_COMPOSITOR_FRAME_SINK_H_ +#include "base/memory/read_only_shared_memory_region.h" #include "components/viz/common/quads/compositor_frame.h" #include "gpu/ipc/common/mailbox.mojom-blink.h" #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h" @@ -49,7 +50,7 @@ MOCK_METHOD1(SubmitCompositorFrameSync_, void(viz::CompositorFrame*)); MOCK_METHOD1(DidNotProduceFrame, void(const viz::BeginFrameAck&)); MOCK_METHOD2(DidAllocateSharedBitmap, - void(mojo::ScopedSharedBufferHandle, + void(base::ReadOnlySharedMemoryRegion, gpu::mojom::blink::MailboxPtr)); MOCK_METHOD1(DidDeleteSharedBitmap, void(gpu::mojom::blink::MailboxPtr)); MOCK_METHOD1(SetPreferredFrameInterval, void(base::TimeDelta));
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc index e7b9b44..cf35222 100644 --- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc +++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -234,12 +234,12 @@ } void VideoFrameSubmitter::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, + base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(compositor_frame_sink_); compositor_frame_sink_->DidAllocateSharedBitmap( - std::move(buffer), SharedBitmapIdToGpuMailboxPtr(id)); + std::move(region), SharedBitmapIdToGpuMailboxPtr(id)); } void VideoFrameSubmitter::DidDeleteSharedBitmap(const viz::SharedBitmapId& id) {
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.h b/third_party/blink/renderer/platform/graphics/video_frame_submitter.h index 14825ba..54c6a06 100644 --- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.h +++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
@@ -8,6 +8,7 @@ #include <memory> #include <utility> +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" @@ -75,7 +76,7 @@ const WTF::Vector<viz::ReturnedResource>& resources) override; // viz::SharedBitmapReporter implementation. - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion, const viz::SharedBitmapId&) override; void DidDeleteSharedBitmap(const viz::SharedBitmapId&) override;
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc index 04b29b6..737afe9 100644 --- a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc +++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/memory/ptr_util.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/test/scoped_task_environment.h" #include "base/test/simple_test_tick_clock.h" #include "base/time/time.h" @@ -96,11 +97,11 @@ MOCK_METHOD1(DidNotProduceFrame, void(const viz::BeginFrameAck&)); MOCK_METHOD2(DidAllocateSharedBitmap_, - void(mojo::ScopedSharedBufferHandle* buffer, + void(base::ReadOnlySharedMemoryRegion* region, gpu::mojom::blink::MailboxPtr* id)); - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, gpu::mojom::blink::MailboxPtr id) override { - DidAllocateSharedBitmap_(&buffer, &id); + DidAllocateSharedBitmap_(®ion, &id); } MOCK_METHOD1(DidDeleteSharedBitmap_, void(gpu::mojom::blink::MailboxPtr* id));
diff --git a/third_party/blink/renderer/platform/mojo/interface_invalidator_test.cc b/third_party/blink/renderer/platform/mojo/interface_invalidator_test.cc index 74cd25b7..8bbc5cc 100644 --- a/third_party/blink/renderer/platform/mojo/interface_invalidator_test.cc +++ b/third_party/blink/renderer/platform/mojo/interface_invalidator_test.cc
@@ -7,9 +7,9 @@ #include "base/bind.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/test/bind_test_util.h" +#include "base/test/scoped_task_environment.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/interface_ptr.h" #include "mojo/public/interfaces/bindings/tests/ping_service.mojom-blink.h" @@ -97,7 +97,7 @@ ~InterfaceInvalidatorTest() override {} private: - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; DISALLOW_COPY_AND_ASSIGN(InterfaceInvalidatorTest); };
diff --git a/third_party/blink/renderer/platform/mojo/kurl_security_origin_test.cc b/third_party/blink/renderer/platform/mojo/kurl_security_origin_test.cc index db429023..f41ec14 100644 --- a/third_party/blink/renderer/platform/mojo/kurl_security_origin_test.cc +++ b/third_party/blink/renderer/platform/mojo/kurl_security_origin_test.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/macros.h" -#include "base/message_loop/message_loop.h" +#include "base/test/scoped_task_environment.h" #include "mojo/public/cpp/bindings/binding.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/mojom/url_test.mojom-blink.h" @@ -35,7 +35,7 @@ // Mojo version of chrome IPC test in url/ipc/url_param_traits_unittest.cc. TEST(KURLSecurityOriginStructTraitsTest, Basic) { - base::MessageLoop message_loop; + base::test::ScopedTaskEnvironment scoped_task_environment; url::mojom::blink::UrlTestPtr proxy; UrlTestImpl impl(MakeRequest(&proxy));
diff --git a/third_party/blink/renderer/platform/timer_test.cc b/third_party/blink/renderer/platform/timer_test.cc index 4ff74e0..aaa2bcb 100644 --- a/third_party/blink/renderer/platform/timer_test.cc +++ b/third_party/blink/renderer/platform/timer_test.cc
@@ -6,8 +6,8 @@ #include <memory> #include <queue> -#include "base/message_loop/message_loop.h" #include "base/single_thread_task_runner.h" +#include "base/test/scoped_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/platform.h" @@ -83,7 +83,7 @@ platform_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; }; class OnHeapTimerOwner final
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 23709bf..5d4730b 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -5300,12 +5300,6 @@ crbug.com/919272 external/wpt/resource-timing/resource-timing.html [ Skip ] -### virtual/streams-native/http/tests/streams/transferable/ -crbug.com/902633 virtual/streams-native/http/tests/streams/transferable/writable-stream.html [ Timeout ] -crbug.com/902633 virtual/streams-native/http/tests/streams/transferable/shared-worker.html [ Pass Failure ] -crbug.com/902633 virtual/streams-native/http/tests/streams/transferable/worker.html [ Pass Failure ] - - # Sheriff 2019-01-03 crbug.com/918905 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/block-size-with-min-or-max-content-table-1b.html [ Pass Failure ] @@ -5797,9 +5791,9 @@ crbug.com/966345 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped.html [ Failure ] crbug.com/966345 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped.html [ Failure ] +crbug.com/905971 virtual/blink-cors/external/wpt/service-workers/service-worker/detached-context.https.html [ Pass Crash ] crbug.com/905971 virtual/blink-cors/http/tests/security/img-redirect-to-crossorigin-credentials.html [ Failure ] crbug.com/905971 virtual/blink-cors/http/tests/security/script-crossorigin-redirect-credentials.html [ Failure ] -crbug.com/905971 [ Win ] virtual/blink-cors/external/wpt/service-workers/service-worker/detached-context.https.html [ Pass Crash ] # Sheriff 2019-06-04 crbug.com/970135 [ Mac ] virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-interested-element-indicated.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/referrer-policy-test-case.sub.js b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/referrer-policy-test-case.sub.js index b286760..0c0f381 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/referrer-policy-test-case.sub.js +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/referrer-policy-test-case.sub.js
@@ -125,14 +125,52 @@ policyDeliveries: [delivery] }; + let currentURL = location.toString(); const expectedReferrer = - referrerUrlResolver[scenario.referrer_url](location.toString()); + referrerUrlResolver[scenario.referrer_url](currentURL); // Request in the top-level document. promise_test(_ => { + return invokeRequest(subresource, []) + .then(result => checkResult(expectedReferrer, result)); + }, testDescription); + + // `Referer` headers with length over 4k are culled down to an origin, so, let's test around + // that boundary for tests that would otherwise return the complete URL. + if (scenario.referrer_url == "stripped-referrer") { + promise_test(_ => { + history.pushState(null, null, "/"); + history.replaceState(null, null, "A".repeat(4096 - location.href.length - 1)); + const expectedReferrer = location.href; + // Ensure that we don't load the same URL as the previous test. + subresource.url += "&-1"; return invokeRequest(subresource, []) - .then(result => checkResult(expectedReferrer, result)); - }, testDescription); + .then(result => checkResult(location.href, result)) + .finally(_ => history.back()); + }, "`Referer` header with length < 4k is not stripped to an origin."); + + promise_test(_ => { + history.pushState(null, null, "/"); + history.replaceState(null, null, "A".repeat(4096 - location.href.length)); + const expectedReferrer = location.href; + // Ensure that we don't load the same URL as the previous test. + subresource.url += "&0"; + return invokeRequest(subresource, []) + .then(result => checkResult(expectedReferrer, result)) + .finally(_ => history.back()); + }, "`Referer` header with length == 4k is not stripped to an origin."); + + promise_test(_ => { + const originString = referrerUrlResolver["origin"](currentURL); + history.pushState(null, null, "/"); + history.replaceState(null, null, "A".repeat(4096 - location.href.length + 1)); + // Ensure that we don't load the same URL as the previous test. + subresource.url += "&+1"; + return invokeRequest(subresource, []) + .then(result => checkResult(originString, result)) + .finally(_ => history.back()); + }, "`Referer` header with length > 4k is stripped to an origin."); + } // We test requests from inside iframes only for <img> tags. // This is just to preserve the previous test coverage.
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/readable-stream-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/readable-stream-expected.txt deleted file mode 100644 index a398705f..0000000 --- a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/readable-stream-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -This is a testharness.js-based test. -FAIL sending one chunk through a transferred stream should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL sending ten chunks through a transferred stream should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL sending ten chunks one at a time should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL sending ten chunks on demand should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL transferring a stream should relieve backpressure assert_array_equals: pull() should have been called lengths differ, expected 1 got 0 -FAIL transferring a stream should add one chunk to the queue size promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL the extra queue from transferring is counted in chunks promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL cancel should be propagated to the original promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL cancel should abort a pending read() promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL stream cancel should not wait for underlying source cancel promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL serialization should not happen until the value is read promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL transferring a non-serializable chunk should error both sides promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL errors should be passed through promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL race between cancel() and error() should leave sides in different states promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL race between cancel() and close() should be benign promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL race between cancel() and enqueue() should be benign promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/reason-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/reason-expected.txt deleted file mode 100644 index e381006..0000000 --- a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/reason-expected.txt +++ /dev/null
@@ -1,25 +0,0 @@ -This is a testharness.js-based test. -FAIL reason with a simple value of 'hi' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL reason with a simple value of ' \r -' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL reason with a simple value of '7' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL reason with a simple value of '3' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL reason with a simple value of 'undefined' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL reason with a simple value of 'null' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL reason with a simple value of 'true' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL reason with a simple value of 'false' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL reason with a type of 'symbol' should be squished to undefined promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL reason with a type of 'function' should be squished to undefined promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL number with a value of 'NaN' should be squished to null promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL number with a value of 'Infinity' should be squished to null promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL objects that can be completely expressed in JSON should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL objects that cannot be expressed in JSON should result in a TypeError promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL the type and message of a TypeError should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL other attributes of a TypeError should not be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL a TypeError message should not be preserved if it is not a string promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL a TypeError message should not be preserved if it is a getter promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL a TypeError message should not be preserved if it is inherited promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL DOMException errors should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -FAIL RangeErrors should not be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/service-worker-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/service-worker-expected.txt deleted file mode 100644 index d487631..0000000 --- a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/service-worker-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -PASS service-worker -FAIL serviceWorker.controller.postMessage should be able to transfer a ReadableStream assert_true: the original stream should be locked expected true got false -FAIL postMessage in a service worker should be able to transfer ReadableStream promise_test: Unhandled rejection with value: "BAD: TypeError: Cannot read property 'constructor' of null" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/shared-worker-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/shared-worker-expected.txt deleted file mode 100644 index a61ccf35..0000000 --- a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/shared-worker-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -FAIL worker.postMessage should be able to transfer a ReadableStream assert_true: the original stream should be locked expected true got false -FAIL postMessage in a worker should be able to transfer a ReadableStream promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'constructor' of null" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/transform-stream-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/transform-stream-expected.txt deleted file mode 100644 index fddd996..0000000 --- a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/transform-stream-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -This is a testharness.js-based test. -FAIL window.postMessage should be able to transfer a TransformStream assert_true: the readable side should be locked expected true got false -PASS a TransformStream with a locked writable should not be transferable -PASS a TransformStream with a locked readable should not be transferable -PASS a TransformStream with both sides locked should not be transferable -FAIL piping through transferred transforms should work Cannot read property 'source' of null -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/window-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/window-expected.txt deleted file mode 100644 index 8e6fa50..0000000 --- a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/window-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ -CONSOLE ERROR: line 23: Uncaught TypeError: Cannot read property 'start' of null -CONSOLE ERROR: line 17: Uncaught (in promise) TypeError: Cannot read property 'constructor' of null -CONSOLE ERROR: line 41: Uncaught (in promise) TypeError: Cannot read property 'addEventListener' of null -CONSOLE ERROR: line 45: Uncaught (in promise) Error: assert_array_equals: there should be no ports in the event lengths differ, expected 0 got 1 -CONSOLE ERROR: line 5: Uncaught TypeError: Failed to execute 'postMessage' on 'Window': Value at index 0 is an untransferable 'null' value. -This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = assert_array_equals: there should be no ports in the event lengths differ, expected 0 got 1 -FAIL window.postMessage should be able to transfer a ReadableStream assert_true: the original stream should be locked expected true got false -FAIL port.postMessage should be able to transfer a ReadableStream assert_true: the original stream should be locked expected true got false -FAIL the same ReadableStream posted multiple times should arrive together object null is not iterable (cannot read property Symbol(Symbol.iterator)) -FAIL transfer to and from an iframe should work assert_array_equals: there should be no ports in the event lengths differ, expected 0 got 1 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/worker-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/worker-expected.txt deleted file mode 100644 index d3ca9a3..0000000 --- a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/worker-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -CONSOLE ERROR: line 2: Uncaught TypeError: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': Value at index 0 is an untransferable 'null' value. -CONSOLE ERROR: line 2: Uncaught TypeError: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': Value at index 0 is an untransferable 'null' value. -This is a testharness.js-based test. -FAIL worker.postMessage should be able to transfer a ReadableStream assert_true: the original stream should be locked expected true got false -FAIL postMessage in a worker should be able to transfer a ReadableStream promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'constructor' of null" -FAIL terminating a worker should not error the stream promise_test: Unhandled rejection with value: "error in worker" -Harness: the test ran to completion. -
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index fd6906a..3171e26 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-10-0-55-gc949ab075 -Revision: c949ab0757a2514cd3a37b3e1e8390fd662a025b +Version: VER-2-10-0-56-g711b593e4 +Revision: 711b593e4b589fbd726a4962ad492fc4e416355d License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses" License File: src/docs/FTL.TXT
diff --git a/tools/ipc_fuzzer/message_tools/message_list.cc b/tools/ipc_fuzzer/message_tools/message_list.cc index faf70177..df0f9ac 100644 --- a/tools/ipc_fuzzer/message_tools/message_list.cc +++ b/tools/ipc_fuzzer/message_tools/message_list.cc
@@ -93,7 +93,7 @@ result = false; } while (class_id > previous_class_id + 1) { - if (!base::ContainsValue(exemptions, previous_class_id + 1)) { + if (!base::Contains(exemptions, previous_class_id + 1)) { std::cout << "Missing message file for enum " << class_id - (previous_class_id + 1) << " before enum used by " << file_name << "\n"; @@ -108,7 +108,7 @@ } while (LastIPCMsgStart > highest_class_id + 1) { - if (!base::ContainsValue(exemptions, highest_class_id + 1)) { + if (!base::Contains(exemptions, highest_class_id + 1)) { std::cout << "Missing message file for enum " << LastIPCMsgStart - (highest_class_id + 1) << " before enum LastIPCMsgStart\n";
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 92e762d..15bbfae 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -863,6 +863,7 @@ <int value="1" label="PASSWORD"/> <int value="2" label="PAYMENT_INFO"/> <int value="3" label="ADDRESS_INFO"/> + <int value="4" label="TOUCH_TO_FILL_INFO"/> </enum> <enum name="AccessPasswordInSettingsEvent"> @@ -17066,7 +17067,6 @@ <int value="559" label="KerberosAddAccountsAllowed"/> <int value="560" label="KerberosAccounts"/> <int value="561" label="StickyKeysEnabled"/> - <int value="562" label="DockedMagnifierEnabled"/> <int value="563" label="AppRecommendationZeroStateEnabled"/> <int value="564" label="BrowserSwitcherExternalGreylistUrl"/> <int value="565" label="PolicyDictionaryMultipleSourceMergeList"/> @@ -45415,6 +45415,14 @@ <int value="8" label="Metadata persistence failed"/> </enum> +<enum name="PasswordUpdateLoginSyncError"> + <int value="0" label="None"/> + <int value="1" label="DB Not Available"/> + <int value="2" label="No Records were Updated"/> + <int value="3" label="Encryption Service Failure"/> + <int value="4" label="DB Error"/> +</enum> + <enum name="PaymentRequestAbortReason"> <int value="0" label="DismissedByUser"/> <int value="1" label="AbortedByMerchant"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 83e99ea..767e79da 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -2756,7 +2756,7 @@ </histogram> <histogram name="Android.PhotoPicker.BitmapScalerTask" units="ms" - expires_after="M77"> + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2765,7 +2765,7 @@ </histogram> <histogram name="Android.PhotoPicker.CacheHits" units="Hits" - expires_after="M77"> + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2775,7 +2775,7 @@ </histogram> <histogram name="Android.PhotoPicker.DecodeRequests" units="Hits" - expires_after="M77"> + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2784,7 +2784,8 @@ </summary> </histogram> -<histogram name="Android.PhotoPicker.DecoderHostFailureOutOfMemory" units="%"> +<histogram name="Android.PhotoPicker.DecoderHostFailureOutOfMemory" units="%" + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2798,7 +2799,7 @@ </histogram> <histogram name="Android.PhotoPicker.DecoderHostFailureRuntime" units="%" - expires_after="M77"> + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2812,7 +2813,7 @@ </histogram> <histogram name="Android.PhotoPicker.DialogAction" - enum="PhotoPickerDialogAction" expires_after="M77"> + enum="PhotoPickerDialogAction" expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2821,7 +2822,7 @@ </histogram> <histogram name="Android.PhotoPicker.EnumeratedFiles" units="Files" - expires_after="M77"> + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2831,7 +2832,7 @@ </histogram> <histogram name="Android.PhotoPicker.EnumeratedRate" - units="Files per 10th of a second" expires_after="M77"> + units="Files per 10th of a second" expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2841,7 +2842,7 @@ </histogram> <histogram name="Android.PhotoPicker.EnumerationTime" units="ms" - expires_after="M77"> + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2850,7 +2851,8 @@ </summary> </histogram> -<histogram name="Android.PhotoPicker.ExifOrientation" enum="ExifOrientation"> +<histogram name="Android.PhotoPicker.ExifOrientation" enum="ExifOrientation" + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <summary> Records whether the EXIF orientation directive is present and what it is set @@ -2859,7 +2861,8 @@ </summary> </histogram> -<histogram name="Android.PhotoPicker.ImageByteCount" units="KB"> +<histogram name="Android.PhotoPicker.ImageByteCount" units="KB" + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2868,7 +2871,8 @@ </summary> </histogram> -<histogram name="Android.PhotoPicker.ImageDecodeTime" units="ms"> +<histogram name="Android.PhotoPicker.ImageDecodeTime" units="ms" + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2878,7 +2882,7 @@ </histogram> <histogram name="Android.PhotoPicker.RequestProcessTime" units="ms" - expires_after="M77"> + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2888,7 +2892,8 @@ </summary> </histogram> -<histogram name="Android.PhotoPicker.UpscaleLowResBitmap" units="ms"> +<histogram name="Android.PhotoPicker.UpscaleLowResBitmap" units="ms" + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -3010,7 +3015,7 @@ </histogram> <histogram name="Android.SelectFileDialogImgCount" units="images" - expires_after="M77"> + expires_after="2020-06-01"> <owner>finnur@chromium.org</owner> <owner>peter@chromium.org</owner> <summary> @@ -3022,7 +3027,7 @@ </histogram> <histogram name="Android.SelectFileDialogScope" enum="SelectFileDialogScope" - expires_after="M77"> + expires_after="2020-06-01"> <owner>peter@chromium.org</owner> <summary> Records the scope of accepted content for a select file dialog when shown by @@ -90366,6 +90371,17 @@ </summary> </histogram> +<histogram name="PasswordManager.ApplySyncChanges.UpdateLoginSyncError" + enum="PasswordUpdateLoginSyncError" expires_after="M80"> + <owner>mamir@chromium.org</owner> + <owner>mastiz@chromium.org</owner> + <summary> + Records different results upon updating a remote password to the password + manager. It is recorded every time after receiving remote password + incremental updates from the server. + </summary> +</histogram> + <histogram name="PasswordManager.ApplySyncChangesState" enum="PasswordApplySyncChangesState" expires_after="M80"> <owner>mamir@chromium.org</owner> @@ -91192,6 +91208,17 @@ </summary> </histogram> +<histogram name="PasswordManager.MergeSyncData.UpdateLoginSyncError" + enum="PasswordUpdateLoginSyncError" expires_after="M80"> + <owner>mamir@chromium.org</owner> + <owner>mastiz@chromium.org</owner> + <summary> + Records different results upon updating a remote password in the password + manager. It is recorded during the initial sync when merging remote and + local data. + </summary> +</histogram> + <histogram name="PasswordManager.MultiAccountPasswordUpdateAction" enum="MultiAccountUpdateBubbleUserAction" expires_after="2018-03-29"> <obsolete> @@ -129906,6 +129933,23 @@ </summary> </histogram> +<histogram name="Tab.Count.Guest" expires_after="M85"> + <owner>rhalavati@chromium.org</owner> + <owner>chrome-privacy-core@google.com</owner> + <summary> + Number of open tabs in each guest window. Recorded when a new tab is opened. + </summary> +</histogram> + +<histogram name="Tab.Count.Incognito" expires_after="M85"> + <owner>rhalavati@chromium.org</owner> + <owner>chrome-privacy-core@google.com</owner> + <summary> + Number of open tabs in each incognito window. Recorded when a new tab is + opened. + </summary> +</histogram> + <histogram name="Tab.Deactivation.Bookmarked" enum="Boolean" expires_after="2016-11-11"> <obsolete>
diff --git a/tools/perf/core/stacktrace_unittest.py b/tools/perf/core/stacktrace_unittest.py index eff01f8..f739303 100644 --- a/tools/perf/core/stacktrace_unittest.py +++ b/tools/perf/core/stacktrace_unittest.py
@@ -15,6 +15,7 @@ # Stack traces do not currently work on 10.6, but they are also being # disabled shortly so just disable it for now. # All platforms except chromeos should at least have a valid minidump. + # Disabled on Android, flaky: crbug.com/971998. @decorators.Disabled('snowleopard', 'chromeos', 'android') def testValidDump(self): with self.assertRaises(exceptions.DevtoolsTargetCrashException) as c:
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index a3063b4..b52059d 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -339,50 +339,7 @@ crbug.com/954949 [ Nexus5X_Webview ] system_health.memory_mobile/browse:news:washingtonpost [ Skip ] crbug.com/961417 [ Android_Go ] system_health.memory_mobile/browse:social:tumblr_infinite_scroll:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:media:flickr_infinite_scroll [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:search:amp:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:games:lazors [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:games:spychase:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:media:flickr:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:news:irctc [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:search:baidu:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:search:google:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:tools:stackoverflow:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/background:search:google [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:media:googleplaystore:2019 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:media:imgur [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:media:facebook_photos [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:media:youtube [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:shopping:lazada [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:tools:maps [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:media:dailymotion [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:news:qq [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:news:wikipedia:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:search:ebay:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:search:taobao [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:tools:dropbox [ Skip ] -crbug.com/964960 [ Nexus_5X ] system_health.memory_mobile/background:social:facebook [ Skip ] -crbug.com/964960 [ Nexus_5X ] system_health.memory_mobile/browse:social:facebook_infinite_scroll:2018 [ Skip ] -crbug.com/964960 [ Nexus_5X ] system_health.memory_mobile/load:media:facebook_photos [ Skip ] -crbug.com/964960 [ Nexus_5X ] system_health.memory_mobile/load:media:google_images:2018 [ Skip ] -crbug.com/964960 [ Nexus_5X ] system_health.memory_mobile/load:media:soundcloud:2018 [ Skip ] -crbug.com/964960 [ Nexus_5X ] system_health.memory_mobile/load:search:yahoo:2018 [ Skip ] -crbug.com/964960 [ Nexus_5X ] system_health.memory_mobile/load:social:twitter [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:news:cricbuzz [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:news:reddit [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:news:qq [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:search:amp:sxg:2019 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:social:instagram [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:social:twitter [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/browse:social:tumblr_infinite_scroll:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:chrome:blank [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:media:imgur:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:media:youtube:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:news:cnn:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:news:reddit [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:search:yandex:2018 [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:tools:docs [ Skip ] -crbug.com/964804 [ Nexus_5X ] system_health.memory_mobile/load:tools:weather [ Skip ] +crbug.com/964960 [ Nexus_5X ] system_health.memory_mobile/* [ Skip ] # Benchmark: tab_switching.typical_25 crbug.com/747026 [ Mac ] tab_switching.typical_25/multitab:misc:typical24 [ Skip ]
diff --git a/tools/traffic_annotation/auditor/instance.cc b/tools/traffic_annotation/auditor/instance.cc index 9ddac6d..4a33123 100644 --- a/tools/traffic_annotation/auditor/instance.cc +++ b/tools/traffic_annotation/auditor/instance.cc
@@ -278,19 +278,19 @@ std::set<int> fields; GetSemanticsFieldNumbers(&fields); for (const auto& item : kSemanticsFields) { - if (!base::ContainsKey(fields, item.first)) + if (!base::Contains(fields, item.first)) unspecifieds.push_back(item.second); } GetPolicyFieldNumbers(&fields); for (const auto& item : kPolicyFields) { - if (!base::ContainsKey(fields, item.first)) { + if (!base::Contains(fields, item.first)) { // If 'cookies_allowed = NO' is provided, ignore not having // 'cookies_allowed = YES'. if (item.first == traffic_annotation::NetworkTrafficAnnotation_TrafficPolicy:: kCookiesAllowedFieldNumber && - base::ContainsKey(fields, -item.first)) + base::Contains(fields, -item.first)) continue; // If |cookies_store| is not provided, ignore if 'cookies_allowed = NO' is @@ -298,7 +298,7 @@ if (item.first == traffic_annotation::NetworkTrafficAnnotation_TrafficPolicy:: kCookiesStoreFieldNumber && - base::ContainsKey( + base::Contains( fields, -traffic_annotation::NetworkTrafficAnnotation_TrafficPolicy:: kCookiesAllowedFieldNumber)) @@ -306,9 +306,9 @@ // If either of |chrome_policy| or |policy_exception_justification| are // avaliable, ignore not having the other one. - if (base::ContainsValue(kChromePolicyFields, item.first) && - (base::ContainsKey(fields, kChromePolicyFields[0]) || - base::ContainsKey(fields, kChromePolicyFields[1]))) { + if (base::Contains(kChromePolicyFields, item.first) && + (base::Contains(fields, kChromePolicyFields[0]) || + base::Contains(fields, kChromePolicyFields[1]))) { continue; } unspecifieds.push_back(item.second); @@ -522,35 +522,35 @@ // The values of the semantics and policy are set so that the tests would know // which fields were available before archive. - if (base::ContainsKey( + if (base::Contains( semantics_fields, traffic_annotation::NetworkTrafficAnnotation_TrafficSemantics:: kSenderFieldNumber)) { annotation.proto.mutable_semantics()->set_sender("[Archived]"); } - if (base::ContainsKey( + if (base::Contains( semantics_fields, traffic_annotation::NetworkTrafficAnnotation_TrafficSemantics:: kDescriptionFieldNumber)) { annotation.proto.mutable_semantics()->set_description("[Archived]"); } - if (base::ContainsKey( + if (base::Contains( semantics_fields, traffic_annotation::NetworkTrafficAnnotation_TrafficSemantics:: kTriggerFieldNumber)) { annotation.proto.mutable_semantics()->set_trigger("[Archived]"); } - if (base::ContainsKey( + if (base::Contains( semantics_fields, traffic_annotation::NetworkTrafficAnnotation_TrafficSemantics:: kDataFieldNumber)) { annotation.proto.mutable_semantics()->set_data("[Archived]"); } - if (base::ContainsKey( + if (base::Contains( semantics_fields, traffic_annotation::NetworkTrafficAnnotation_TrafficSemantics:: kDestinationFieldNumber)) { @@ -559,7 +559,7 @@ NetworkTrafficAnnotation_TrafficSemantics_Destination_WEBSITE); } - if (base::ContainsKey( + if (base::Contains( policy_fields, traffic_annotation::NetworkTrafficAnnotation_TrafficPolicy:: kCookiesAllowedFieldNumber)) { @@ -568,7 +568,7 @@ NetworkTrafficAnnotation_TrafficPolicy_CookiesAllowed_YES); } - if (base::ContainsKey( + if (base::Contains( policy_fields, -traffic_annotation::NetworkTrafficAnnotation_TrafficPolicy:: kCookiesAllowedFieldNumber)) { @@ -577,28 +577,28 @@ NetworkTrafficAnnotation_TrafficPolicy_CookiesAllowed_NO); } - if (base::ContainsKey( + if (base::Contains( policy_fields, traffic_annotation::NetworkTrafficAnnotation_TrafficPolicy:: kCookiesStoreFieldNumber)) { annotation.proto.mutable_policy()->set_cookies_store("[Archived]"); } - if (base::ContainsKey( + if (base::Contains( policy_fields, traffic_annotation::NetworkTrafficAnnotation_TrafficPolicy:: kSettingFieldNumber)) { annotation.proto.mutable_policy()->set_setting("[Archived]"); } - if (base::ContainsKey( + if (base::Contains( policy_fields, traffic_annotation::NetworkTrafficAnnotation_TrafficPolicy:: kChromePolicyFieldNumber)) { annotation.proto.mutable_policy()->add_chrome_policy(); } - if (base::ContainsKey( + if (base::Contains( policy_fields, traffic_annotation::NetworkTrafficAnnotation_TrafficPolicy:: kPolicyExceptionJustificationFieldNumber)) {
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc b/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc index eb2a867..281d832 100644 --- a/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc +++ b/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc
@@ -89,7 +89,7 @@ // TODO(https://crbug.com/690323): Update to a more general policy. bool PathFiltersMatch(const std::vector<std::string>& path_filters, const std::string file_path) { - if (base::ContainsValue(path_filters, file_path)) + if (base::Contains(path_filters, file_path)) return true; for (const std::string& path_filter : path_filters) { if (path_filter.find(".") == std::string::npos && @@ -612,7 +612,7 @@ return false; // Already checked? - if (base::ContainsKey(checked_dependencies_, call.file_path)) + if (base::Contains(checked_dependencies_, call.file_path)) return checked_dependencies_[call.file_path]; std::string gn_output; @@ -732,7 +732,7 @@ } for (AnnotationInstance* instance : completing_annotations) { - if (!base::ContainsKey(used_completing_annotations, instance)) { + if (!base::Contains(used_completing_annotations, instance)) { errors_.push_back( AuditorResult(AuditorResult::Type::ERROR_INCOMPLETED_ANNOTATION, instance->proto.unique_id()));
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc b/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc index 6ccb370..5bcc9d0 100644 --- a/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc +++ b/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc
@@ -432,7 +432,7 @@ } for (const AuditorResult& result : raw_errors) { - if (base::ContainsKey(warning_types, result.type())) + if (base::Contains(warning_types, result.type())) warnings.push_back(result); else errors.push_back(result);
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_auditor_unittest.cc b/tools/traffic_annotation/auditor/traffic_annotation_auditor_unittest.cc index 5b0322ae..085cc5e6 100644 --- a/tools/traffic_annotation/auditor/traffic_annotation_auditor_unittest.cc +++ b/tools/traffic_annotation/auditor/traffic_annotation_auditor_unittest.cc
@@ -203,11 +203,11 @@ EXPECT_EQ(git_files.size(), base::size(kRelevantFiles)); for (const char* filepath : kRelevantFiles) { - EXPECT_TRUE(base::ContainsValue(git_files, filepath)); + EXPECT_TRUE(base::Contains(git_files, filepath)); } for (const char* filepath : kIrrelevantFiles) { - EXPECT_FALSE(base::ContainsValue(git_files, filepath)); + EXPECT_FALSE(base::Contains(git_files, filepath)); } } @@ -233,7 +233,7 @@ file_paths.clear(); filter.GetRelevantFiles(base::FilePath(), ignore_list, "", &file_paths); EXPECT_EQ(file_paths.size(), git_files_count - 1); - EXPECT_FALSE(base::ContainsValue(file_paths, ignore_list[0])); + EXPECT_FALSE(base::Contains(file_paths, ignore_list[0])); // Check if files are filtered based on given directory. ignore_list.clear(); @@ -410,7 +410,7 @@ TrafficAnnotationAuditor::GetReservedIDsMap(); for (int id : expected_ids) { - EXPECT_TRUE(base::ContainsKey(reserved_words, id)); + EXPECT_TRUE(base::Contains(reserved_words, id)); EXPECT_EQ(id, TrafficAnnotationAuditor::ComputeHashValue( reserved_words.find(id)->second)); }
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_exporter.cc b/tools/traffic_annotation/auditor/traffic_annotation_exporter.cc index ae0828a..d7f40968 100644 --- a/tools/traffic_annotation/auditor/traffic_annotation_exporter.cc +++ b/tools/traffic_annotation/auditor/traffic_annotation_exporter.cc
@@ -185,7 +185,7 @@ int content_hash_code = annotation.GetContentHashCode(); // If annotation unique id is already in the imported annotations list, // check if other fields have changed. - if (base::ContainsKey(archive_, annotation.proto.unique_id())) { + if (base::Contains(archive_, annotation.proto.unique_id())) { ArchivedAnnotation* current = &archive_[annotation.proto.unique_id()]; // Check second id. @@ -197,7 +197,7 @@ } // Check platform. - if (!base::ContainsValue(current->os_list, current_platform_)) { + if (!base::Contains(current->os_list, current_platform_)) { current->os_list.push_back(current_platform_); modified_ = true; } @@ -236,10 +236,10 @@ // If a none-reserved annotation is removed from current platform, update it. for (auto& item : archive_) { - if (base::ContainsValue(item.second.os_list, current_platform_) && + if (base::Contains(item.second.os_list, current_platform_) && item.second.content_hash_code != -1 && - !base::ContainsKey(current_platform_hashcodes, - item.second.unique_id_hash_code)) { + !base::Contains(current_platform_hashcodes, + item.second.unique_id_hash_code)) { base::Erase(item.second.os_list, current_platform_); modified_ = true; } @@ -247,7 +247,7 @@ // If there is a new reserved id, add it. for (const auto& item : reserved_ids) { - if (!base::ContainsKey(archive_, item.second)) { + if (!base::Contains(archive_, item.second)) { ArchivedAnnotation new_item; new_item.unique_id_hash_code = item.first; new_item.os_list = all_supported_platforms_; @@ -364,7 +364,7 @@ // Check for annotation hash code duplications. std::map<int, std::string> used_codes; for (auto& item : archive_) { - if (base::ContainsKey(used_codes, item.second.unique_id_hash_code)) { + if (base::Contains(used_codes, item.second.unique_id_hash_code)) { AuditorResult error(AuditorResult::Type::ERROR_HASH_CODE_COLLISION); error.AddDetail(used_codes[item.second.unique_id_hash_code]); error.AddDetail(item.first); @@ -387,7 +387,7 @@ // Check that listed OSes are valid. for (const auto& pair : archive_) { for (const auto& os : pair.second.os_list) { - if (!base::ContainsValue(all_supported_platforms_, os)) { + if (!base::Contains(all_supported_platforms_, os)) { AuditorResult error(AuditorResult::Type::ERROR_INVALID_OS, std::string(), kAnnotationsXmlPath.MaybeAsASCII(), AuditorResult::kNoCodeLineSpecified); @@ -463,7 +463,7 @@ } for (const std::string& id : old_keys) { - if (base::ContainsKey(new_items, id) && old_items[id] != new_items[id]) { + if (base::Contains(new_items, id) && old_items[id] != new_items[id]) { message += base::StringPrintf("\n\tUpdate line: '%s' --> '%s'", old_items[id].c_str(), new_items[id].c_str());
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_exporter.h b/tools/traffic_annotation/auditor/traffic_annotation_exporter.h index 2d4e121..62786fe 100644 --- a/tools/traffic_annotation/auditor/traffic_annotation_exporter.h +++ b/tools/traffic_annotation/auditor/traffic_annotation_exporter.h
@@ -71,7 +71,7 @@ // Checks if the current platform is in the os list of archived annotation. bool MatchesCurrentPlatform(const ArchivedAnnotation& annotation) const { - return base::ContainsValue(annotation.os_list, current_platform_); + return base::Contains(annotation.os_list, current_platform_); } // Produces the list of annotations that are not defined in this platform.
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_id_checker.cc b/tools/traffic_annotation/auditor/traffic_annotation_id_checker.cc index 235dcdc..3d9c63a 100644 --- a/tools/traffic_annotation/auditor/traffic_annotation_id_checker.cc +++ b/tools/traffic_annotation/auditor/traffic_annotation_id_checker.cc
@@ -55,7 +55,7 @@ std::vector<AuditorResult>* errors) { for (AnnotationItem& item : annotations_) { for (int i = 0; i < item.ids_count; i++) { - if (base::ContainsKey(invalid_set, item.ids[i].hash_code)) { + if (base::Contains(invalid_set, item.ids[i].hash_code)) { errors->push_back(AuditorResult(error_type, item.ids[i].text, item.file_path, item.line_number)); } @@ -83,7 +83,7 @@ std::map<int, std::string> collisions; for (AnnotationItem& item : annotations_) { for (int i = 0; i < item.ids_count; i++) { - if (!base::ContainsKey(collisions, item.ids[i].hash_code)) { + if (!base::Contains(collisions, item.ids[i].hash_code)) { // If item is loaded from archive, and it is the second id, do not keep // the id for checks. Archive just keeps the hash code of the second id // and the text value of it is not correct. @@ -112,7 +112,7 @@ // Check if first ids are unique. for (AnnotationItem& item : annotations_) { - if (!base::ContainsKey(first_ids, item.ids[0].hash_code)) { + if (!base::Contains(first_ids, item.ids[0].hash_code)) { first_ids[item.ids[0].hash_code] = &item; } else { errors->push_back(CreateRepeatedIDError( @@ -124,7 +124,7 @@ // type PARTIAL and owner of the first id should be of type COMPLETING. for (AnnotationItem& item : annotations_) { if (item.ids_count == 2 && - base::ContainsKey(first_ids, item.ids[1].hash_code)) { + base::Contains(first_ids, item.ids[1].hash_code)) { if (item.type != AnnotationInstance::Type::ANNOTATION_PARTIAL || first_ids[item.ids[1].hash_code]->type != AnnotationInstance::Type::ANNOTATION_COMPLETING) { @@ -139,7 +139,7 @@ for (AnnotationItem& item : annotations_) { if (item.ids_count != 2) continue; - if (!base::ContainsKey(second_ids, item.ids[1].hash_code)) { + if (!base::Contains(second_ids, item.ids[1].hash_code)) { second_ids[item.ids[1].hash_code] = &item; } else { AnnotationInstance::Type other_type =
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc index e3bde07..701ec8b 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -124,46 +124,21 @@ // null if if the AtkObject is destroyed. AtkObject* g_active_top_level_frame = nullptr; -// AtkTableCell was introduced in ATK 2.12. Ubuntu Trusty has ATK 2.10. -// Compile-time checks are in place for ATK versions that are older than 2.12. -// However, we also need runtime checks in case the version we are building -// against is newer than the runtime version. To prevent a runtime error, we -// check that we have a version of ATK that supports AtkTableCell. If we do, -// we dynamically load the symbol; if we don't, the interface is absent from -// the accessible object and its methods will not be exposed or callable. -// The definitions below ensure we have no missing symbols. Note that in -// environments where we have ATK > 2.12, the definitions of AtkTableCell and -// AtkTableCellIface below are overridden by the runtime version. -// TODO(accessibility) Remove these definitions, along with the use of -// LoadTableCellMethods() when 2.12 is the minimum supported version. -typedef struct _AtkTableCell AtkTableCell; -typedef struct _AtkTableCellIface AtkTableCellIface; -typedef GType (*cell_get_type_func)(); -typedef GPtrArray* (*get_column_header_cells_func)(AtkTableCell* cell); -typedef GPtrArray* (*get_row_header_cells_func)(AtkTableCell* cell); -typedef bool (*get_row_column_span_func)(AtkTableCell* cell, - gint* row, - gint* column, - gint* row_span, - gint* col_span); +#if defined(ATK_216) +constexpr AtkRole kStaticRole = ATK_ROLE_STATIC; +constexpr AtkRole kSubscriptRole = ATK_ROLE_SUBSCRIPT; +constexpr AtkRole kSuperscriptRole = ATK_ROLE_SUPERSCRIPT; +#else +constexpr AtkRole kStaticRole = ATK_ROLE_TEXT; +constexpr AtkRole kSubscriptRole = ATK_ROLE_TEXT; +constexpr AtkRole kSuperscriptRole = ATK_ROLE_TEXT; +#endif -cell_get_type_func cell_get_type = nullptr; -get_column_header_cells_func get_column_header_cells = nullptr; -get_row_header_cells_func get_row_header_cells = nullptr; -get_row_column_span_func get_row_column_span = nullptr; - -bool LoadTableCellMethods() { - cell_get_type = reinterpret_cast<cell_get_type_func>( - dlsym(RTLD_DEFAULT, "atk_table_cell_get_type")); - get_column_header_cells = reinterpret_cast<get_column_header_cells_func>( - dlsym(RTLD_DEFAULT, "atk_table_cell_get_column_header_cells")); - get_row_header_cells = reinterpret_cast<get_row_header_cells_func>( - dlsym(RTLD_DEFAULT, "atk_table_cell_get_row_header_cells")); - get_row_column_span = reinterpret_cast<get_row_column_span_func>( - dlsym(RTLD_DEFAULT, "atk_table_cell_get_row_column_span")); - - return cell_get_type; -} +#if defined(ATK_226) +constexpr AtkRole kAtkFootnoteRole = ATK_ROLE_FOOTNOTE; +#else +constexpr AtkRole kAtkFootnoteRole = ATK_ROLE_LIST_ITEM; +#endif AXPlatformNodeAuraLinux* AtkObjectToAXPlatformNodeAuraLinux( AtkObject* atk_object) { @@ -310,19 +285,6 @@ } } -void IdsToGPtrArray(AXPlatformNodeDelegate* delegate, - const std::vector<int32_t>& ids, - GPtrArray* array) { - for (const auto& node_id : ids) { - if (AXPlatformNode* header = delegate->GetFromNodeID(node_id)) { - if (AtkObject* atk_header = header->GetNativeViewAccessible()) { - g_object_ref(atk_header); - g_ptr_array_add(array, atk_header); - } - } - } -} - const char* BuildDescriptionFromHeaders(AXPlatformNodeDelegate* delegate, const std::vector<int32_t>& ids) { std::vector<std::string> names; @@ -364,149 +326,21 @@ return g_slist_prepend(attribute_set, attribute); } -// TODO(aleventhal) Remove this and use atk_role_get_name() once the following -// GNOME bug is fixed: https://bugzilla.gnome.org/show_bug.cgi?id=795983 -const char* const kRoleNames[] = { - "invalid", // ATK_ROLE_INVALID. - "accelerator label", - "alert", - "animation", - "arrow", - "calendar", - "canvas", - "check box", - "check menu item", - "color chooser", - "column header", - "combo box", - "dateeditor", - "desktop icon", - "desktop frame", - "dial", - "dialog", - "directory pane", - "drawing area", - "file chooser", - "filler", - "fontchooser", - "frame", - "glass pane", - "html container", - "icon", - "image", - "internal frame", - "label", - "layered pane", - "list", - "list item", - "menu", - "menu bar", - "menu item", - "option pane", - "page tab", - "page tab list", - "panel", - "password text", - "popup menu", - "progress bar", - "push button", - "radio button", - "radio menu item", - "root pane", - "row header", - "scroll bar", - "scroll pane", - "separator", - "slider", - "split pane", - "spin button", - "statusbar", - "table", - "table cell", - "table column header", - "table row header", - "tear off menu item", - "terminal", - "text", - "toggle button", - "tool bar", - "tool tip", - "tree", - "tree table", - "unknown", - "viewport", - "window", - "header", - "footer", - "paragraph", - "ruler", - "application", - "autocomplete", - "edit bar", - "embedded component", - "entry", - "chart", - "caption", - "document frame", - "heading", - "page", - "section", - "redundant object", - "form", - "link", - "input method window", - "table row", - "tree item", - "document spreadsheet", - "document presentation", - "document text", - "document web", - "document email", - "comment", - "list box", - "grouping", - "image map", - "notification", - "info bar", - "level bar", - "title bar", - "block quote", - "audio", - "video", - "definition", - "article", - "landmark", - "log", - "marquee", - "math", - "rating", - "timer", - "description list", - "description term", - "description value", - "static", - "math fraction", - "math root", - "subscript", - "superscript", - "footnote", // ATK_ROLE_FOOTNOTE = 122. -}; +AtkObject* GetActiveDescendantOfCurrentFocused() { + if (!g_current_focused) + return nullptr; -#if defined(ATK_216) -constexpr AtkRole kStaticRole = ATK_ROLE_STATIC; -constexpr AtkRole kSubscriptRole = ATK_ROLE_SUBSCRIPT; -constexpr AtkRole kSuperscriptRole = ATK_ROLE_SUPERSCRIPT; -#else -constexpr AtkRole kStaticRole = ATK_ROLE_TEXT; -constexpr AtkRole kSubscriptRole = ATK_ROLE_TEXT; -constexpr AtkRole kSuperscriptRole = ATK_ROLE_TEXT; -#endif + auto* node = AtkObjectToAXPlatformNodeAuraLinux(g_current_focused); + if (!node) + return nullptr; -#if defined(ATK_226) -constexpr AtkRole kAtkFootnoteRole = ATK_ROLE_FOOTNOTE; -#else -constexpr AtkRole kAtkFootnoteRole = ATK_ROLE_LIST_ITEM; -#endif + int32_t id = + node->GetIntAttribute(ax::mojom::IntAttribute::kActivedescendantId); + if (auto* descendant = node->GetDelegate()->GetFromNodeID(id)) + return descendant->GetNativeViewAccessible(); + + return nullptr; +} namespace atk_component { @@ -1748,7 +1582,7 @@ } GPtrArray* GetColumnHeaderCells(AtkTableCell* cell) { - GPtrArray* array = g_ptr_array_new(); + GPtrArray* array = g_ptr_array_new_with_free_func(g_object_unref); // AtkTableCell is implemented on cells, row headers, and column headers. // Calling GetColHeaderNodeIds() on a column header cell will include that @@ -1757,12 +1591,20 @@ // headers for non-header cells. if (atk_object_get_role(ATK_OBJECT(cell)) != ATK_ROLE_TABLE_CELL) return array; + auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(cell)); + if (!obj) + return array; + auto* table = obj->GetTable(); + if (!table) + return array; - if (auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(cell))) { - if (auto* table = obj->GetTable()) { - std::vector<int32_t> ids = - table->GetDelegate()->GetColHeaderNodeIds(obj->GetTableColumn()); - IdsToGPtrArray(table->GetDelegate(), ids, array); + std::vector<int32_t> ids = + table->GetDelegate()->GetColHeaderNodeIds(obj->GetTableColumn()); + for (const auto& node_id : ids) { + if (AXPlatformNode* node = table->GetDelegate()->GetFromNodeID(node_id)) { + if (AtkObject* atk_node = node->GetNativeViewAccessible()) { + g_ptr_array_add(array, g_object_ref(atk_node)); + } } } @@ -1787,7 +1629,7 @@ } GPtrArray* GetRowHeaderCells(AtkTableCell* cell) { - GPtrArray* array = g_ptr_array_new(); + GPtrArray* array = g_ptr_array_new_with_free_func(g_object_unref); // AtkTableCell is implemented on cells, row headers, and column headers. // Calling GetRowHeaderNodeIds() on a row header cell will include that @@ -1796,12 +1638,20 @@ // headers for non-header cells. if (atk_object_get_role(ATK_OBJECT(cell)) != ATK_ROLE_TABLE_CELL) return array; + auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(cell)); + if (!obj) + return array; + auto* table = obj->GetTable(); + if (!table) + return array; - if (auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(cell))) { - if (auto* table = obj->GetTable()) { - std::vector<int32_t> ids = - table->GetDelegate()->GetRowHeaderNodeIds(obj->GetTableRow()); - IdsToGPtrArray(table->GetDelegate(), ids, array); + std::vector<int32_t> ids = + table->GetDelegate()->GetRowHeaderNodeIds(obj->GetTableRow()); + for (const auto& node_id : ids) { + if (AXPlatformNode* node = table->GetDelegate()->GetFromNodeID(node_id)) { + if (AtkObject* atk_node = node->GetNativeViewAccessible()) { + g_ptr_array_add(array, g_object_ref(atk_node)); + } } } @@ -2011,6 +1861,25 @@ } // namespace +// static +base::Optional<AtkTableCellInterface> AtkTableCellInterface::Get() { + static base::Optional<AtkTableCellInterface> interface = base::nullopt; + if (interface.has_value()) + return interface->GetType ? interface : base::nullopt; + + interface.emplace(); + interface->GetType = reinterpret_cast<GetTypeFunc>( + dlsym(RTLD_DEFAULT, "atk_table_cell_get_type")); + interface->GetColumnHeaderCells = reinterpret_cast<GetColumnHeaderCellsFunc>( + dlsym(RTLD_DEFAULT, "atk_table_cell_get_column_header_cells")); + interface->GetRowHeaderCells = reinterpret_cast<GetRowHeaderCellsFunc>( + dlsym(RTLD_DEFAULT, "atk_table_cell_get_row_header_cells")); + interface->GetRowColumnSpan = reinterpret_cast<GetRowColumnSpanFunc>( + dlsym(RTLD_DEFAULT, "atk_table_cell_get_row_column_span")); + interface->initialized = true; + return interface->GetType ? interface : base::nullopt; +} + void AXPlatformNodeAuraLinux::EnsureGTypeInit() { #if !GLIB_CHECK_VERSION(2, 36, 0) static bool first_time = true; @@ -2123,10 +1992,14 @@ if (interface_mask_ & (1 << ATK_TABLE_INTERFACE)) g_type_add_interface_static(type, ATK_TYPE_TABLE, &atk_table::Info); - // Run-time check to ensure AtkTableCell is supported (requires ATK 2.12). - if (LoadTableCellMethods() && - interface_mask_ & (1 << ATK_TABLE_CELL_INTERFACE)) - g_type_add_interface_static(type, cell_get_type(), &atk_table_cell::Info); + if (interface_mask_ & (1 << ATK_TABLE_CELL_INTERFACE)) { + // Run-time check to ensure AtkTableCell is supported (requires ATK 2.12). + auto interface = AtkTableCellInterface::Get(); + if (interface.has_value()) { + g_type_add_interface_static(type, interface->GetType(), + &atk_table_cell::Info); + } + } return type; } @@ -2570,22 +2443,6 @@ } } -static AtkObject* GetActiveDescendantOfCurrentFocused() { - if (!g_current_focused) - return nullptr; - - auto* node = AtkObjectToAXPlatformNodeAuraLinux(g_current_focused); - if (!node) - return nullptr; - - int32_t id = - node->GetIntAttribute(ax::mojom::IntAttribute::kActivedescendantId); - if (auto* descendant = node->GetDelegate()->GetFromNodeID(id)) - return descendant->GetNativeViewAccessible(); - - return nullptr; -} - void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) { AXNodeData data = GetData(); @@ -2856,179 +2713,6 @@ } } -void AXPlatformNodeAuraLinux::AddAccessibilityTreeProperties( - base::DictionaryValue* dict) { - AtkRole role = GetAtkRole(); - if (role != ATK_ROLE_UNKNOWN) { - int role_index = static_cast<int>(role); - dict->SetString("role", kRoleNames[role_index]); - } - const gchar* name = atk_object_get_name(atk_object_); - if (name) - dict->SetString("name", std::string(name)); - const gchar* description = atk_object_get_description(atk_object_); - if (description) - dict->SetString("description", std::string(description)); - - AtkStateSet* state_set = atk_object_ref_state_set(atk_object_); - auto states = std::make_unique<base::ListValue>(); - for (int i = ATK_STATE_INVALID; i < ATK_STATE_LAST_DEFINED; i++) { - AtkStateType state_type = static_cast<AtkStateType>(i); - if (atk_state_set_contains_state(state_set, state_type)) - states->AppendString(atk_state_type_get_name(state_type)); - } - dict->Set("states", std::move(states)); - - AtkRelationSet* relation_set = atk_object_ref_relation_set(atk_object_); - auto relations = std::make_unique<base::ListValue>(); - for (int i = ATK_RELATION_NULL; i < ATK_RELATION_LAST_DEFINED; i++) { - AtkRelationType relation_type = static_cast<AtkRelationType>(i); - if (atk_relation_set_contains(relation_set, relation_type)) - relations->AppendString(atk_relation_type_get_name(relation_type)); - } - dict->Set("relations", std::move(relations)); - - AtkAttributeSet* attributes = atk_object_get_attributes(atk_object_); - for (AtkAttributeSet* attr = attributes; attr; attr = attr->next) { - AtkAttribute* attribute = static_cast<AtkAttribute*>(attr->data); - dict->SetString(attribute->name, attribute->value); - } - atk_attribute_set_free(attributes); - - // Properties obtained via AtkValue. - auto value_properties = std::make_unique<base::ListValue>(); - if (ATK_IS_VALUE(atk_object_)) { - AtkValue* value = ATK_VALUE(atk_object_); - GValue current = G_VALUE_INIT; - g_value_init(¤t, G_TYPE_FLOAT); - atk_value_get_current_value(value, ¤t); - value_properties->AppendString( - base::StringPrintf("current=%f", g_value_get_float(¤t))); - - GValue minimum = G_VALUE_INIT; - g_value_init(&minimum, G_TYPE_FLOAT); - atk_value_get_minimum_value(value, &minimum); - value_properties->AppendString( - base::StringPrintf("minimum=%f", g_value_get_float(&minimum))); - - GValue maximum = G_VALUE_INIT; - g_value_init(&maximum, G_TYPE_FLOAT); - atk_value_get_maximum_value(value, &maximum); - value_properties->AppendString( - base::StringPrintf("maximum=%f", g_value_get_float(&maximum))); - } - dict->Set("value", std::move(value_properties)); - - // Properties obtained via AtkTable. - auto table_properties = std::make_unique<base::ListValue>(); - if (ATK_IS_TABLE(atk_object_)) { - AtkTable* table = ATK_TABLE(atk_object_); - - // Column details. - int n_cols = atk_table_get_n_columns(table); - table_properties->AppendString(base::StringPrintf("cols=%i", n_cols)); - - std::vector<std::string> col_headers; - for (int i = 0; i < n_cols; i++) { - std::string header = atk_table_get_column_description(table, i); - if (!header.empty()) - col_headers.push_back(base::StringPrintf("'%s'", header.c_str())); - } - - if (!col_headers.size()) - col_headers.push_back("NONE"); - - table_properties->AppendString(base::StringPrintf( - "headers=(%s);", base::JoinString(col_headers, ", ").c_str())); - - // Row details. - int n_rows = atk_table_get_n_rows(table); - table_properties->AppendString(base::StringPrintf("rows=%i", n_rows)); - - std::vector<std::string> row_headers; - for (int i = 0; i < n_rows; i++) { - std::string header = atk_table_get_row_description(table, i); - if (!header.empty()) - row_headers.push_back(base::StringPrintf("'%s'", header.c_str())); - } - - if (!row_headers.size()) - row_headers.push_back("NONE"); - - table_properties->AppendString(base::StringPrintf( - "headers=(%s);", base::JoinString(row_headers, ", ").c_str())); - - // Caption details. - AtkObject* caption = atk_table_get_caption(table); - table_properties->AppendString( - base::StringPrintf("caption=%s;", caption ? "true" : "false")); - - // Summarize information about the cells from the table's perspective here. - std::vector<std::string> span_info; - for (int r = 0; r < n_rows; r++) { - for (int c = 0; c < n_cols; c++) { - int row_span = atk_table_get_row_extent_at(table, r, c); - int col_span = atk_table_get_column_extent_at(table, r, c); - if (row_span != 1 || col_span != 1) { - span_info.push_back(base::StringPrintf("cell at %i,%i: %ix%i", r, c, - row_span, col_span)); - } - } - } - if (!span_info.size()) - span_info.push_back("all: 1x1"); - - table_properties->AppendString(base::StringPrintf( - "spans=(%s)", base::JoinString(span_info, ", ").c_str())); - } - - dict->Set("table", std::move(table_properties)); - - // Properties obtained via AtkTableCell, if possible. If we do not have at - // least ATK 2.12, use the same logic in our AtkTableCell implementation so - // that tests can still be run. - auto cell_properties = std::make_unique<base::ListValue>(); - if (role == ATK_ROLE_TABLE_CELL || role == ATK_ROLE_COLUMN_HEADER || - role == ATK_ROLE_ROW_HEADER) { - int row, col, row_span, col_span; - GPtrArray* col_headers; - GPtrArray* row_headers; - if (cell_get_type) { - AtkTableCell* cell = G_TYPE_CHECK_INSTANCE_CAST( - (atk_object_), cell_get_type(), AtkTableCell); - col_headers = get_column_header_cells(cell); - row_headers = get_row_header_cells(cell); - get_row_column_span(cell, &row, &col, &row_span, &col_span); - } else { - auto* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object_); - if (!obj) - return; - row = obj->GetTableRow(); - col = obj->GetTableColumn(); - row_span = obj->GetTableRowSpan(); - col_span = obj->GetTableColumnSpan(); - col_headers = g_ptr_array_new(); - row_headers = g_ptr_array_new(); - if (role == ATK_ROLE_TABLE_CELL) { - auto* delegate = obj->GetTable()->GetDelegate(); - std::vector<int32_t> col_header_ids = - delegate->GetColHeaderNodeIds(col); - std::vector<int32_t> row_header_ids = - delegate->GetRowHeaderNodeIds(row); - IdsToGPtrArray(delegate, col_header_ids, col_headers); - IdsToGPtrArray(delegate, row_header_ids, row_headers); - } - } - cell_properties->AppendString( - base::StringPrintf("(row=%i, col=%i, row_span=%i, col_span=%i", row, - col, row_span, col_span)); - cell_properties->AppendString( - base::StringPrintf("n_row_headers=%i, n_col_headers=%i)", - row_headers->len, col_headers->len)); - } - dict->Set("cell", std::move(cell_properties)); -} - gfx::NativeViewAccessible AXPlatformNodeAuraLinux::GetNativeViewAccessible() { return atk_object_; }
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.h b/ui/accessibility/platform/ax_platform_node_auralinux.h index 8f24a35..243de66 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.h +++ b/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -28,6 +28,39 @@ namespace ui { +// AtkTableCell was introduced in ATK 2.12. Ubuntu Trusty has ATK 2.10. +// Compile-time checks are in place for ATK versions that are older than 2.12. +// However, we also need runtime checks in case the version we are building +// against is newer than the runtime version. To prevent a runtime error, we +// check that we have a version of ATK that supports AtkTableCell. If we do, +// we dynamically load the symbol; if we don't, the interface is absent from +// the accessible object and its methods will not be exposed or callable. +// The definitions below ensure we have no missing symbols. Note that in +// environments where we have ATK > 2.12, the definitions of AtkTableCell and +// AtkTableCellIface below are overridden by the runtime version. +// TODO(accessibility) Remove AtkTableCellInterface when 2.12 is the minimum +// supported version. +struct AX_EXPORT AtkTableCellInterface { + typedef struct _AtkTableCell AtkTableCell; + typedef struct _AtkTableCellIface AtkTableCellIface; + typedef GType (*GetTypeFunc)(); + typedef GPtrArray* (*GetColumnHeaderCellsFunc)(AtkTableCell* cell); + typedef GPtrArray* (*GetRowHeaderCellsFunc)(AtkTableCell* cell); + typedef bool (*GetRowColumnSpanFunc)(AtkTableCell* cell, + gint* row, + gint* column, + gint* row_span, + gint* col_span); + + GetTypeFunc GetType = nullptr; + GetColumnHeaderCellsFunc GetColumnHeaderCells = nullptr; + GetRowHeaderCellsFunc GetRowHeaderCells = nullptr; + GetRowColumnSpanFunc GetRowColumnSpan = nullptr; + bool initialized = false; + + static base::Optional<AtkTableCellInterface> Get(); +}; + // Implements accessibility on Aura Linux using ATK. class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase { public: @@ -46,7 +79,6 @@ void DataChanged(); void Destroy() override; - void AddAccessibilityTreeProperties(base::DictionaryValue* dict); AtkRole GetAtkRole(); void GetAtkState(AtkStateSet* state_set);
diff --git a/ui/base/clipboard/clipboard_mac.mm b/ui/base/clipboard/clipboard_mac.mm index 7ec5c99c..0a1ae03 100644 --- a/ui/base/clipboard/clipboard_mac.mm +++ b/ui/base/clipboard/clipboard_mac.mm
@@ -339,6 +339,7 @@ NOTREACHED() << "SkBitmapToNSImageWithColorSpace failed"; return; } + // TODO (https://crbug.com/971916): Write NSImage directly to clipboard. // An API to ask the NSImage to write itself to the clipboard comes in 10.6 :( // For now, spit out the image as a TIFF. NSPasteboard* pb = GetPasteboard();
diff --git a/ui/base/ime/mojo/ime_struct_traits_unittest.cc b/ui/base/ime/mojo/ime_struct_traits_unittest.cc index e261476..6ec9920 100644 --- a/ui/base/ime/mojo/ime_struct_traits_unittest.cc +++ b/ui/base/ime/mojo/ime_struct_traits_unittest.cc
@@ -6,8 +6,8 @@ #include <utility> -#include "base/message_loop/message_loop.h" #include "base/stl_util.h" +#include "base/test/scoped_task_environment.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ime/mojo/ime_struct_traits_test.mojom.h" @@ -35,7 +35,9 @@ std::move(callback).Run(in); } - base::MessageLoop loop_; // A MessageLoop is needed for Mojo IPC to work. + base::test::ScopedTaskEnvironment + scoped_task_environment_; // A MessageLoop is needed for Mojo IPC to + // work. mojo::BindingSet<mojom::IMEStructTraitsTest> traits_test_bindings_; DISALLOW_COPY_AND_ASSIGN(IMEStructTraitsTest);
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_parser.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_parser.js index 6de0e42..dc4680d 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_parser.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_parser.js
@@ -3,89 +3,94 @@ // found in the LICENSE file. /** - * @param {MetadataParserLogger} parent Parent object. - * @param {string} type Parser type. - * @param {RegExp} urlFilter RegExp to match URLs. - * @constructor - * @struct + * @implements {MetadataParserLogger} */ -function MetadataParser(parent, type, urlFilter) { - this.parent_ = parent; - this.type = type; - this.urlFilter = urlFilter; - this.verbose = parent.verbose; - this.mimeType = 'unknown'; -} +class MetadataParser { + /** + * @param {!MetadataParserLogger} parent Parent object. + * @param {string} type Parser type. + * @param {!RegExp} urlFilter RegExp to match URLs. + */ + constructor(parent, type, urlFilter) { + /** @private @const {!MetadataParserLogger} */ + this.parent_ = parent; + /** @public @const {string} */ + this.type = type; + /** @public @const {!RegExp} */ + this.urlFilter = urlFilter; + /** @public @const {boolean} */ + this.verbose = parent.verbose; + /** @public {string} */ + this.mimeType = 'unknown'; + } -/** - * Output an error message. - * @param {...(Object|string)} var_args Arguments. - */ -MetadataParser.prototype.error = function(var_args) { - this.parent_.error.apply(this.parent_, arguments); -}; + /** + * Output an error message. + * @param {...(Object|string)} var_args Arguments. + */ + error(var_args) { + this.parent_.error.apply(this.parent_, arguments); + } -/** - * Output a log message. - * @param {...(Object|string)} var_args Arguments. - */ -MetadataParser.prototype.log = function(var_args) { - this.parent_.log.apply(this.parent_, arguments); -}; - -/** - * Output a log message if |verbose| flag is on. - * @param {...(Object|string)} var_args Arguments. - */ -MetadataParser.prototype.vlog = function(var_args) { - if (this.verbose) { + /** + * Output a log message. + * @param {...(Object|string)} var_args Arguments. + */ + log(var_args) { this.parent_.log.apply(this.parent_, arguments); } -}; -/** - * @return {Object} Metadata object with the minimal set of properties. - */ -MetadataParser.prototype.createDefaultMetadata = function() { - return {type: this.type, mimeType: this.mimeType}; -}; + /** + * Output a log message if |verbose| flag is on. + * @param {...(Object|string)} var_args Arguments. + */ + vlog(var_args) { + if (this.verbose) { + this.parent_.log.apply(this.parent_, arguments); + } + } -/** - * Utility function to read specified range of bytes from file - * @param {File} file The file to read. - * @param {number} begin Starting byte(included). - * @param {number} end Last byte(excluded). - * @param {function(File, ByteReader)} callback Callback to invoke. - * @param {function(string)} onError Error handler. - */ -MetadataParser.readFileBytes = (file, begin, end, callback, onError) => { - const fileReader = new FileReader(); - fileReader.onerror = event => { - onError(event.type); - }; - fileReader.onloadend = () => { - callback( - file, - new ByteReader( - /** @type {ArrayBuffer} */ (fileReader.result))); - }; - fileReader.readAsArrayBuffer(file.slice(begin, end)); -}; + /** + * @return {Object} Metadata object with the minimal set of properties. + */ + createDefaultMetadata() { + return {type: this.type, mimeType: this.mimeType}; + } + + /** + * Utility function to read specified range of bytes from file + * @param {File} file The file to read. + * @param {number} begin Starting byte(included). + * @param {number} end Last byte(excluded). + * @param {function(File, ByteReader)} callback Callback to invoke. + * @param {function(string)} onError Error handler. + */ + static readFileBytes(file, begin, end, callback, onError) { + const fileReader = new FileReader(); + fileReader.onerror = event => { + onError(event.type); + }; + fileReader.onloadend = () => { + callback( + file, + new ByteReader( + /** @type {ArrayBuffer} */ (fileReader.result))); + }; + fileReader.readAsArrayBuffer(file.slice(begin, end)); + } +} /** * Base class for image metadata parsers. - * @param {MetadataParserLogger} parent Parent object. - * @param {string} type Image type. - * @param {RegExp} urlFilter RegExp to match URLs. - * @constructor - * @struct - * @extends {MetadataParser} */ -function ImageParser(parent, type, urlFilter) { - MetadataParser.apply(this, arguments); - this.mimeType = 'image/' + this.type; +class ImageParser extends MetadataParser { + /** + * @param {!MetadataParserLogger} parent Parent object. + * @param {string} type Image type. + * @param {!RegExp} urlFilter RegExp to match URLs. + */ + constructor(parent, type, urlFilter) { + super(parent, type, urlFilter); + this.mimeType = 'image/' + this.type; + } } - -ImageParser.prototype = { - __proto__: MetadataParser.prototype -};
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc index eb548c2f..68296bb 100644 --- a/ui/gl/gl_gl_api_implementation.cc +++ b/ui/gl/gl_gl_api_implementation.cc
@@ -469,8 +469,7 @@ } void RealGLApi::glUseProgramFn(GLuint program) { - ui::gl::ShaderTracking* shader_tracking = - ui::gl::ShaderTracking::GetInstance(); + ShaderTracking* shader_tracking = ShaderTracking::GetInstance(); if (shader_tracking) { std::vector<char> buffers[2]; char* strings[2] = {nullptr, nullptr}; @@ -485,8 +484,8 @@ GLuint shaders[2] = {0}; glGetAttachedShadersFn(program, 2, &count, shaders); for (GLsizei ii = 0; ii < std::min(2, count); ++ii) { - buffers[ii].resize(ui::gl::ShaderTracking::kMaxShaderSize); - glGetShaderSourceFn(shaders[ii], ui::gl::ShaderTracking::kMaxShaderSize, + buffers[ii].resize(ShaderTracking::kMaxShaderSize); + glGetShaderSourceFn(shaders[ii], ShaderTracking::kMaxShaderSize, nullptr, buffers[ii].data()); strings[ii] = buffers[ii].data(); }
diff --git a/ui/gl/shader_tracking.cc b/ui/gl/shader_tracking.cc index eb4480c..8836224 100644 --- a/ui/gl/shader_tracking.cc +++ b/ui/gl/shader_tracking.cc
@@ -7,7 +7,6 @@ #include "base/logging.h" #include "ui/gl/gl_switches.h" -namespace ui { namespace gl { // static @@ -39,4 +38,3 @@ } } // namespace gl -} // namespace ui
diff --git a/ui/gl/shader_tracking.h b/ui/gl/shader_tracking.h index b83ac6f..7fb7b58a 100644 --- a/ui/gl/shader_tracking.h +++ b/ui/gl/shader_tracking.h
@@ -13,7 +13,6 @@ #include "build/build_config.h" #include "ui/gl/gl_export.h" -namespace ui { namespace gl { class GL_EXPORT ShaderTracking { @@ -39,6 +38,5 @@ }; } // namespace gl -} // namespace ui #endif // UI_GL_SHADER_TRACKING_H_
diff --git a/ui/latency/mojo/struct_traits_unittest.cc b/ui/latency/mojo/struct_traits_unittest.cc index 4f03eecc..6ada7af8 100644 --- a/ui/latency/mojo/struct_traits_unittest.cc +++ b/ui/latency/mojo/struct_traits_unittest.cc
@@ -4,7 +4,7 @@ #include <utility> -#include "base/message_loop/message_loop.h" +#include "base/test/scoped_task_environment.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/latency/mojo/latency_info_struct_traits.h" @@ -32,7 +32,7 @@ std::move(callback).Run(info); } - base::MessageLoop loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; mojo::BindingSet<TraitsTestService> traits_test_bindings_; DISALLOW_COPY_AND_ASSIGN(StructTraitsTest); };
diff --git a/ui/login/OWNERS b/ui/login/OWNERS index 9570de68..43c2ba7 100644 --- a/ui/login/OWNERS +++ b/ui/login/OWNERS
@@ -1,4 +1,9 @@ +# (in PST) achuith@chromium.org alemate@chromium.org tbarzic@chromium.org xiyuan@chromium.org + +# (in CET) +antrim@chromium.org +rsorokin@chromium.org
diff --git a/ui/login/display_manager.js b/ui/login/display_manager.js index f2cf183..f766edf 100644 --- a/ui/login/display_manager.js +++ b/ui/login/display_manager.js
@@ -522,6 +522,9 @@ if (oldStep.onBeforeHide) oldStep.onBeforeHide(); + if (oldStep.defaultControl && oldStep.defaultControl.onBeforeHide) + oldStep.defaultControl.onBeforeHide(); + $('oobe').className = nextStepId; // Need to do this before calling newStep.onBeforeShow() so that new step
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc index b6c85ef..3f163a0 100644 --- a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc +++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
@@ -558,7 +558,7 @@ void WaylandBufferManagerHost::CreateShmBasedBuffer( gfx::AcceleratedWidget widget, mojo::ScopedHandle shm_fd, - size_t length, + uint64_t length, const gfx::Size& size, uint32_t buffer_id) { DCHECK(base::MessageLoopCurrentForUI::IsSet());
diff --git a/ui/views/controls/editable_combobox/editable_combobox.cc b/ui/views/controls/editable_combobox/editable_combobox.cc index 410cb92..23b6e4f 100644 --- a/ui/views/controls/editable_combobox/editable_combobox.cc +++ b/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -249,6 +249,51 @@ DISALLOW_COPY_AND_ASSIGN(EditableComboboxMenuModel); }; +// This class adds itself as the pre-target handler for the RootView of the +// EditableCombobox. We use it to close the menu when press events happen in the +// RootView but not inside the EditableComboobox's textfield. +class EditableCombobox::EditableComboboxPreTargetHandler + : public ui::EventHandler { + public: + EditableComboboxPreTargetHandler(EditableCombobox* owner, View* root_view) + : owner_(owner), root_view_(root_view) { + root_view_->AddPreTargetHandler(this); + } + + ~EditableComboboxPreTargetHandler() override { StopObserving(); } + + // ui::EventHandler overrides. + void OnMouseEvent(ui::MouseEvent* event) override { + if (event->type() == ui::ET_MOUSE_PRESSED && + event->flags() == event->changed_button_flags()) + HandlePressEvent(event->root_location()); + } + void OnTouchEvent(ui::TouchEvent* event) override { + if (event->type() == ui::ET_TOUCH_PRESSED) + HandlePressEvent(event->root_location()); + } + + private: + void HandlePressEvent(const gfx::Point& root_location) { + View* handler = root_view_->GetEventHandlerForPoint(root_location); + if (handler == owner_->textfield_ || handler == owner_->arrow_) + return; + owner_->CloseMenu(); + } + + void StopObserving() { + if (!root_view_) + return; + root_view_->RemovePreTargetHandler(this); + root_view_ = nullptr; + } + + EditableCombobox* owner_; + View* root_view_; + + DISALLOW_COPY_AND_ASSIGN(EditableComboboxPreTargetHandler); +}; + //////////////////////////////////////////////////////////////////////////////// // EditableCombobox, public, non-overridden methods: EditableCombobox::EditableCombobox( @@ -423,6 +468,7 @@ void EditableCombobox::CloseMenu() { menu_runner_.reset(); + pre_target_handler_.reset(); } void EditableCombobox::OnItemSelected(int index) { @@ -466,6 +512,15 @@ if (!textfield_->HasFocus() || (menu_runner_ && menu_runner_->IsRunning())) return; + // Since we don't capture the mouse, we want to see the events that happen in + // the EditableCombobox's RootView to get a chance to close the menu if they + // happen outside |textfield_|. Events that happen over the menu belong to + // another Widget and they don't go through this pre-target handler. + // Events that happen outside both the menu and the RootView cause + // OnViewBlurred to be called, which also closes the menu. + pre_target_handler_ = std::make_unique<EditableComboboxPreTargetHandler>( + this, GetWidget()->GetRootView()); + gfx::Rect local_bounds = textfield_->GetLocalBounds(); gfx::Point menu_position(local_bounds.origin()); // Inset the menu's requested position so the border of the menu lines up
diff --git a/ui/views/controls/editable_combobox/editable_combobox.h b/ui/views/controls/editable_combobox/editable_combobox.h index c0f59314..0386dfb 100644 --- a/ui/views/controls/editable_combobox/editable_combobox.h +++ b/ui/views/controls/editable_combobox/editable_combobox.h
@@ -31,6 +31,7 @@ namespace views { class EditableComboboxMenuModel; class EditableComboboxListener; +class EditableComboboxPreTargetHandler; class MenuRunner; class Textfield; @@ -104,6 +105,7 @@ private: class EditableComboboxMenuModel; + class EditableComboboxPreTargetHandler; void CloseMenu(); @@ -142,6 +144,11 @@ // The EditableComboboxMenuModel used by |menu_runner_|. std::unique_ptr<EditableComboboxMenuModel> menu_model_; + // Pre-target handler that closes the menu when press events happen in the + // root view (outside of the open menu's boundaries) but not inside the + // textfield. + std::unique_ptr<EditableComboboxPreTargetHandler> pre_target_handler_; + // Typography context for the text written in the textfield and the options // shown in the drop-down menu. const int text_context_;
diff --git a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc index c9f42e5..396f86bb 100644 --- a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc +++ b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
@@ -100,6 +100,10 @@ EditableCombobox* combobox_ = nullptr; View* dummy_focusable_view_ = nullptr; + // We make |combobox_| a child of another View to test different removal + // scenarios. + View* parent_of_combobox_ = nullptr; + // Listener for our EditableCombobox. std::unique_ptr<DummyListener> listener_; @@ -135,15 +139,17 @@ const bool filter_on_edit, const bool show_on_empty, const EditableCombobox::Type type) { + parent_of_combobox_ = new View(); + parent_of_combobox_->SetID(1); combobox_ = new EditableCombobox(std::make_unique<ui::SimpleComboboxModel>(items), filter_on_edit, show_on_empty, type); listener_ = std::make_unique<DummyListener>(); combobox_->set_listener(listener_.get()); - combobox_->SetID(1); + combobox_->SetID(2); dummy_focusable_view_ = new View(); dummy_focusable_view_->SetFocusBehavior(View::FocusBehavior::ALWAYS); - dummy_focusable_view_->SetID(2); + dummy_focusable_view_->SetID(3); InitWidget(); } @@ -154,11 +160,14 @@ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.bounds = gfx::Rect(0, 0, 1000, 1000); + parent_of_combobox_->SetBoundsRect(gfx::Rect(0, 0, 500, 40)); + combobox_->SetBoundsRect(gfx::Rect(0, 0, 500, 40)); + widget_->Init(params); View* container = new View(); widget_->SetContentsView(container); - container->AddChildView(combobox_); - combobox_->SetBoundsRect(gfx::Rect(0, 0, 500, 40)); + container->AddChildView(parent_of_combobox_); + parent_of_combobox_->AddChildView(combobox_); container->AddChildView(dummy_focusable_view_); widget_->Show(); @@ -256,6 +265,51 @@ EXPECT_FALSE(IsMenuOpen()); } +TEST_F(EditableComboboxTest, + ClickOutsideEditableComboboxWithoutLosingFocusClosesMenu) { + InitEditableCombobox(); + combobox_->GetTextfieldForTest()->RequestFocus(); + EXPECT_TRUE(IsMenuOpen()); + + const gfx::Point outside_point(combobox_->x() + combobox_->width() + 1, + combobox_->y() + 1); + PerformClick(widget_, outside_point); + + WaitForMenuClosureAnimation(); + EXPECT_FALSE(IsMenuOpen()); + EXPECT_TRUE(combobox_->GetTextfieldForTest()->HasFocus()); +} + +TEST_F(EditableComboboxTest, ClickTextfieldDoesntCloseMenu) { + InitEditableCombobox(); + combobox_->GetTextfieldForTest()->RequestFocus(); + EXPECT_TRUE(IsMenuOpen()); + + MenuRunner* menu_runner1 = combobox_->GetMenuRunnerForTest(); + ClickTextfield(); + MenuRunner* menu_runner2 = combobox_->GetMenuRunnerForTest(); + EXPECT_TRUE(IsMenuOpen()); + + // Making sure the menu didn't close and reopen (causing a flicker). + EXPECT_EQ(menu_runner1, menu_runner2); +} + +TEST_F(EditableComboboxTest, RemovingControlWhileMenuOpenClosesMenu) { + InitEditableCombobox(); + combobox_->GetTextfieldForTest()->RequestFocus(); + EXPECT_TRUE(IsMenuOpen()); + parent_of_combobox_->RemoveChildView(combobox_); + EXPECT_EQ(nullptr, combobox_->GetMenuRunnerForTest()); +} + +TEST_F(EditableComboboxTest, RemovingParentOfControlWhileMenuOpenClosesMenu) { + InitEditableCombobox(); + combobox_->GetTextfieldForTest()->RequestFocus(); + EXPECT_TRUE(IsMenuOpen()); + widget_->GetContentsView()->RemoveChildView(parent_of_combobox_); + EXPECT_EQ(nullptr, combobox_->GetMenuRunnerForTest()); +} + TEST_F(EditableComboboxTest, LeftOrRightKeysMoveInTextfield) { InitEditableCombobox(); combobox_->GetTextfieldForTest()->RequestFocus();