diff --git a/DEPS b/DEPS index c47e99d1..500daca 100644 --- a/DEPS +++ b/DEPS
@@ -269,19 +269,19 @@ # 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': '3dc829746aace492c8e5871ab6da905fb6c56a08', + 'skia_revision': '1186b60fcfac987c2264d95f1a4a98018c718e19', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '62f0387a92f1e5987dae85682c845c244a3b175a', + 'v8_revision': 'a0762ead80f58826ff6e09e19bccdc0bd65fc84b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '40269f91c3ae0fd1a2f02e30aa5a38fe03cf08f6', + 'angle_revision': '118a6484c8d008af595abe87ab91ee98f9006c4d', # 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': '3ce90c53592847ef69206569d46bfc217a3b7bc2', + 'swiftshader_revision': '73679602bc0be54c3fba1caaf2141b05f19aa468', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -348,7 +348,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'f1dd54487ab166f8e11e81a784f09be2402d0929', + 'devtools_frontend_revision': '5baff14b8c6a722d0cf426134c366c43f92c562a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -384,7 +384,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': '92244ec9d463a705d0ef3542223e13b523f08854', + 'dawn_revision': 'e9ce8326b7843be34e8a31a5a54600cb924c83f2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -745,7 +745,7 @@ }, 'src/ios/third_party/earl_grey2/src': { - 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '02c5d69c82143d3d7867362dce01088467bee107', + 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'd6f38aa83c84f31185b16b8f138cace09c8343f5', 'condition': 'checkout_ios', }, @@ -765,7 +765,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '2ff701bbbeacb133aad87956b58d97dac86cfc8d', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '31892cf6c20691aac39b9f17278e08ded01aa491', 'condition': 'checkout_ios', }, @@ -914,7 +914,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'BYxYEZvLrXS8AvKaRJNfGUwJEjLslkbSYUdG0kDQ4p8C', + 'version': 'ysPZmJ22H1d0s_hhsbD8Z_63nV2LPoUuz24Ll_Xk788C', }, ], 'condition': 'checkout_android', @@ -1705,7 +1705,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '0dd7405d1bfa950a71572aeb77aa38aacef6653d', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'ab8c1e50a3b3a15258b23120995ab7845ca40929', + Var('webrtc_git') + '/src.git' + '@' + 'f4fcdf1ee1fd5752f2af13fe731f5638363722ef', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1778,7 +1778,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1ef4e54b5094d0c65477fab41c082c7cd16110a4', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9b3abfc9a1e2ea583c82b857c612365e5d093d67', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni index 7930451..86f8504 100644 --- a/android_webview/system_webview_apk_tmpl.gni +++ b/android_webview/system_webview_apk_tmpl.gni
@@ -153,16 +153,6 @@ _include_primary_support = true } secondary_native_lib_placeholders = [ "libdummy.so" ] - static_library_provider_use_secondary_abi = true - } - - # http://crbug.com/1042107. - if (is_component_build) { - if (invoker.is_64_bit_browser) { - main_component_library = "libmonochrome_64.cr.so" - } else { - main_component_library = "libmonochrome.cr.so" - } } } else { native_lib_placeholders = [ "libdummy.so" ]
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index a48e53c..ea8e3541 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -3302,6 +3302,8 @@ "test/ash_test_helper.h", "test/ash_test_suite.cc", "test/ash_test_suite.h", + "test/ash_test_util.cc", + "test/ash_test_util.h", "test/ash_test_views_delegate.cc", "test/ash_test_views_delegate.h", "test/fake_android_intent_helper.cc", @@ -3445,6 +3447,7 @@ "//ui/ozone", "//ui/platform_window/common", "//ui/shell_dialogs", + "//ui/snapshot:snapshot", "//ui/views", "//ui/views:test_support", "//ui/wm",
diff --git a/ash/app_list/app_list_metrics.cc b/ash/app_list/app_list_metrics.cc index e02ec2a8..8d8cdcd 100644 --- a/ash/app_list/app_list_metrics.cc +++ b/ash/app_list/app_list_metrics.cc
@@ -289,7 +289,7 @@ // Ignore the OEM folder and the "Linux apps" folder because those folders // are automatically created. The following metrics are trying to measure // how often users engage with folders that they created themselves. - if (folder->IsPersistent()) + if (folder->IsSystemFolder()) continue; number_of_apps_in_non_system_folders += folder->item_list()->item_count(); number_of_non_system_folders++;
diff --git a/ash/app_list/app_list_metrics_unittest.cc b/ash/app_list/app_list_metrics_unittest.cc index 5b54a452..0ff07b8 100644 --- a/ash/app_list/app_list_metrics_unittest.cc +++ b/ash/app_list/app_list_metrics_unittest.cc
@@ -900,12 +900,12 @@ "Apps.AppList.NumberOfAppsInNonSystemFolders", 2)); } -TEST_F(AppListPeriodicMetricsTest, RecordFolderMetrics_PersistentFolder) { +TEST_F(AppListPeriodicMetricsTest, RecordFolderMetrics_SystemFolder) { base::HistogramTester histogram; AppListFolderItem* folder = GetAppListTestHelper()->model()->CreateSingleItemFolder("folder_id", "item_id"); - folder->SetIsPersistent(true); + folder->SetIsSystemFolder(true); RecordPeriodicAppListMetrics();
diff --git a/ash/app_list/model/app_list_folder_item.cc b/ash/app_list/model/app_list_folder_item.cc index d73bed7f..63ab079 100644 --- a/ash/app_list/model/app_list_folder_item.cc +++ b/ash/app_list/model/app_list_folder_item.cc
@@ -96,16 +96,16 @@ UpdateIsNewInstall(); } -bool AppListFolderItem::IsPersistent() const { - return GetMetadata()->is_persistent; +bool AppListFolderItem::IsSystemFolder() const { + return GetMetadata()->is_system_folder; } -void AppListFolderItem::SetIsPersistent(bool is_persistent) { - metadata()->is_persistent = is_persistent; +void AppListFolderItem::SetIsSystemFolder(bool is_system_folder) { + metadata()->is_system_folder = is_system_folder; } bool AppListFolderItem::ShouldAutoRemove() const { - return ChildItemCount() <= (IsPersistent() ? 0u : 1u); + return ChildItemCount() <= (IsSystemFolder() ? 0u : 1u); } std::string AppListFolderItem::GenerateId() {
diff --git a/ash/app_list/model/app_list_folder_item.h b/ash/app_list/model/app_list_folder_item.h index 76afd20..1d14e04 100644 --- a/ash/app_list/model/app_list_folder_item.h +++ b/ash/app_list/model/app_list_folder_item.h
@@ -92,9 +92,10 @@ // AppListItemObserver: void ItemIsNewInstallChanged() override; - // Persistent folders will be retained even if there is 1 app in them. - bool IsPersistent() const; - void SetIsPersistent(bool is_persistent); + // Whether this is a system created folder like the Linux apps folder or the + // OEM folder. + bool IsSystemFolder() const; + void SetIsSystemFolder(bool is_system_folder); // Returns true if this folder is a candidate for auto-removal (based on its // type and the number of children it has).
diff --git a/ash/app_list/model/app_list_model_unittest.cc b/ash/app_list/model/app_list_model_unittest.cc index 2b7a32b2..d66a8c8 100644 --- a/ash/app_list/model/app_list_model_unittest.cc +++ b/ash/app_list/model/app_list_model_unittest.cc
@@ -582,12 +582,12 @@ EXPECT_EQ("folder1", GetModelContents()); } -TEST_F(AppListModelFolderTest, UninstallPersistentFolderItem) { +TEST_F(AppListModelFolderTest, UninstallSystemFolderItem) { AppListItem* item0 = model_->CreateAndAddItem("Item 0"); AppListItem* item1 = model_->CreateAndAddItem("Item 1"); AppListFolderItem* folder1 = static_cast<AppListFolderItem*>( model_->AddItem(new AppListFolderItem("folder1", model_.get()))); - folder1->SetIsPersistent(true); + folder1->SetIsSystemFolder(true); EXPECT_EQ("Item 0,Item 1,folder1", GetModelContents()); // Move all items to folder1.
diff --git a/ash/components/arc/ime/arc_ime_bridge_impl.cc b/ash/components/arc/ime/arc_ime_bridge_impl.cc index 589d9e2..2bf6beb2 100644 --- a/ash/components/arc/ime/arc_ime_bridge_impl.cc +++ b/ash/components/arc/ime/arc_ime_bridge_impl.cc
@@ -79,7 +79,8 @@ return; ime_instance->SetCompositionText(base::UTF16ToUTF8(composition.text), - ConvertSegments(composition)); + ConvertSegments(composition), + composition.selection); } void ArcImeBridgeImpl::SendConfirmCompositionText() {
diff --git a/ash/components/arc/mojom/ime.mojom b/ash/components/arc/mojom/ime.mojom index 35343d3..0b688d88 100644 --- a/ash/components/arc/mojom/ime.mojom +++ b/ash/components/arc/mojom/ime.mojom
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Next MinVersion: 21 +// Next MinVersion: 22 module arc.mojom; @@ -151,7 +151,10 @@ [MinVersion=6] Init@6(pending_remote<ImeHost> host_remote) => (); // Sets composition text and attributes requested by the host IME. - SetCompositionText@1(string text, array<CompositionSegment> segments); + SetCompositionText@1( + string text, + array<CompositionSegment> segments, + [MinVersion=21] Range? selection_range); // Sets selection text and attributes requested by the host IME. [MinVersion=12] SetSelectionText@7(Range selection); @@ -166,8 +169,8 @@ // end of the text). If |new_cursor_position| <= 0, then it is relative to the // start (0 being the beginning of the text). InsertText@3( - string text, - [MinVersion=17] int32 new_cursor_position); + string text, + [MinVersion=17] int32 new_cursor_position); // Informs the virtual keyboard availability and bounds on screen is changing. // |is_available| whether a virtual keyboard is visible or not.
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 4945865..cdc00d80 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -1433,7 +1433,7 @@ // Uses new AuthSession-based API in cryptohome to authenticate users during // sign-in. const base::Feature kUseAuthsessionAuthentication{ - "UseAuthsessionAuthentication", base::FEATURE_ENABLED_BY_DEFAULT}; + "UseAuthsessionAuthentication", base::FEATURE_DISABLED_BY_DEFAULT}; // Enables using the BluetoothSystem Mojo interface for Bluetooth operations. const base::Feature kUseBluetoothSystemInAsh{"UseBluetoothSystemInAsh",
diff --git a/ash/display/screen_ash.cc b/ash/display/screen_ash.cc index 6400703a..e3ead6a 100644 --- a/ash/display/screen_ash.cc +++ b/ash/display/screen_ash.cc
@@ -42,6 +42,7 @@ : display_list_(screen_ash->GetAllDisplays()), primary_display_(screen_ash->GetPrimaryDisplay()) { SetDisplayForNewWindows(primary_display_.id()); + set_shutdown(true); } ScreenForShutdown(const ScreenForShutdown&) = delete;
diff --git a/ash/public/cpp/app_list/app_list_types.h b/ash/public/cpp/app_list/app_list_types.h index 6fe4657..2875eb15 100644 --- a/ash/public/cpp/app_list/app_list_types.h +++ b/ash/public/cpp/app_list/app_list_types.h
@@ -131,8 +131,12 @@ std::string folder_id; // Id of folder where the item resides. syncer::StringOrdinal position; // Position of the item. bool is_folder = false; // Whether this item is a folder. - bool is_persistent = false; // Whether this folder is allowed to contain only - // 1 item. + + // Whether the folder was system created (e.g. the OEM folder or Linux apps + // folder). Historically (pre-2022) these folders were the only ones allowed + // to contain a single item. + bool is_system_folder = false; + gfx::ImageSkia icon; // The icon of this item. bool is_page_break = false; // Whether this item is a "page break" item. SkColor badge_color = SK_ColorWHITE; // Notification badge color.
diff --git a/ash/shelf/shelf_context_menu_model_unittest.cc b/ash/shelf/shelf_context_menu_model_unittest.cc index fc25400..0209e3435 100644 --- a/ash/shelf/shelf_context_menu_model_unittest.cc +++ b/ash/shelf/shelf_context_menu_model_unittest.cc
@@ -4,6 +4,8 @@ #include "ash/shelf/shelf_context_menu_model.h" +#include <tuple> + #include "ash/constants/ash_features.h" #include "ash/public/cpp/app_menu_constants.h" #include "ash/public/cpp/shelf_item_delegate.h" @@ -21,6 +23,7 @@ #include "base/test/scoped_feature_list.h" #include "components/user_manager/user_type.h" #include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" #include "ui/display/display.h" #include "ui/views/widget/widget.h" @@ -38,9 +41,13 @@ class ShelfContextMenuModelTest : public AshTestBase, - public ::testing::WithParamInterface<user_manager::UserType> { + public ::testing::WithParamInterface< + std::tuple<user_manager::UserType, bool>> { public: - ShelfContextMenuModelTest() = default; + ShelfContextMenuModelTest() { + feature_list_.InitWithFeatureState(ash::features::kPersonalizationHub, + IsPersonalizationHubParamEnabled()); + } ShelfContextMenuModelTest(const ShelfContextMenuModelTest&) = delete; ShelfContextMenuModelTest& operator=(const ShelfContextMenuModelTest&) = @@ -58,7 +65,11 @@ session->SwitchActiveUser(AccountId::FromUserEmail("user1@test.com")); } - user_manager::UserType GetUserType() const { return GetParam(); } + user_manager::UserType GetUserType() const { return std::get<0>(GetParam()); } + + bool IsPersonalizationHubParamEnabled() const { + return std::get<1>(GetParam()); + } MockNewWindowDelegate* GetMockNewWindowDelegate() { return static_cast<MockNewWindowDelegate*>( @@ -66,6 +77,7 @@ } private: + base::test::ScopedFeatureList feature_list_; std::unique_ptr<TestNewWindowDelegateProvider> delegate_provider_; }; @@ -100,10 +112,12 @@ int last_executed_command_ = 0; }; -INSTANTIATE_TEST_SUITE_P(, - ShelfContextMenuModelTest, - ::testing::Values(user_manager::USER_TYPE_REGULAR, - user_manager::USER_TYPE_CHILD)); +INSTANTIATE_TEST_SUITE_P( + , + ShelfContextMenuModelTest, + ::testing::Combine(::testing::Values(user_manager::USER_TYPE_REGULAR, + user_manager::USER_TYPE_CHILD), + ::testing::Bool())); // Tests the default items in a shelf context menu. TEST_P(ShelfContextMenuModelTest, Basic) { @@ -112,7 +126,11 @@ ASSERT_EQ(3, menu.GetItemCount()); EXPECT_EQ(CommandId::MENU_AUTO_HIDE, menu.GetCommandIdAt(0)); EXPECT_EQ(CommandId::MENU_ALIGNMENT_MENU, menu.GetCommandIdAt(1)); - EXPECT_EQ(CommandId::MENU_CHANGE_WALLPAPER, menu.GetCommandIdAt(2)); + if (IsPersonalizationHubParamEnabled()) { + EXPECT_EQ(CommandId::MENU_PERSONALIZATION_HUB, menu.GetCommandIdAt(2)); + } else { + EXPECT_EQ(CommandId::MENU_CHANGE_WALLPAPER, menu.GetCommandIdAt(2)); + } for (int i = 0; i < menu.GetItemCount(); ++i) { EXPECT_TRUE(menu.IsEnabledAt(i)); EXPECT_TRUE(menu.IsVisibleAt(i)); @@ -162,32 +180,21 @@ TEST_P(ShelfContextMenuModelTest, OpensPersonalizationHubOrWallpaper) { int64_t display_id = GetPrimaryDisplay().id(); - base::test::ScopedFeatureList scoped_feature_list; - // Disable personalization hub feature should open wallpaper. - { - scoped_feature_list.InitAndDisableFeature( - ash::features::kPersonalizationHub); + ShelfContextMenuModel menu(nullptr, display_id); + + if (IsPersonalizationHubParamEnabled()) { + // Personalization hub feature enabled should open hub. + EXPECT_CALL(*GetMockNewWindowDelegate(), OpenPersonalizationHub).Times(1); + menu.ActivatedAt(2); + } else { TestWallpaperControllerClient client; Shell::Get()->wallpaper_controller()->SetClient(&client); EXPECT_EQ(0u, client.open_count()); - ShelfContextMenuModel menu_without_feature(nullptr, display_id); // Click the third option, wallpaper picker. It should open. - menu_without_feature.ActivatedAt(2); + menu.ActivatedAt(2); EXPECT_EQ(1u, client.open_count()); } - - scoped_feature_list.Reset(); - // Enable personalization hub feature should open hub. - { - EXPECT_CALL(*GetMockNewWindowDelegate(), OpenPersonalizationHub).Times(1); - - scoped_feature_list.InitAndEnableFeature( - ash::features::kPersonalizationHub); - - ShelfContextMenuModel menu_with_feature(nullptr, display_id); - menu_with_feature.ActivatedAt(2); - } } // Tests custom items in a shelf context menu for an application. @@ -249,8 +256,13 @@ ShelfContextMenuModel menu1(nullptr, primary_id); EXPECT_EQ(2, menu1.GetItemCount()); EXPECT_EQ(ShelfContextMenuModel::MENU_AUTO_HIDE, menu1.GetCommandIdAt(0)); - EXPECT_EQ(ShelfContextMenuModel::MENU_CHANGE_WALLPAPER, - menu1.GetCommandIdAt(1)); + if (IsPersonalizationHubParamEnabled()) { + EXPECT_EQ(ShelfContextMenuModel::MENU_PERSONALIZATION_HUB, + menu1.GetCommandIdAt(1)); + } else { + EXPECT_EQ(ShelfContextMenuModel::MENU_CHANGE_WALLPAPER, + menu1.GetCommandIdAt(1)); + } // Test that a menu shown out of tablet mode includes all three options: // MENU_AUTO_HIDE, MENU_ALIGNMENT_MENU, and MENU_CHANGE_WALLPAPER. @@ -282,8 +294,13 @@ EXPECT_TRUE(submenu->IsEnabledAt(2)); // Test the wallpaper picker option. - EXPECT_EQ(ShelfContextMenuModel::MENU_CHANGE_WALLPAPER, - menu2.GetCommandIdAt(2)); + if (IsPersonalizationHubParamEnabled()) { + EXPECT_EQ(ShelfContextMenuModel::MENU_PERSONALIZATION_HUB, + menu2.GetCommandIdAt(2)); + } else { + EXPECT_EQ(ShelfContextMenuModel::MENU_CHANGE_WALLPAPER, + menu2.GetCommandIdAt(2)); + } EXPECT_TRUE(menu2.IsEnabledAt(2)); }
diff --git a/ash/test/ash_test_util.cc b/ash/test/ash_test_util.cc new file mode 100644 index 0000000..fdd74337 --- /dev/null +++ b/ash/test/ash_test_util.cc
@@ -0,0 +1,50 @@ +// Copyright 2022 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/test/ash_test_util.h" + +#include "ash/shell.h" +#include "base/callback.h" +#include "base/files/file_util.h" +#include "base/run_loop.h" +#include "ui/gfx/image/image.h" +#include "ui/snapshot/snapshot_aura.h" + +namespace ash::test { + +namespace { +void SnapshotCallback(base::RunLoop* run_loop, + gfx::Image* ret_image, + gfx::Image image) { + *ret_image = image; + run_loop->Quit(); +} +} // namespace + +bool TakePrimaryDisplayScreenshotAndSave(const base::FilePath& file_path) { + // Return false if the file extension is not "png". + if (file_path.Extension() != ".png") + return false; + + // Return false if `file_path`'s directory does not exist. + const base::FilePath directory_name = file_path.DirName(); + if (!base::PathExists(directory_name)) + return false; + + base::RunLoop run_loop; + gfx::Image image; + ui::GrabWindowSnapshotAsyncAura( + Shell::Get()->GetPrimaryRootWindow(), + Shell::Get()->GetPrimaryRootWindow()->bounds(), + base::BindOnce(&SnapshotCallback, &run_loop, &image)); + run_loop.Run(); + auto data = image.As1xPNGBytes(); + int data_size = static_cast<int>(data->size()); + DCHECK_GT(data_size, 0); + int written_size = base::WriteFile( + file_path, reinterpret_cast<const char*>(data->front()), data_size); + return written_size == data_size; +} + +} // namespace ash::test
diff --git a/ash/test/ash_test_util.h b/ash/test/ash_test_util.h new file mode 100644 index 0000000..4c59f41 --- /dev/null +++ b/ash/test/ash_test_util.h
@@ -0,0 +1,25 @@ +// Copyright 2022 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_TEST_ASH_TEST_UTIL_H_ +#define ASH_TEST_ASH_TEST_UTIL_H_ + +namespace base { +class FilePath; +} + +namespace ash::test { + +// Takes a screenshot of the primary display and saves the screenshot picture to +// the location specified by `file_path`. Returns true if the screenshot is +// taken and saved successfully. Useful for debugging ash unit tests. When using +// this function on an ash unit test, the test code should be executed with +// --enable-pixel-output-in-tests flag. +// NOTE: `file_path` must end with the extension '.png'. If there is an existing +// file matching `file_path`, the existing file will be overwritten. +bool TakePrimaryDisplayScreenshotAndSave(const base::FilePath& file_path); + +} // namespace ash::test + +#endif
diff --git a/ash/wallpaper/wallpaper_view.cc b/ash/wallpaper/wallpaper_view.cc index b26e921..feabb247 100644 --- a/ash/wallpaper/wallpaper_view.cc +++ b/ash/wallpaper/wallpaper_view.cc
@@ -54,8 +54,6 @@ window->parent()->StackChildAtBottom(window); display::Display display = display::Screen::GetScreen()->GetDisplayNearestWindow(window); - display::ManagedDisplayInfo info = - Shell::Get()->display_manager()->GetDisplayInfo(display.id()); for (auto* child : children()) { child->SetBounds(0, 0, display.size().width(), display.size().height());
diff --git a/ash/webui/media_app_ui/media_app_ui.cc b/ash/webui/media_app_ui/media_app_ui.cc index 212ae7c..652ed10 100644 --- a/ash/webui/media_app_ui/media_app_ui.cc +++ b/ash/webui/media_app_ui/media_app_ui.cc
@@ -107,14 +107,24 @@ // File-type favicons. source->AddResourcePath("system_assets/pdf_icon.svg", IDR_MEDIA_APP_PDF_ICON_SVG); + source->AddResourcePath("system_assets/pdf_icon_dark.svg", + IDR_MEDIA_APP_PDF_ICON_DARK_SVG); source->AddResourcePath("system_assets/video_icon.svg", IDR_MEDIA_APP_VIDEO_ICON_SVG); + source->AddResourcePath("system_assets/video_icon_dark.svg", + IDR_MEDIA_APP_VIDEO_ICON_DARK_SVG); source->AddResourcePath("system_assets/image_icon.svg", IDR_MEDIA_APP_IMAGE_ICON_SVG); + source->AddResourcePath("system_assets/image_icon_dark.svg", + IDR_MEDIA_APP_IMAGE_ICON_DARK_SVG); source->AddResourcePath("system_assets/audio_icon.svg", IDR_MEDIA_APP_AUDIO_ICON_SVG); + source->AddResourcePath("system_assets/audio_icon_dark.svg", + IDR_MEDIA_APP_AUDIO_ICON_DARK_SVG); source->AddResourcePath("system_assets/file_icon.svg", IDR_MEDIA_APP_FILE_ICON_SVG); + source->AddResourcePath("system_assets/file_icon_dark.svg", + IDR_MEDIA_APP_FILE_ICON_DARK_SVG); return source; }
diff --git a/ash/webui/media_app_ui/resources/assets/audio_icon_dark.svg b/ash/webui/media_app_ui/resources/assets/audio_icon_dark.svg new file mode 100644 index 0000000..944bbcf6 --- /dev/null +++ b/ash/webui/media_app_ui/resources/assets/audio_icon_dark.svg
@@ -0,0 +1,3 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M16 15C16 15.55 15.55 16 15 16H14V13H16V15ZM6 16H5C4.45 16 4 15.55 4 15V13H6V16ZM2 9V15C2 16.66 3.34 18 5 18H8V11H4V9C4 5.13 6.13 4 10 4C13.87 4 16 5.13 16 9V11H12V18H15C16.66 18 18 16.66 18 15V9C18 4.03 14.97 2 10 2C5.03 2 2 4.03 2 9Z" fill="#e8eaed"/> +</svg>
diff --git a/ash/webui/media_app_ui/resources/assets/file_icon_dark.svg b/ash/webui/media_app_ui/resources/assets/file_icon_dark.svg new file mode 100644 index 0000000..2c23f14 --- /dev/null +++ b/ash/webui/media_app_ui/resources/assets/file_icon_dark.svg
@@ -0,0 +1,3 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M5 2C4.44772 2 4 2.44772 4 3V17C4 17.5523 4.44772 18 5 18H15C15.5523 18 16 17.5523 16 17V7L11 2H5ZM10 8V4H6V16H14V8H10Z" fill="#e8eaed"/> +</svg>
diff --git a/ash/webui/media_app_ui/resources/assets/image_icon_dark.svg b/ash/webui/media_app_ui/resources/assets/image_icon_dark.svg new file mode 100644 index 0000000..e01b954 --- /dev/null +++ b/ash/webui/media_app_ui/resources/assets/image_icon_dark.svg
@@ -0,0 +1,3 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3H5C3.9 3 3 3.9 3 5V15C3 16.1 3.9 17 5 17H15C16.1 17 17 16.1 17 15V5C17 3.9 16.1 3 15 3ZM15 15H5V5H15V15ZM11.3333 9L9.5 12L8 10.6L6 14H14L11.3333 9Z" fill="#e8eaed"/> +</svg>
diff --git a/ash/webui/media_app_ui/resources/assets/pdf_icon_dark.svg b/ash/webui/media_app_ui/resources/assets/pdf_icon_dark.svg new file mode 100644 index 0000000..853adaf --- /dev/null +++ b/ash/webui/media_app_ui/resources/assets/pdf_icon_dark.svg
@@ -0,0 +1,6 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M6 8.5C6 8.48274 6.00087 8.46569 6.00258 8.44888C6.02819 8.19675 6.24112 8 6.5 8H7.9C8.17614 8 8.4 8.22386 8.4 8.5V9.9C8.4 10.1761 8.17614 10.4 7.9 10.4H6.8V12H6V8.5ZM6.8 8.80005V9.60005H7.59999V8.80005H6.8Z" fill="#e8eaed"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M9.29999 8C9.02385 8 8.79999 8.22386 8.79999 8.5V12H10.7C10.9761 12 11.2 11.7761 11.2 11.5V8.5C11.2 8.22386 10.9761 8 10.7 8H9.29999ZM10.4 8.80005H9.59998V11.2H10.4V8.80005Z" fill="#e8eaed"/> +<path d="M11.6 8.4C11.6 8.17909 11.7791 8 12 8H14V8.8H12.4V9.59998H13.2V10.4H12.4V12H11.6L11.6 8.4Z" fill="#e8eaed"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3H5C3.9 3 3 3.9 3 5V15C3 16.1 3.9 17 5 17H15C16.1 17 17 16.1 17 15V5C17 3.9 16.1 3 15 3ZM15 15H5V5H15V15Z" fill="#e8eaed"/> +</svg>
diff --git a/ash/webui/media_app_ui/resources/assets/video_icon_dark.svg b/ash/webui/media_app_ui/resources/assets/video_icon_dark.svg new file mode 100644 index 0000000..b3fb465 --- /dev/null +++ b/ash/webui/media_app_ui/resources/assets/video_icon_dark.svg
@@ -0,0 +1,3 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M16 4H14L15 7H13L12 4H10L11 7H9L8 4H6L7 7H5L4 4C3 4 2 5.007 2 6V15C2 16 2.9 17 4 17H16C17.1 17.048 18 16.125 18 15V6C18 5.007 17 4 16 4ZM16 15H4V9H16V15Z" fill="#e8eaed"/> +</svg>
diff --git a/ash/webui/media_app_ui/resources/js/launch.js b/ash/webui/media_app_ui/resources/js/launch.js index cd3d9460..0e65514d 100644 --- a/ash/webui/media_app_ui/resources/js/launch.js +++ b/ash/webui/media_app_ui/resources/js/launch.js
@@ -13,6 +13,7 @@ import {DeleteFileMessage, FileContext, IsFileBrowserWritableMessage, LoadFilesMessage, Message, NavigateMessage, NotifyCurrentFileMessage, OpenAllowedFileMessage, OpenAllowedFileResponse, OpenFilesWithPickerMessage, OverwriteFileMessage, OverwriteViaFilePickerResponse, RenameFileMessage, RenameResult, RequestSaveFileMessage, RequestSaveFileResponse, SaveAsMessage, SaveAsResponse} from './message_types.js'; import {mediaAppPageHandler} from './mojo_api_bootstrap.js'; +const DEFAULT_APP_ICON = 'app'; const EMPTY_WRITE_ERROR_NAME = 'EmptyWriteError'; // Open file picker configurations. Should be kept in sync with launch handler @@ -164,6 +165,29 @@ // event listener before the <iframe> is added to the DOM. guestMessagePipe.registerHandler(Message.IFRAME_READY, () => {}); +/** + * The type of icon to show for this app's window. + * @type {string} + */ +let appIconType = DEFAULT_APP_ICON; + +/** + * Sets the app icon depending on the icon type and color theme. + * @param {!MediaQueryList|!Event<!{matches: boolean}>} + * mediaQueryList Determines whether or not the icon should be in dark mode. + */ +function updateAppIcon(mediaQueryList) { + // The default app icon does not have a separate dark variant. + const isDark = + mediaQueryList.matches && appIconType !== DEFAULT_APP_ICON ? '_dark' : ''; + + const icon = /** @type {!HTMLLinkElement} */ ( + document.querySelector('link[rel=icon]')); + icon.href = `system_assets/${appIconType}_icon${isDark}.svg`; +} + +const darkMediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + guestMessagePipe.registerHandler(Message.NOTIFY_CURRENT_FILE, message => { const notifyMsg = /** @type {!NotifyCurrentFileMessage} */ (message); @@ -172,19 +196,19 @@ appTitle = appTitle || title.text; title.text = notifyMsg.name || appTitle; - let genericType = notifyMsg.type ? notifyMsg.type.split('/')[0] : 'file'; + appIconType = notifyMsg.type ? notifyMsg.type.split('/')[0] : 'file'; if (title.text === appTitle) { - genericType = 'app'; + appIconType = DEFAULT_APP_ICON; } else if (notifyMsg.type === 'application/pdf') { - genericType = 'pdf'; - } else if (!['audio', 'image', 'video', 'file'].includes(genericType)) { - genericType = 'file'; + appIconType = 'pdf'; + } else if (!['audio', 'image', 'video', 'file'].includes(appIconType)) { + appIconType = 'file'; } - const icon = /** @type {!HTMLLinkElement} */ ( - document.querySelector('link[rel=icon]')); - icon.href = `system_assets/${genericType}_icon.svg`; + updateAppIcon(darkMediaQuery); }); +darkMediaQuery.addEventListener('change', updateAppIcon); + guestMessagePipe.registerHandler(Message.OPEN_FEEDBACK_DIALOG, () => { let response = mediaAppPageHandler.openFeedbackDialog(); if (response === null) {
diff --git a/ash/webui/media_app_ui/resources/media_app_resources.grd b/ash/webui/media_app_ui/resources/media_app_resources.grd index 7b6147a..a14082b 100644 --- a/ash/webui/media_app_ui/resources/media_app_resources.grd +++ b/ash/webui/media_app_ui/resources/media_app_resources.grd
@@ -17,10 +17,15 @@ <include name="IDR_MEDIA_APP_VIEWPDFHOST_JS" file="js/viewpdfhost.js" type="BINDATA" /> <include name="IDR_MEDIA_APP_APP_ICON_SVG" file="assets/app_icon.svg" type="BINDATA" /> <include name="IDR_MEDIA_APP_IMAGE_ICON_SVG" file="assets/image_icon.svg" type="BINDATA" /> + <include name="IDR_MEDIA_APP_IMAGE_ICON_DARK_SVG" file="assets/image_icon_dark.svg" type="BINDATA" /> <include name="IDR_MEDIA_APP_AUDIO_ICON_SVG" file="assets/audio_icon.svg" type="BINDATA" /> + <include name="IDR_MEDIA_APP_AUDIO_ICON_DARK_SVG" file="assets/audio_icon_dark.svg" type="BINDATA" /> <include name="IDR_MEDIA_APP_VIDEO_ICON_SVG" file="assets/video_icon.svg" type="BINDATA" /> + <include name="IDR_MEDIA_APP_VIDEO_ICON_DARK_SVG" file="assets/video_icon_dark.svg" type="BINDATA" /> <include name="IDR_MEDIA_APP_PDF_ICON_SVG" file="assets/pdf_icon.svg" type="BINDATA" /> + <include name="IDR_MEDIA_APP_PDF_ICON_DARK_SVG" file="assets/pdf_icon_dark.svg" type="BINDATA" /> <include name="IDR_MEDIA_APP_FILE_ICON_SVG" file="assets/file_icon.svg" type="BINDATA" /> + <include name="IDR_MEDIA_APP_FILE_ICON_DARK_SVG" file="assets/file_icon_dark.svg" type="BINDATA" /> <!-- TODO(b/141588875): Switch these to IDR_MEDIA_APP_APP_ICON_*_PNG in the internal media_app_bundle_resources.grd file (and add more icon resolutions) when the final icon is ready. --> <include name="IDR_MEDIA_APP_GALLERY_ICON_16_PNG" file="assets/icon16.png" type="BINDATA" />
diff --git a/ash/webui/media_app_ui/test/dom_testing_helpers.js b/ash/webui/media_app_ui/test/dom_testing_helpers.js index 3d20965..c88f42a4 100644 --- a/ash/webui/media_app_ui/test/dom_testing_helpers.js +++ b/ash/webui/media_app_ui/test/dom_testing_helpers.js
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +/* eslint no-var: "off" */ + /** * @fileoverview Helpers for testing against DOM. For integration tests, this is * injected into an isolated world, so can't access objects in other scripts. @@ -17,7 +19,7 @@ * @param {!Array<string>=} shadowRootPath * @returns {!Promise<!HTMLElement|!ShadowRoot>} */ -async function getNextRoot(selectorMethod, shadowRootPath = []) { +var getNextRoot = async (selectorMethod, shadowRootPath = []) => { /** @type {!HTMLElement|!ShadowRoot} */ let parentNode = document.body; const parentQuery = shadowRootPath.shift(); @@ -29,7 +31,7 @@ parentNode = element.shadowRoot; } return parentNode; -} +}; /** * Runs a query selector once. Returns the Element if it's found, otherwise @@ -39,14 +41,14 @@ * @param {!Array<string>=} path * @return {!Promise<!Element|undefined>} */ -async function getNode(query, path = []) { +var getNode = async (query, path = []) => { const parentElement = await getNextRoot(getNode, path); const existingElement = parentElement.querySelector(query); if (existingElement) { return Promise.resolve(existingElement); } return Promise.resolve(undefined); -} +}; /** * Runs a query selector until it finds an element (repeated on each mutation). @@ -62,7 +64,7 @@ * @param {!Array<string>=} opt_path * @return {!Promise<!Element>} */ -async function waitForNode(query, opt_path) { +var waitForNode = async (query, opt_path) => { const parentElement = await getNextRoot(waitForNode, opt_path); const existingElement = parentElement.querySelector(query); if (existingElement) { @@ -80,7 +82,7 @@ observer.observe( parentElement, {attributes: true, childList: true, subtree: true}); }); -} +}; /** * Returns a promise that resolves when the passed node's child list is updated @@ -88,7 +90,7 @@ * @param {!Node} node * @return {!Promise} */ -function childListUpdate(node) { +var childListUpdate = (node) => { return new Promise(resolve => { const observer = new MutationObserver(() => { resolve(); @@ -96,4 +98,4 @@ }); observer.observe(node, {childList: true}); }); -} +};
diff --git a/ash/webui/media_app_ui/test/media_app_ui_browsertest.js b/ash/webui/media_app_ui/test/media_app_ui_browsertest.js index e7f462f..35b6e4d4 100644 --- a/ash/webui/media_app_ui/test/media_app_ui_browsertest.js +++ b/ash/webui/media_app_ui/test/media_app_ui_browsertest.js
@@ -409,9 +409,47 @@ assertEquals(getTitle().innerText, expectedTitle); assertEquals(getIcon().href.includes(expectedIconType), true); + assertEquals(getIcon().href.includes('dark'), false); } }; +// Test that each file type has a corresponding dark icon. +MediaAppUIBrowserTest.NotifyCurrentFileDark = async () => { + const imageFile = new File([], 'image.png', {type: 'image/png'}); + const audioFile = new File([], 'audio.wav', {type: 'audio/wav'}); + const videoFile = new File([], 'video.mp4', {type: 'video/mp4'}); + const pdfFile = new File([], 'form.pdf', {type: 'application/pdf'}); + const unknownFile = new File([], 'foo.xyz', {type: 'unknown/unknown'}); + + const TEST_CASES = [ + {file: imageFile, expectedIconType: 'image'}, + {file: audioFile, expectedIconType: 'audio'}, + {file: videoFile, expectedIconType: 'video'}, + {file: unknownFile, expectedIconType: 'file'}, + {file: pdfFile, expectedIconType: 'pdf'}, + ]; + for (const {file, expectedIconType} of TEST_CASES) { + const name = file ? file.name : undefined; + const type = file ? file.type : undefined; + await sendTestMessage( + {simple: 'notifyCurrentFile', simpleArgs: {name, type}}); + + assertEquals(getIcon().href.includes(expectedIconType), true); + assertEquals(getIcon().href.includes('dark'), true); + } +}; + +// Test that the Gallery app icon does not have a dark variant. +MediaAppUIBrowserTest.NotifyCurrentFileAppIconDark = async () => { + await sendTestMessage({ + simple: 'notifyCurrentFile', + simpleArgs: {name: undefined, type: undefined} + }); + + assertEquals(getIcon().href.includes('app'), true); + assertEquals(getIcon().href.includes('dark'), false); +}; + // Tests that we show error UX when trying to launch an unopenable file. MediaAppUIBrowserTest.LaunchUnopenableFile = async () => { const mockFileHandle =
diff --git a/ash/webui/media_app_ui/test/media_app_ui_gtest_browsertest.js b/ash/webui/media_app_ui/test/media_app_ui_gtest_browsertest.js index 7ec12c9..36857683 100644 --- a/ash/webui/media_app_ui/test/media_app_ui_gtest_browsertest.js +++ b/ash/webui/media_app_ui/test/media_app_ui_gtest_browsertest.js
@@ -67,6 +67,29 @@ // js2gtest fixtures require var here (https://crbug.com/1033337). // eslint-disable-next-line no-var +var MediaAppUIWithDarkLightModeDarkGtestBrowserTest = + class extends MediaAppUIGtestBrowserTest { + /** @override */ + get featureList() { + return { + enabled: [ + ...super.featureList.enabled, + 'chromeos::features::kDarkLightMode', + ] + }; + } + + /** @override */ + get testGenPreamble() { + return () => { + // Switch to dark mode. + GEN('ash::ColorProvider::Get()->SetDarkModeEnabledForTest(true);'); + }; + } +}; + +// js2gtest fixtures require var here (https://crbug.com/1033337). +// eslint-disable-next-line no-var var MediaAppUIWithoutDarkLightModeGtestBrowserTest = class extends MediaAppUIGtestBrowserTest { /** @override */ @@ -132,6 +155,9 @@ MediaAppUIWithDarkLightModeGtestBrowserTest)) .testCaseBodies, ...(/** @type {{testCaseBodies: Object}} */ ( + MediaAppUIWithDarkLightModeDarkGtestBrowserTest)) + .testCaseBodies, + ...(/** @type {{testCaseBodies: Object}} */ ( MediaAppUIWithoutDarkLightModeGtestBrowserTest)) .testCaseBodies, }; @@ -186,6 +212,18 @@ runMediaAppTest('NotifyCurrentFile'); }); +TEST_F( + 'MediaAppUIWithDarkLightModeDarkGtestBrowserTest', 'NotifyCurrentFileDark', + () => { + runMediaAppTest('NotifyCurrentFileDark'); + }); + +TEST_F( + 'MediaAppUIWithDarkLightModeDarkGtestBrowserTest', + 'NotifyCurrentFileAppIconDark', () => { + runMediaAppTest('NotifyCurrentFileAppIconDark'); + }); + TEST_F('MediaAppUIGtestBrowserTest', 'LaunchUnopenableFile', () => { runMediaAppTest('LaunchUnopenableFile'); });
diff --git a/ash/webui/personalization_app/personalization_app_ui.cc b/ash/webui/personalization_app/personalization_app_ui.cc index 63b45418..0e48749 100644 --- a/ash/webui/personalization_app/personalization_app_ui.cc +++ b/ash/webui/personalization_app/personalization_app_ui.cc
@@ -112,6 +112,8 @@ {"avatarLabel", IDS_PERSONALIZATION_APP_AVATAR_LABEL}, {"takeWebcamPhoto", IDS_PERSONALIZATION_APP_AVATAR_TAKE_PHOTO}, {"takeWebcamVideo", IDS_PERSONALIZATION_APP_AVATAR_TAKE_VIDEO}, + {"webcamCaptureInProgress", + IDS_PERSONALIZATION_APP_AVATAR_CAPTURE_IN_PROGRESS}, {"confirmWebcamPhoto", IDS_PERSONALIZATION_APP_AVATAR_CONFIRM_PHOTO}, {"confirmWebcamVideo", IDS_PERSONALIZATION_APP_AVATAR_CONFIRM_VIDEO}, {"rejectWebcamPhoto", IDS_PERSONALIZATION_APP_AVATAR_REJECT_PHOTO},
diff --git a/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.html b/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.html index bb0cd240..1a9eeb55 100644 --- a/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.html +++ b/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.html
@@ -52,7 +52,7 @@ padding: 6px 16px; } - paper-spinner-lite { + #cameraFeedSpinner { bottom: 50%; left: 50%; position: absolute; @@ -79,11 +79,23 @@ gap: 8px; justify-content: center; } + + #loadingButton { + /* This button is disabled for aria purposes but should look like a regular + primary button. */ + --disabled-text-color: var(--cros-button-label-color-primary); + } + + #loadingButtonSpinner { + --paper-spinner-color: var(--cros-button-label-color-primary); + height: 14px; + width: 14px; + } </style> <cr-dialog id="dialog" show-close-button show-on-attach> <div slot="body"> <template is="dom-if" if="[[showLoading_(cameraStream_, previewBlobUrl_)]]"> - <paper-spinner-lite active></paper-spinner-lite> + <paper-spinner-lite id="cameraFeedSpinner" active></paper-spinner-lite> </template> <template is="dom-if" if="[[showSvgMask_(cameraStream_, previewBlobUrl_)]]"> <svg viewbox="0 0 100 100" id="svg" hidden=""> @@ -108,12 +120,18 @@ <template is="dom-if" if="[[showFooter_(cameraStream_, previewBlobUrl_)]]"> <div slot="footer"> <template is="dom-if" - if="[[showCameraFeed_(cameraStream_, previewBlobUrl_)]]"> + if="[[showTakePhotoButton_(cameraStream_, previewBlobUrl_, captureInProgress_)]]"> <cr-button id="takePhoto" on-click="takePhoto_" class="primary"> <iron-icon icon="[[getTakePhotoIcon_(mode)]]"></iron-icon> <span>[[getTakePhotoText_(mode)]]</span> </cr-button> </template> + <template is="dom-if" if="[[showLoadingSpinnerButton_(mode, cameraStream_, previewBlobUrl_, captureInProgress_)]]"> + <cr-button id="loadingButton" class="primary" disabled> + <paper-spinner-lite id="loadingButtonSpinner" active></paper-spinner-lite> + <span>$i18n{webcamCaptureInProgress}</span> + </cr-button> + </template> <template is="dom-if" if="[[previewBlobUrl_]]"> <cr-button id="confirmPhoto" on-click="confirmPhoto_" class="primary"> <iron-icon icon="personalization:circle_checkmark"></iron-icon>
diff --git a/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.ts b/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.ts index 0f4a49f..d9706154 100644 --- a/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.ts +++ b/ash/webui/personalization_app/resources/trusted/user/avatar_camera_element.ts
@@ -219,6 +219,15 @@ return !!this.cameraStream_ && !this.previewBlobUrl_; } + private showTakePhotoButton_(): boolean { + return this.showCameraFeed_() && !this.captureInProgress_; + } + + private showLoadingSpinnerButton_(): boolean { + return this.mode === AvatarCameraMode.VIDEO && this.showCameraFeed_() && + this.captureInProgress_; + } + private showFooter_(): boolean { return this.showCameraFeed_() || !!this.previewBlobUrl_; }
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service.cc b/ash/webui/shimless_rma/backend/shimless_rma_service.cc index 01ef3da..d20da8c7 100644 --- a/ash/webui/shimless_rma/backend/shimless_rma_service.cc +++ b/ash/webui/shimless_rma/backend/shimless_rma_service.cc
@@ -17,6 +17,7 @@ #include "base/bind.h" #include "base/check_op.h" #include "base/containers/contains.h" +#include "base/files/file_path.h" #include "base/logging.h" #include "chromeos/ash/components/dbus/rmad/rmad.pb.h" #include "chromeos/ash/components/dbus/rmad/rmad_client.h" @@ -932,6 +933,19 @@ std::move(callback))); } +void ShimlessRmaService::SaveLog(SaveLogCallback callback) { + if (state_proto_.state_case() != rmad::RmadState::kRepairComplete) { + LOG(ERROR) << "SaveLog called from incorrect state " + << state_proto_.state_case(); + std::move(callback).Run(base::FilePath(""), + rmad::RmadErrorCode::RMAD_ERROR_REQUEST_INVALID); + return; + } + RmadClient::Get()->SaveLog(base::BindOnce(&ShimlessRmaService::OnSaveLog, + weak_ptr_factory_.GetWeakPtr(), + std::move(callback))); +} + void ShimlessRmaService::OnGetLog(GetLogCallback callback, absl::optional<rmad::GetLogReply> response) { if (!response) { @@ -944,6 +958,20 @@ std::move(callback).Run(response->log(), response->error()); } +void ShimlessRmaService::OnSaveLog( + SaveLogCallback callback, + absl::optional<rmad::SaveLogReply> response) { + if (!response) { + LOG(ERROR) << "Failed to call rmad::SaveLog"; + std::move(callback).Run(base::FilePath(""), + rmad::RmadErrorCode::RMAD_ERROR_REQUEST_INVALID); + return; + } + + std::move(callback).Run(base::FilePath(response->save_path()), + response->error()); +} + void ShimlessRmaService::GetPowerwashRequired( GetPowerwashRequiredCallback callback) { if (state_proto_.state_case() != rmad::RmadState::kRepairComplete) {
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service.h b/ash/webui/shimless_rma/backend/shimless_rma_service.h index 875ce32..e945ebe 100644 --- a/ash/webui/shimless_rma/backend/shimless_rma_service.h +++ b/ash/webui/shimless_rma/backend/shimless_rma_service.h
@@ -134,6 +134,7 @@ WriteProtectManuallyEnabledCallback callback) override; void GetLog(GetLogCallback callback) override; + void SaveLog(SaveLogCallback callback) override; void GetPowerwashRequired(GetPowerwashRequiredCallback callback) override; void LaunchDiagnostics() override; void EndRma(rmad::RepairCompleteState::ShutdownMethod shutdown_method, @@ -206,6 +207,8 @@ EndRmaCallback callback); void OnGetLog(GetLogCallback callback, absl::optional<rmad::GetLogReply> response); + void OnSaveLog(SaveLogCallback callback, + absl::optional<rmad::SaveLogReply> response); void OnOsUpdateStatusCallback(update_engine::Operation operation, double progress,
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc b/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc index fdae9594..71be12e 100644 --- a/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc +++ b/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc
@@ -13,6 +13,7 @@ #include "ash/webui/shimless_rma/backend/shimless_rma_delegate.h" #include "ash/webui/shimless_rma/mojom/shimless_rma.mojom.h" #include "base/callback_helpers.h" +#include "base/files/file_path.h" #include "base/strings/stringprintf.h" #include "base/test/bind.h" #include "base/test/task_environment.h" @@ -2785,6 +2786,54 @@ run_loop.RunUntilIdle(); } +TEST_F(ShimlessRmaServiceTest, SaveLog) { + const std::vector<rmad::GetStateReply> fake_states = { + CreateStateReply(rmad::RmadState::kRepairComplete, rmad::RMAD_ERROR_OK)}; + fake_rmad_client_()->SetFakeStateReplies(std::move(fake_states)); + const std::unique_ptr<base::FilePath> expected_save_path = + std::make_unique<base::FilePath>( + FILE_PATH_LITERAL("log/save/path/for/testing")); + + fake_rmad_client_()->SetSaveLogReply(expected_save_path->value(), + rmad::RMAD_ERROR_OK); + base::RunLoop run_loop; + shimless_rma_provider_->GetCurrentState(base::BindLambdaForTesting( + [&](mojom::State state, bool can_cancel, bool can_go_back, + rmad::RmadErrorCode error) { + EXPECT_EQ(state, mojom::State::kRepairComplete); + EXPECT_EQ(error, rmad::RmadErrorCode::RMAD_ERROR_OK); + })); + run_loop.RunUntilIdle(); + + shimless_rma_provider_->SaveLog(base::BindLambdaForTesting( + [&](const base::FilePath& save_path, rmad::RmadErrorCode error) { + EXPECT_EQ(save_path, *expected_save_path.get()); + EXPECT_EQ(error, rmad::RmadErrorCode::RMAD_ERROR_OK); + })); + run_loop.RunUntilIdle(); +} + +TEST_F(ShimlessRmaServiceTest, SaveLogWrongStateEmpty) { + const std::vector<rmad::GetStateReply> fake_states = {CreateStateReply( + rmad::RmadState::kDeviceDestination, rmad::RMAD_ERROR_OK)}; + fake_rmad_client_()->SetFakeStateReplies(std::move(fake_states)); + base::RunLoop run_loop; + shimless_rma_provider_->GetCurrentState(base::BindLambdaForTesting( + [&](mojom::State state, bool can_cancel, bool can_go_back, + rmad::RmadErrorCode error) { + EXPECT_EQ(state, mojom::State::kChooseDestination); + EXPECT_EQ(error, rmad::RmadErrorCode::RMAD_ERROR_OK); + })); + run_loop.RunUntilIdle(); + + shimless_rma_provider_->SaveLog(base::BindLambdaForTesting( + [&](const base::FilePath& save_path, rmad::RmadErrorCode error) { + EXPECT_TRUE(save_path.empty()); + EXPECT_EQ(error, rmad::RmadErrorCode::RMAD_ERROR_REQUEST_INVALID); + })); + run_loop.RunUntilIdle(); +} + TEST_F(ShimlessRmaServiceTest, GetPowerwashRequired) { rmad::GetStateReply repair_complete_state = CreateStateReply(rmad::RmadState::kRepairComplete, rmad::RMAD_ERROR_OK);
diff --git a/ash/webui/shimless_rma/mojom/shimless_rma.mojom b/ash/webui/shimless_rma/mojom/shimless_rma.mojom index 8232bf9..e31bcbce 100644 --- a/ash/webui/shimless_rma/mojom/shimless_rma.mojom +++ b/ash/webui/shimless_rma/mojom/shimless_rma.mojom
@@ -36,6 +36,7 @@ module ash.shimless_rma.mojom; +import "mojo/public/mojom/base/file_path.mojom"; import "mojo/public/mojom/base/string16.mojom"; // RMA states. @@ -754,6 +755,9 @@ // Get the RMA Log. // Returns an error indicating success or a failure. GetLog() => (string log, RmadErrorCode error); + // Save the RMA Log to the USB drive. + // Returns an error indicating success or a failure. + SaveLog() => (mojo_base.mojom.FilePath save_path, RmadErrorCode error); // Get whether need to powerwash at the end of repair. GetPowerwashRequired() => (bool powerwash_required); // Launch the system diagnostics app.
diff --git a/ash/webui/shimless_rma/resources/BUILD.gn b/ash/webui/shimless_rma/resources/BUILD.gn index b873d80..8bcb68a 100644 --- a/ash/webui/shimless_rma/resources/BUILD.gn +++ b/ash/webui/shimless_rma/resources/BUILD.gn
@@ -14,6 +14,7 @@ preprocessed_dir = "preprocessed" preprocessed_gen_manifest = "preprocessed_gen_manifest.json" preprocessed_mojo_manifest = "preprocessed_mojo_manifest.json" +preprocess_external_mojo_manifest = "preprocessed_external_mojo_manifest.json" polymer_element_files = [ "base_page.js", @@ -68,12 +69,17 @@ ] input_files_base_dir = rebase_path(".", "//") deps = [ + ":preprocess_external_mojo", ":preprocess_generated", ":preprocess_mojo", ] manifest_files = [ "$target_gen_dir/$preprocessed_gen_manifest", "$target_gen_dir/$preprocessed_mojo_manifest", + "$target_gen_dir/$preprocess_external_mojo_manifest", + ] + resource_path_rewrites = [ + "mojo/public/mojom/base/file_path.mojom-lite.js|file_path.mojom-lite.js", ] grd_prefix = "ash_shimless_rma" out_grd = "$target_gen_dir/${grd_prefix}_resources.grd" @@ -476,6 +482,14 @@ in_files = [ "mojom/shimless_rma.mojom-lite.js" ] } +preprocess_if_expr("preprocess_external_mojo") { + deps = [ "//mojo/public/mojom/base:base_js__generator" ] + in_folder = "$root_gen_dir" + out_folder = "$target_gen_dir/preprocessed_external_mojo" + out_manifest = "$target_gen_dir/$preprocess_external_mojo_manifest" + in_files = [ "mojo/public/mojom/base/file_path.mojom-lite.js" ] +} + html_to_js("web_components") { js_files = polymer_element_files }
diff --git a/ash/webui/shimless_rma/resources/fake_data.js b/ash/webui/shimless_rma/resources/fake_data.js index 343ffd2..bc5fef5 100644 --- a/ash/webui/shimless_rma/resources/fake_data.js +++ b/ash/webui/shimless_rma/resources/fake_data.js
@@ -445,3 +445,6 @@ 'tristique risus nec. Scelerisque eu ultrices vitae auctor eu augue ut ' + 'lectus. Tellus pellentesque eu tincidunt tortor aliquam. Fermentum leo ' + 'vel orci porta non pulvinar neque laoreet suspendisse.\n'; + +/** @type {string} */ +export const fakeLogSavePath = 'fake/save/path';
diff --git a/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js b/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js index 634eee25..32b9d96 100644 --- a/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js +++ b/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import '/file_path.mojom-lite.js'; + import {FakeMethodResolver} from 'chrome://resources/ash/common/fake_method_resolver.js'; import {FakeObservables} from 'chrome://resources/ash/common/fake_observables.js'; import {assert} from 'chrome://resources/js/assert.m.js'; @@ -720,6 +722,20 @@ this.methods_.setResult('getLog', {log: log, error: RmadErrorCode.kOk}); } + /** + * @return {!Promise<{savePath: !mojoBase.mojom.FilePath, error: + * !RmadErrorCode}>} + */ + saveLog() { + return this.methods_.resolveMethod('saveLog'); + } + + /** @param {!mojoBase.mojom.FilePath} savePath */ + setSaveLogResult(savePath) { + this.methods_.setResult( + 'saveLog', {savePath: savePath, error: RmadErrorCode.kOk}); + } + /** @return {!Promise<{powerwashRequired: boolean, error: !RmadErrorCode}>} */ getPowerwashRequired() { return this.methods_.resolveMethod('getPowerwashRequired'); @@ -1211,6 +1227,7 @@ // undefined by default. this.components_ = []; this.setGetLogResult(''); + this.setSaveLogResult({'path': ''}); } /** @@ -1292,6 +1309,7 @@ this.methods_.register('writeProtectManuallyEnabled'); this.methods_.register('getLog'); + this.methods_.register('saveLog'); this.methods_.register('getPowerwashRequired'); this.methods_.register('endRma');
diff --git a/ash/webui/shimless_rma/resources/mojo_interface_provider.js b/ash/webui/shimless_rma/resources/mojo_interface_provider.js index 0a2aa9b..916a08c0 100644 --- a/ash/webui/shimless_rma/resources/mojo_interface_provider.js +++ b/ash/webui/shimless_rma/resources/mojo_interface_provider.js
@@ -4,7 +4,7 @@ import {assert} from 'chrome://resources/js/assert.m.js'; -import {fakeCalibrationComponentsWithFails, fakeChromeVersion, fakeComponents, fakeDeviceRegions, fakeDeviceSkus, fakeDeviceWhiteLabels, fakeLog, fakeRsuChallengeCode, fakeRsuChallengeQrCode, fakeStates} from './fake_data.js'; +import {fakeCalibrationComponentsWithFails, fakeChromeVersion, fakeComponents, fakeDeviceRegions, fakeDeviceSkus, fakeDeviceWhiteLabels, fakeLog, fakeLogSavePath, fakeRsuChallengeCode, fakeRsuChallengeQrCode, fakeStates} from './fake_data.js'; import {FakeShimlessRmaService} from './fake_shimless_rma_service.js'; import {CalibrationSetupInstruction, NetworkConfigServiceInterface, RmadErrorCode, ShimlessRmaService, ShimlessRmaServiceInterface, WriteProtectDisableCompleteAction} from './shimless_rma_types.js'; @@ -86,6 +86,7 @@ service.automaticallyTriggerPowerCableStateObservation(); service.setGetLogResult(fakeLog); + service.setSaveLogResult({'path': fakeLogSavePath}); service.setGetPowerwashRequiredResult(true); // Set the fake service.
diff --git a/ash/webui/shimless_rma/resources/shimless_rma_types.js b/ash/webui/shimless_rma/resources/shimless_rma_types.js index ae3cfb0..e4b0c142 100644 --- a/ash/webui/shimless_rma/resources/shimless_rma_types.js +++ b/ash/webui/shimless_rma/resources/shimless_rma_types.js
@@ -7,12 +7,14 @@ * Type aliases for the mojo API. */ -import {OncMojo} from 'chrome://resources/cr_components/chromeos/network/onc_mojo.m.js'; import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; import 'chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js'; import 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-lite.js'; +import './file_path.mojom-lite.js'; import './mojom/shimless_rma.mojom-lite.js'; +import {OncMojo} from 'chrome://resources/cr_components/chromeos/network/onc_mojo.m.js'; + /** * Return type from state progression methods. * Convenience type as mojo-lite does not define types for method results and
diff --git a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html index 30e3be2..658fd952 100644 --- a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html +++ b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html
@@ -227,7 +227,8 @@ <cr-button id="closeLogDialogButton" on-click="onCancelClick_"> [[i18n('rmaLogsCancelButtonText')]] </cr-button> - <cr-button id="saveLogDialogButton" class="text-button action-button"> + <cr-button id="saveLogDialogButton" class="text-button action-button" + on-click="onSaveLogClick_"> [[i18n('rmaLogsSaveToUsbButtonText')]] </cr-button> </div>
diff --git a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js index 1743c34..b68576ff 100644 --- a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js +++ b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js
@@ -268,6 +268,11 @@ } /** @protected */ + onSaveLogClick_() { + this.shimlessRmaService_.saveLog(); + } + + /** @protected */ onCutoffCancelClick_() { this.cancelBatteryCutoff_(); }
diff --git a/base/BUILD.gn b/base/BUILD.gn index be46e9c6..caae724 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -1019,11 +1019,11 @@ if (is_win) { sources += [ - "debug/close_handle_hook_win.cc", - "debug/close_handle_hook_win.h", "debug/debugger_win.cc", "debug/gdi_debug_util_win.cc", "debug/gdi_debug_util_win.h", + "debug/handle_hooks_win.cc", + "debug/handle_hooks_win.h", "debug/invalid_access_win.cc", "debug/invalid_access_win.h", "debug/stack_trace_win.cc",
diff --git a/base/allocator/partition_allocator/partition_address_space.cc b/base/allocator/partition_allocator/partition_address_space.cc index f4b7965..f42cffc 100644 --- a/base/allocator/partition_allocator/partition_address_space.cc +++ b/base/allocator/partition_allocator/partition_address_space.cc
@@ -7,6 +7,7 @@ #include <array> #include <cstdint> #include <ostream> +#include <string> #include "base/allocator/partition_allocator/address_pool_manager.h" #include "base/allocator/partition_allocator/page_allocator.h" @@ -19,6 +20,10 @@ #include "base/compiler_specific.h" #include "build/build_config.h" +#if BUILDFLAG(IS_IOS) +#include <mach-o/dyld.h> +#endif + #if BUILDFLAG(IS_WIN) #include <windows.h> #endif @@ -70,60 +75,105 @@ PartitionAddressSpace::GigaCageSetup PartitionAddressSpace::setup_; #if defined(PA_USE_DYNAMICALLY_SIZED_GIGA_CAGE) +#if BUILDFLAG(IS_IOS) +namespace { +bool IsIOSTestProcess() { + // On iOS, only applications with the extended virtual addressing entitlement + // can use a large address space. Since Earl Grey test runner apps cannot get + // entitlements, they must use a much smaller pool size. + uint32_t executable_length = 0; + _NSGetExecutablePath(NULL, &executable_length); + PA_DCHECK(executable_length > 0); + + // 'new' cannot be used here, since this function is called during + // PartitionAddressSpace initialization, at which point 'new' interception + // is already active. 'malloc' is safe to use, since on Apple platforms, + // InitializeDefaultAllocatorPartitionRoot() is called before 'malloc' + // interception is set up. + char* executable_path = (char*)malloc(executable_length); + int rv = _NSGetExecutablePath(executable_path, &executable_length); + PA_DCHECK(!rv); + size_t executable_path_length = + std::char_traits<char>::length(executable_path); + + const char kTestProcessSuffix[] = "Runner"; + size_t test_process_suffix_length = + std::char_traits<char>::length(kTestProcessSuffix); + + if (executable_path_length < test_process_suffix_length) + return false; + + return !std::char_traits<char>::compare( + executable_path + (executable_path_length - test_process_suffix_length), + kTestProcessSuffix, test_process_suffix_length); +} +} // namespace + +ALWAYS_INLINE size_t PartitionAddressSpace::RegularPoolSize() { + return IsIOSTestProcess() ? kRegularPoolSizeForIOSTestProcess + : kRegularPoolSize; +} +ALWAYS_INLINE size_t PartitionAddressSpace::BRPPoolSize() { + return IsIOSTestProcess() ? kBRPPoolSizeForIOSTestProcess : kBRPPoolSize; +} +#else ALWAYS_INLINE size_t PartitionAddressSpace::RegularPoolSize() { return kRegularPoolSize; } ALWAYS_INLINE size_t PartitionAddressSpace::BRPPoolSize() { return kBRPPoolSize; } +#endif // BUILDFLAG(IS_IOS) #endif // defined(PA_USE_DYNAMICALLY_SIZED_GIGA_CAGE) void PartitionAddressSpace::Init() { if (IsInitialized()) return; + size_t regular_pool_size = RegularPoolSize(); setup_.regular_pool_base_address_ = AllocPages( - RegularPoolSize(), RegularPoolSize(), + regular_pool_size, regular_pool_size, PageAccessibilityConfiguration::kInaccessible, PageTag::kPartitionAlloc); if (!setup_.regular_pool_base_address_) HandleGigaCageAllocFailure(); #if defined(PA_USE_DYNAMICALLY_SIZED_GIGA_CAGE) - setup_.regular_pool_base_mask_ = ~(RegularPoolSize() - 1) & kMemTagUnmask; + setup_.regular_pool_base_mask_ = ~(regular_pool_size - 1) & kMemTagUnmask; #endif - PA_DCHECK(!(setup_.regular_pool_base_address_ & (RegularPoolSize() - 1))); + PA_DCHECK(!(setup_.regular_pool_base_address_ & (regular_pool_size - 1))); setup_.regular_pool_ = AddressPoolManager::GetInstance().Add( - setup_.regular_pool_base_address_, RegularPoolSize()); + setup_.regular_pool_base_address_, regular_pool_size); PA_CHECK(setup_.regular_pool_ == kRegularPoolHandle); PA_DCHECK(!IsInRegularPool(setup_.regular_pool_base_address_ - 1)); PA_DCHECK(IsInRegularPool(setup_.regular_pool_base_address_)); PA_DCHECK(IsInRegularPool(setup_.regular_pool_base_address_ + - RegularPoolSize() - 1)); + regular_pool_size - 1)); PA_DCHECK( - !IsInRegularPool(setup_.regular_pool_base_address_ + RegularPoolSize())); + !IsInRegularPool(setup_.regular_pool_base_address_ + regular_pool_size)); + size_t brp_pool_size = BRPPoolSize(); // Reserve an extra allocation granularity unit before the BRP pool, but keep // the pool aligned at BRPPoolSize(). A pointer immediately past an allocation // is a valid pointer, and having a "forbidden zone" before the BRP pool // prevents such a pointer from "sneaking into" the pool. const size_t kForbiddenZoneSize = PageAllocationGranularity(); uintptr_t base_address = AllocPagesWithAlignOffset( - 0, BRPPoolSize() + kForbiddenZoneSize, BRPPoolSize(), - BRPPoolSize() - kForbiddenZoneSize, + 0, brp_pool_size + kForbiddenZoneSize, brp_pool_size, + brp_pool_size - kForbiddenZoneSize, PageAccessibilityConfiguration::kInaccessible, PageTag::kPartitionAlloc); if (!base_address) HandleGigaCageAllocFailure(); setup_.brp_pool_base_address_ = base_address + kForbiddenZoneSize; #if defined(PA_USE_DYNAMICALLY_SIZED_GIGA_CAGE) - setup_.brp_pool_base_mask_ = ~(BRPPoolSize() - 1) & kMemTagUnmask; + setup_.brp_pool_base_mask_ = ~(brp_pool_size - 1) & kMemTagUnmask; #endif - PA_DCHECK(!(setup_.brp_pool_base_address_ & (BRPPoolSize() - 1))); + PA_DCHECK(!(setup_.brp_pool_base_address_ & (brp_pool_size - 1))); setup_.brp_pool_ = AddressPoolManager::GetInstance().Add( - setup_.brp_pool_base_address_, BRPPoolSize()); + setup_.brp_pool_base_address_, brp_pool_size); PA_CHECK(setup_.brp_pool_ == kBRPPoolHandle); PA_DCHECK(!IsInBRPPool(setup_.brp_pool_base_address_ - 1)); PA_DCHECK(IsInBRPPool(setup_.brp_pool_base_address_)); - PA_DCHECK(IsInBRPPool(setup_.brp_pool_base_address_ + BRPPoolSize() - 1)); - PA_DCHECK(!IsInBRPPool(setup_.brp_pool_base_address_ + BRPPoolSize())); + PA_DCHECK(IsInBRPPool(setup_.brp_pool_base_address_ + brp_pool_size - 1)); + PA_DCHECK(!IsInBRPPool(setup_.brp_pool_base_address_ + brp_pool_size)); #if PA_STARSCAN_USE_CARD_TABLE // Reserve memory for PCScan quarantine card table.
diff --git a/base/allocator/partition_allocator/partition_address_space.h b/base/allocator/partition_allocator/partition_address_space.h index 8719868..febb5037 100644 --- a/base/allocator/partition_allocator/partition_address_space.h +++ b/base/allocator/partition_allocator/partition_address_space.h
@@ -201,18 +201,29 @@ static constexpr size_t kBRPPoolSize = kPoolMaxSize; static_assert(base::bits::IsPowerOfTwo(kRegularPoolSize) && base::bits::IsPowerOfTwo(kBRPPoolSize)); -#if BUILDFLAG(IS_IOS) - // TODO(crbug.com/1250788): Remove the iOS special case. - static constexpr size_t kConfigurablePoolMaxSize = kPoolMaxSize; - static constexpr size_t kConfigurablePoolMinSize = kPoolMaxSize; -#else static constexpr size_t kConfigurablePoolMaxSize = kPoolMaxSize; static constexpr size_t kConfigurablePoolMinSize = 1 * kGiB; -#endif static_assert(kConfigurablePoolMinSize <= kConfigurablePoolMaxSize); static_assert(base::bits::IsPowerOfTwo(kConfigurablePoolMaxSize) && base::bits::IsPowerOfTwo(kConfigurablePoolMinSize)); +#if BUILDFLAG(IS_IOS) + +#if !defined(PA_USE_DYNAMICALLY_SIZED_GIGA_CAGE) +#error iOS is only supported with a dynamically sized GigaCase. +#endif + + // We can't afford pool sizes as large as kPoolMaxSize in iOS EarlGrey tests, + // since the test process cannot use an extended virtual address space (see + // crbug.com/1250788). + static constexpr size_t kRegularPoolSizeForIOSTestProcess = kGiB / 4; + static constexpr size_t kBRPPoolSizeForIOSTestProcess = kGiB / 4; + static_assert(kRegularPoolSizeForIOSTestProcess < kRegularPoolSize); + static_assert(kBRPPoolSizeForIOSTestProcess < kBRPPoolSize); + static_assert(base::bits::IsPowerOfTwo(kRegularPoolSizeForIOSTestProcess) && + base::bits::IsPowerOfTwo(kBRPPoolSizeForIOSTestProcess)); +#endif // BUILDFLAG(IOS_IOS) + #if !defined(PA_USE_DYNAMICALLY_SIZED_GIGA_CAGE) // Masks used to easy determine belonging to a pool. // On Arm, the top byte of each pointer is ignored (meaning there are
diff --git a/base/allocator/partition_allocator/partition_alloc_config.h b/base/allocator/partition_allocator/partition_alloc_config.h index 1bc2462c..e2806f13 100644 --- a/base/allocator/partition_allocator/partition_alloc_config.h +++ b/base/allocator/partition_allocator/partition_alloc_config.h
@@ -30,9 +30,11 @@ #define PA_STARSCAN_NEON_SUPPORTED #endif -#if 0 +#if BUILDFLAG(IS_IOS) // Use dynamically sized GigaCage. This allows to query the size at run-time, -// before initialization, instead of using a hardcoded constexpr. +// before initialization, instead of using a hardcoded constexpr. This is needed +// on iOS because iOS test processes can't handle a large cage (see +// crbug.com/1250788). #define PA_USE_DYNAMICALLY_SIZED_GIGA_CAGE #endif
diff --git a/base/allocator/partition_allocator/partition_alloc_constants.h b/base/allocator/partition_allocator/partition_alloc_constants.h index 783f11e..5c4fc39 100644 --- a/base/allocator/partition_allocator/partition_alloc_constants.h +++ b/base/allocator/partition_allocator/partition_alloc_constants.h
@@ -251,12 +251,7 @@ #if defined(PA_HAS_64_BITS_POINTERS) // The Configurable Pool is only available in 64-bit mode constexpr size_t kNumPools = 3; -// TODO(crbug.com/1250788): Remove the iOS special case, once larger address -// space can be used there. This limitation isn't meant for releasing, but is ok -// to keep for now only because nothing uses PartitionAlloc on iOS yet. -#if BUILDFLAG(IS_IOS) -constexpr size_t kPoolMaxSize = kGiB / 4; -#elif BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) // Special-case macOS. Contrary to other platforms, there is no sandbox limit // there, meaning that a single renderer could "happily" consume >8GiB. So the // 8GiB pool size is a regression. Make the limit higher on this platform only
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc index e2f11102..5d75f3af 100644 --- a/base/allocator/partition_allocator/partition_alloc_unittest.cc +++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -53,7 +53,7 @@ #include <sys/time.h> #endif // BUILDFLAG(IS_POSIX) -#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(IS_APPLE) +#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(IS_MAC) #include <OpenCL/opencl.h> #include <base/mac/mac_util.h>
diff --git a/base/debug/close_handle_hook_win.h b/base/debug/close_handle_hook_win.h deleted file mode 100644 index c775d75..0000000 --- a/base/debug/close_handle_hook_win.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_DEBUG_CLOSE_HANDLE_HOOK_WIN_H_ -#define BASE_DEBUG_CLOSE_HANDLE_HOOK_WIN_H_ - -#include "base/base_export.h" - -namespace base { -namespace debug { - -// Installs the hooks required to debug use of improper handles. -BASE_EXPORT void InstallHandleHooks(); - -} // namespace debug -} // namespace base - -#endif // BASE_DEBUG_CLOSE_HANDLE_HOOK_WIN_H_
diff --git a/base/debug/close_handle_hook_win.cc b/base/debug/handle_hooks_win.cc similarity index 61% rename from base/debug/close_handle_hook_win.cc rename to base/debug/handle_hooks_win.cc index 68b0198..bc3eed4b 100644 --- a/base/debug/close_handle_hook_win.cc +++ b/base/debug/handle_hooks_win.cc
@@ -2,17 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/close_handle_hook_win.h" +#include "base/debug/handle_hooks_win.h" -#include <Windows.h> +#include <windows.h> + #include <psapi.h> #include <stddef.h> -#include <algorithm> -#include <memory> -#include <vector> - +#include "base/logging.h" #include "base/memory/raw_ptr.h" +#include "base/numerics/safe_conversions.h" #include "base/win/iat_patch_function.h" #include "base/win/pe_image.h" #include "base/win/scoped_handle.h" @@ -20,24 +19,18 @@ namespace { -typedef BOOL (WINAPI* CloseHandleType) (HANDLE handle); +using CloseHandleType = decltype(&::CloseHandle); +using DuplicateHandleType = decltype(&::DuplicateHandle); -typedef BOOL (WINAPI* DuplicateHandleType)(HANDLE source_process, - HANDLE source_handle, - HANDLE target_process, - HANDLE* target_handle, - DWORD desired_access, - BOOL inherit_handle, - DWORD options); - -CloseHandleType g_close_function = NULL; -DuplicateHandleType g_duplicate_function = NULL; +CloseHandleType g_close_function = nullptr; +DuplicateHandleType g_duplicate_function = nullptr; // The entry point for CloseHandle interception. This function notifies the // verifier about the handle that is being closed, and calls the original // function. BOOL WINAPI CloseHandleHook(HANDLE handle) { - base::win::OnHandleBeingClosed(handle); + base::win::OnHandleBeingClosed(handle, + base::win::HandleOperation::kCloseHandleHook); return g_close_function(handle); } @@ -50,7 +43,8 @@ DWORD options) { if ((options & DUPLICATE_CLOSE_SOURCE) && (GetProcessId(source_process) == ::GetCurrentProcessId())) { - base::win::OnHandleBeingClosed(source_handle); + base::win::OnHandleBeingClosed( + source_handle, base::win::HandleOperation::kDuplicateHandleHook); } return g_duplicate_function(source_process, source_handle, target_process, @@ -74,9 +68,7 @@ AutoProtectMemory(const AutoProtectMemory&) = delete; AutoProtectMemory& operator=(const AutoProtectMemory&) = delete; - ~AutoProtectMemory() { - RevertProtection(); - } + ~AutoProtectMemory() { RevertProtection(); } // Grants write access to a given memory range. bool ChangeProtection(void* address, size_t bytes); @@ -101,7 +93,7 @@ return false; DWORD is_executable = (PAGE_EXECUTE | PAGE_EXECUTE_READ | - PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) & + PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) & memory_info.Protect; DWORD protect = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; @@ -128,9 +120,12 @@ old_protect_ = 0; } -// Performs an EAT interception. -void EATPatch(HMODULE module, const char* function_name, - void* new_function, void** old_function) { +#if defined(ARCH_CPU_32_BITS) +// Performs an EAT interception. Only supported on 32-bit. +void EATPatch(HMODULE module, + const char* function_name, + void* new_function, + void** old_function) { if (!module) return; @@ -150,30 +145,35 @@ return; // Perform the patch. - *eat_entry = static_cast<DWORD>(reinterpret_cast<uintptr_t>(new_function) - - reinterpret_cast<uintptr_t>(module)); + *eat_entry = + base::checked_cast<DWORD>(reinterpret_cast<uintptr_t>(new_function) - + reinterpret_cast<uintptr_t>(module)); } +#endif // defined(ARCH_CPU_32_BITS) // Performs an IAT interception. -base::win::IATPatchFunction* IATPatch(HMODULE module, const char* function_name, - void* new_function, void** old_function) { +std::unique_ptr<base::win::IATPatchFunction> IATPatch(HMODULE module, + const char* function_name, + void* new_function, + void** old_function) { if (!module) - return NULL; + return nullptr; - base::win::IATPatchFunction* patch = new base::win::IATPatchFunction; + auto patch = std::make_unique<base::win::IATPatchFunction>(); __try { // There is no guarantee that |module| is still loaded at this point. if (patch->PatchFromModule(module, "kernel32.dll", function_name, new_function)) { - delete patch; - return NULL; + return nullptr; } - } __except((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION || - GetExceptionCode() == EXCEPTION_GUARD_PAGE || - GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR) ? - EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { + } __except ((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION || + GetExceptionCode() == EXCEPTION_GUARD_PAGE || + GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR) + ? EXCEPTION_EXECUTE_HANDLER + : EXCEPTION_CONTINUE_SEARCH) { // Leak the patch. - return NULL; + std::ignore = patch.release(); + return nullptr; } if (!(*old_function)) { @@ -184,44 +184,32 @@ return patch; } -// Keeps track of all the hooks needed to intercept functions which could -// possibly close handles. -class HandleHooks { - public: - HandleHooks() {} +} // namespace - HandleHooks(const HandleHooks&) = delete; - HandleHooks& operator=(const HandleHooks&) = delete; - - ~HandleHooks() {} - - void AddIATPatch(HMODULE module); - void AddEATPatch(); - - private: - std::vector<base::win::IATPatchFunction*> hooks_; -}; - +// static void HandleHooks::AddIATPatch(HMODULE module) { if (!module) return; - base::win::IATPatchFunction* patch = NULL; - patch = + auto close_handle_patch = IATPatch(module, "CloseHandle", reinterpret_cast<void*>(&CloseHandleHook), reinterpret_cast<void**>(&g_close_function)); - if (!patch) + if (!close_handle_patch) return; - hooks_.push_back(patch); + // This is intentionally leaked. + std::ignore = close_handle_patch.release(); - patch = IATPatch(module, "DuplicateHandle", - reinterpret_cast<void*>(&DuplicateHandleHook), - reinterpret_cast<void**>(&g_duplicate_function)); - if (!patch) + auto duplicate_handle_patch = IATPatch( + module, "DuplicateHandle", reinterpret_cast<void*>(&DuplicateHandleHook), + reinterpret_cast<void**>(&g_duplicate_function)); + if (!duplicate_handle_patch) return; - hooks_.push_back(patch); + // This is intentionally leaked. + std::ignore = duplicate_handle_patch.release(); } +#if defined(ARCH_CPU_32_BITS) +// static void HandleHooks::AddEATPatch() { // An attempt to restore the entry on the table at destruction is not safe. EATPatch(GetModuleHandleA("kernel32.dll"), "CloseHandle", @@ -231,33 +219,24 @@ reinterpret_cast<void*>(&DuplicateHandleHook), reinterpret_cast<void**>(&g_duplicate_function)); } +#endif // defined(ARCH_CPU_32_BITS) -void PatchLoadedModules(HandleHooks* hooks) { +// static +void HandleHooks::PatchLoadedModules() { const DWORD kSize = 256; DWORD returned; - std::unique_ptr<HMODULE[]> modules(new HMODULE[kSize]); - if (!EnumProcessModules(GetCurrentProcess(), modules.get(), - kSize * sizeof(HMODULE), &returned)) { + auto modules = std::make_unique<HMODULE[]>(kSize); + if (!::EnumProcessModules(GetCurrentProcess(), modules.get(), + kSize * sizeof(HMODULE), &returned)) { return; } returned /= sizeof(HMODULE); returned = std::min(kSize, returned); for (DWORD current = 0; current < returned; current++) { - hooks->AddIATPatch(modules[current]); + AddIATPatch(modules[current]); } } -} // namespace - -void InstallHandleHooks() { - static HandleHooks* hooks = new HandleHooks(); - - // Performing EAT interception first is safer in the presence of other - // threads attempting to call CloseHandle. - hooks->AddEATPatch(); - PatchLoadedModules(hooks); -} - } // namespace debug } // namespace base
diff --git a/base/debug/handle_hooks_win.h b/base/debug/handle_hooks_win.h new file mode 100644 index 0000000..5459393 --- /dev/null +++ b/base/debug/handle_hooks_win.h
@@ -0,0 +1,41 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_DEBUG_HANDLE_HOOKS_WIN_H_ +#define BASE_DEBUG_HANDLE_HOOKS_WIN_H_ + +#include "base/base_export.h" +#include "base/win/windows_types.h" +#include "build/build_config.h" + +namespace base { +namespace debug { + +// Provides the ability to intercept functions which could possibly close +// handles in support of the handle tracker. +// This is a currently a container class for static functions because there is +// ongoing work to make the patches unhook, currently blocked by test failures. +// See https://crbug.com/1327397. +class BASE_EXPORT HandleHooks { + public: + HandleHooks() = delete; + + HandleHooks(const HandleHooks&) = delete; + HandleHooks& operator=(const HandleHooks&) = delete; + + // Patch IAT for a specified module. + static void AddIATPatch(HMODULE module); + // Add an EAT patch on kernel32.dll. This patch does not get removed. This is + // only supported on 32-bit because the EAT only supports 32-bit RVAs. +#if defined(ARCH_CPU_32_BITS) + static void AddEATPatch(); +#endif + // Patch IAT for all currently loaded modules. + static void PatchLoadedModules(); +}; + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_HANDLE_HOOKS_WIN_H_
diff --git a/base/win/scoped_handle.cc b/base/win/scoped_handle.cc index de68545..1c1cdce 100644 --- a/base/win/scoped_handle.cc +++ b/base/win/scoped_handle.cc
@@ -11,6 +11,21 @@ using base::win::internal::ScopedHandleVerifier; +std::ostream& operator<<(std::ostream& os, HandleOperation operation) { + switch (operation) { + case HandleOperation::kHandleAlreadyTracked: + return os << "Handle Already Tracked"; + case HandleOperation::kCloseHandleNotTracked: + return os << "Closing an untracked handle"; + case HandleOperation::kCloseHandleNotOwner: + return os << "Closing a handle owned by something else"; + case HandleOperation::kCloseHandleHook: + return os << "CloseHandleHook validation failure"; + case HandleOperation::kDuplicateHandleHook: + return os << "DuplicateHandleHook validation failure"; + } +} + // Static. bool HandleTraits::CloseHandle(HANDLE handle) { return ScopedHandleVerifier::Get()->CloseHandle(handle); @@ -36,8 +51,8 @@ return ScopedHandleVerifier::Get()->Disable(); } -void OnHandleBeingClosed(HANDLE handle) { - return ScopedHandleVerifier::Get()->OnHandleBeingClosed(handle); +void OnHandleBeingClosed(HANDLE handle, HandleOperation operation) { + return ScopedHandleVerifier::Get()->OnHandleBeingClosed(handle, operation); } } // namespace win
diff --git a/base/win/scoped_handle.h b/base/win/scoped_handle.h index bfa8188..3a7d47e 100644 --- a/base/win/scoped_handle.h +++ b/base/win/scoped_handle.h
@@ -7,6 +7,8 @@ #include "base/win/windows_types.h" +#include <ostream> + #include "base/base_export.h" #include "base/check_op.h" #include "base/dcheck_is_on.h" @@ -26,6 +28,16 @@ namespace base { namespace win { +enum class HandleOperation { + kHandleAlreadyTracked, + kCloseHandleNotTracked, + kCloseHandleNotOwner, + kCloseHandleHook, + kDuplicateHandleHook +}; + +std::ostream& operator<<(std::ostream& os, HandleOperation operation); + // Generic wrapper for raw handles that takes care of closing handles // automatically. The class interface follows the style of // the ScopedFILE class with two additions: @@ -113,8 +125,9 @@ } private: - FRIEND_TEST_ALL_PREFIXES(ScopedHandleTest, HandleVerifierWrongOwner); - FRIEND_TEST_ALL_PREFIXES(ScopedHandleTest, HandleVerifierUntrackedHandle); + FRIEND_TEST_ALL_PREFIXES(ScopedHandleDeathTest, HandleVerifierWrongOwner); + FRIEND_TEST_ALL_PREFIXES(ScopedHandleDeathTest, + HandleVerifierUntrackedHandle); Handle handle_; }; @@ -183,7 +196,7 @@ GenericScopedHandle<HandleTraits, DummyVerifierTraits>; using CheckedScopedHandle = GenericScopedHandle<HandleTraits, VerifierTraits>; -#if DCHECK_IS_ON() && !defined(ARCH_CPU_64_BITS) +#if DCHECK_IS_ON() using ScopedHandle = CheckedScopedHandle; #else using ScopedHandle = UncheckedScopedHandle; @@ -198,7 +211,8 @@ // verification of improper handle closing is desired. If |handle| is being // tracked by the handle verifier and ScopedHandle is not the one closing it, // a CHECK is generated. -BASE_EXPORT void OnHandleBeingClosed(HANDLE handle); +BASE_EXPORT void OnHandleBeingClosed(HANDLE handle, HandleOperation operation); + } // namespace win } // namespace base
diff --git a/base/win/scoped_handle_unittest.cc b/base/win/scoped_handle_unittest.cc index 0df21ce..228f2eb6 100644 --- a/base/win/scoped_handle_unittest.cc +++ b/base/win/scoped_handle_unittest.cc
@@ -8,11 +8,13 @@ #include "base/base_switches.h" #include "base/command_line.h" +#include "base/debug/handle_hooks_win.h" #include "base/files/file_path.h" #include "base/scoped_native_library.h" #include "base/test/multiprocess_test.h" #include "base/test/test_timeouts.h" #include "base/win/scoped_handle.h" +#include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/multiprocess_func_list.h" @@ -24,9 +26,31 @@ extern "C" bool __declspec(dllexport) RunTest(); } // namespace testing -TEST(ScopedHandleTest, ScopedHandle) { +class ScopedHandleTest : public ::testing::Test, + public ::testing::WithParamInterface<bool> { + public: + ScopedHandleTest(const ScopedHandleTest&) = delete; + ScopedHandleTest& operator=(const ScopedHandleTest&) = delete; + + protected: + ScopedHandleTest() { + if (HooksEnabled()) { +#if defined(ARCH_CPU_32_BITS) + // EAT patch is only supported on 32-bit. + base::debug::HandleHooks::AddEATPatch(); +#endif + base::debug::HandleHooks::PatchLoadedModules(); + } + } + + static bool HooksEnabled() { return GetParam(); } +}; + +using ScopedHandleDeathTest = ScopedHandleTest; + +TEST_P(ScopedHandleTest, ScopedHandle) { // Any illegal error code will do. We just need to test that it is preserved - // by ScopedHandle to avoid bug 528394. + // by ScopedHandle to avoid https://crbug.com/528394. const DWORD magic_error = 0x12345678; HANDLE handle = ::CreateMutex(nullptr, false, nullptr); @@ -49,7 +73,7 @@ EXPECT_EQ(magic_error, ::GetLastError()); } -TEST(ScopedHandleTest, HandleVerifierTrackedHasBeenClosed) { +TEST_P(ScopedHandleDeathTest, HandleVerifierTrackedHasBeenClosed) { HANDLE handle = ::CreateMutex(nullptr, false, nullptr); ASSERT_NE(HANDLE(nullptr), handle); using NtCloseFunc = decltype(&::NtClose); @@ -64,10 +88,35 @@ // Destructing a ScopedHandle with an illegally closed handle should // fail. }, - ""); + "CloseHandle failed"); } -TEST(ScopedHandleTest, HandleVerifierDoubleTracking) { +TEST_P(ScopedHandleDeathTest, HandleVerifierCloseTrackedHandle) { + // This test is only valid if hooks are enabled. + if (!HooksEnabled()) + return; + ASSERT_DEATH( + { + HANDLE handle = ::CreateMutex(nullptr, false, nullptr); + ASSERT_NE(HANDLE(nullptr), handle); + + // Start tracking the handle so that closes outside of the checker are + // caught. + base::win::CheckedScopedHandle handle_holder(handle); + + // Closing a tracked handle using ::CloseHandle should crash due to hook + // noticing the illegal close. + ::CloseHandle(handle); + }, + // This test must match the CloseHandleHook causing this failure, because + // if the hook doesn't crash and instead the handle is double closed by + // the `handle_holder` going out of scope, then there is still a crash, + // but a different crash and one we are not explicitly testing here. This + // other crash is tested in HandleVerifierTrackedHasBeenClosed above. + "CloseHandleHook validation failure"); +} + +TEST_P(ScopedHandleDeathTest, HandleVerifierDoubleTracking) { HANDLE handle = ::CreateMutex(nullptr, false, nullptr); ASSERT_NE(HANDLE(nullptr), handle); @@ -76,7 +125,7 @@ ASSERT_DEATH({ base::win::CheckedScopedHandle handle_holder2(handle); }, ""); } -TEST(ScopedHandleTest, HandleVerifierWrongOwner) { +TEST_P(ScopedHandleDeathTest, HandleVerifierWrongOwner) { HANDLE handle = ::CreateMutex(nullptr, false, nullptr); ASSERT_NE(HANDLE(nullptr), handle); @@ -86,12 +135,12 @@ base::win::CheckedScopedHandle handle_holder2; handle_holder2.handle_ = handle; }, - ""); + "Closing a handle owned by something else"); ASSERT_TRUE(handle_holder.is_valid()); handle_holder.Close(); } -TEST(ScopedHandleTest, HandleVerifierUntrackedHandle) { +TEST_P(ScopedHandleDeathTest, HandleVerifierUntrackedHandle) { HANDLE handle = ::CreateMutex(nullptr, false, nullptr); ASSERT_NE(HANDLE(nullptr), handle); @@ -100,7 +149,7 @@ base::win::CheckedScopedHandle handle_holder; handle_holder.handle_ = handle; }, - ""); + "Closing an untracked handle"); ASSERT_TRUE(::CloseHandle(handle)); } @@ -113,7 +162,7 @@ #define MAYBE_MultiProcess MultiProcess #endif -TEST(ScopedHandleTest, MAYBE_MultiProcess) { +TEST_P(ScopedHandleTest, MAYBE_MultiProcess) { // Initializing ICU in the child process causes a scoped handle to be created // before the test gets a chance to test the race condition, so disable ICU // for the child process here. @@ -145,5 +194,18 @@ return 0; } +INSTANTIATE_TEST_SUITE_P(HooksEnabled, + ScopedHandleTest, + ::testing::Values(true)); +INSTANTIATE_TEST_SUITE_P(HooksDisabled, + ScopedHandleTest, + ::testing::Values(false)); +INSTANTIATE_TEST_SUITE_P(HooksEnabled, + ScopedHandleDeathTest, + ::testing::Values(true)); +INSTANTIATE_TEST_SUITE_P(HooksDisabled, + ScopedHandleDeathTest, + ::testing::Values(false)); + } // namespace win } // namespace base
diff --git a/base/win/scoped_handle_verifier.cc b/base/win/scoped_handle_verifier.cc index e64bd2c..e7ab4b9 100644 --- a/base/win/scoped_handle_verifier.cc +++ b/base/win/scoped_handle_verifier.cc
@@ -18,6 +18,7 @@ #include "base/trace_event/base_tracing.h" #include "base/win/base_win_buildflags.h" #include "base/win/current_module.h" +#include "base/win/scoped_handle.h" extern "C" { __declspec(dllexport) void* GetHandleVerifier(); @@ -40,21 +41,25 @@ using NativeLock = base::internal::LockImpl; NOINLINE void ReportErrorOnScopedHandleOperation( - const base::debug::StackTrace& creation_stack) { + const base::debug::StackTrace& creation_stack, + HandleOperation operation) { auto creation_stack_copy = creation_stack; base::debug::Alias(&creation_stack_copy); - CHECK(false); + base::debug::Alias(&operation); + CHECK(false) << operation; __builtin_unreachable(); } NOINLINE void ReportErrorOnScopedHandleOperation( const base::debug::StackTrace& creation_stack, - const ScopedHandleVerifierInfo& other) { + const ScopedHandleVerifierInfo& other, + HandleOperation operation) { auto other_stack_copy = *other.stack; base::debug::Alias(&other_stack_copy); auto creation_stack_copy = creation_stack; base::debug::Alias(&creation_stack_copy); - CHECK(false); + base::debug::Alias(&operation); + CHECK(false) << operation; __builtin_unreachable(); } @@ -107,7 +112,7 @@ bool CloseHandleWrapper(HANDLE handle) { if (!::CloseHandle(handle)) - CHECK(false); // CloseHandle failed. + CHECK(false) << "CloseHandle failed"; return true; } @@ -202,9 +207,10 @@ enabled_ = false; } -void ScopedHandleVerifier::OnHandleBeingClosed(HANDLE handle) { +void ScopedHandleVerifier::OnHandleBeingClosed(HANDLE handle, + HandleOperation operation) { if (enabled_) - OnHandleBeingClosedImpl(handle); + OnHandleBeingClosedImpl(handle, operation); } HMODULE ScopedHandleVerifier::GetModule() const { @@ -227,7 +233,8 @@ thread_id}); if (!result.second) { // Attempt to start tracking already tracked handle. - ReportErrorOnScopedHandleOperation(creation_stack_, result.first->second); + ReportErrorOnScopedHandleOperation(creation_stack_, result.first->second, + HandleOperation::kHandleAlreadyTracked); } } @@ -239,18 +246,22 @@ HandleMap::iterator i = map_.find(handle); if (i == map_.end()) { // Attempting to close an untracked handle. - ReportErrorOnScopedHandleOperation(creation_stack_); + ReportErrorOnScopedHandleOperation(creation_stack_, + HandleOperation::kCloseHandleNotTracked); } if (i->second.owner != owner) { // Attempting to close a handle not owned by opener. - ReportErrorOnScopedHandleOperation(creation_stack_, i->second); + ReportErrorOnScopedHandleOperation(creation_stack_, i->second, + HandleOperation::kCloseHandleNotOwner); } map_.erase(i); } -NOINLINE void ScopedHandleVerifier::OnHandleBeingClosedImpl(HANDLE handle) { +NOINLINE void ScopedHandleVerifier::OnHandleBeingClosedImpl( + HANDLE handle, + HandleOperation operation) { if (closing_.Get()) return; @@ -258,7 +269,7 @@ HandleMap::iterator i = map_.find(handle); if (i != map_.end()) { // CloseHandle called on tracked handle. - ReportErrorOnScopedHandleOperation(creation_stack_, i->second); + ReportErrorOnScopedHandleOperation(creation_stack_, i->second, operation); } }
diff --git a/base/win/scoped_handle_verifier.h b/base/win/scoped_handle_verifier.h index 84bb547d..7085e99 100644 --- a/base/win/scoped_handle_verifier.h +++ b/base/win/scoped_handle_verifier.h
@@ -18,6 +18,7 @@ namespace base { namespace win { +enum class HandleOperation; namespace internal { struct HandleHash { @@ -76,7 +77,7 @@ virtual void StopTracking(HANDLE handle, const void* owner, const void* pc1, const void* pc2); virtual void Disable(); - virtual void OnHandleBeingClosed(HANDLE handle); + virtual void OnHandleBeingClosed(HANDLE handle, HandleOperation operation); virtual HMODULE GetModule() const; private: @@ -86,7 +87,7 @@ const void* pc2); void StopTrackingImpl(HANDLE handle, const void* owner, const void* pc1, const void* pc2); - void OnHandleBeingClosedImpl(HANDLE handle); + void OnHandleBeingClosedImpl(HANDLE handle, HandleOperation operation); static base::internal::LockImpl* GetLock(); static void InstallVerifier();
diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py index 6fd132f..ad16a8a 100755 --- a/build/android/gyp/proguard.py +++ b/build/android/gyp/proguard.py
@@ -464,6 +464,10 @@ 'com.google.common.flogger.backend.google.GooglePlatform', 'com.google.common.flogger.backend.system.DefaultPlatform', + # trichrome_webview_google_bundle contains this missing reference. + # TODO(crbug.com/1142530): Fix this missing reference properly. + 'org.chromium.build.NativeLibraries', + # TODO(agrieve): Exclude these only when use_jacoco_coverage=true. 'java.lang.instrument.ClassFileTransformer', 'java.lang.instrument.IllegalClassFormatException',
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 6c119948..1a9b3736 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -2133,7 +2133,6 @@ # uncompressed in the APK. Must be unset or true if load_library_from_apk # is set to true. # uncompress_dex: Store final .dex files uncompressed in the apk. - # omit_dex: If true, do not build or include classes.dex. # strip_resource_names: True if resource names should be stripped from the # resources.arsc file in the apk or module. # strip_unused_resources: True if unused resources should be stripped from @@ -2216,7 +2215,6 @@ defined(invoker.is_base_module) && invoker.is_base_module } - _omit_dex = defined(invoker.omit_dex) && invoker.omit_dex _enable_multidex = !defined(invoker.enable_multidex) || invoker.enable_multidex @@ -2360,13 +2358,12 @@ _rebased_build_config = rebase_path(_build_config, root_build_dir) assert(_rebased_build_config != "") # Mark as used. - _generate_buildconfig_java = !defined(invoker.apk_under_test) && !_omit_dex + _generate_buildconfig_java = !defined(invoker.apk_under_test) if (defined(invoker.generate_buildconfig_java)) { _generate_buildconfig_java = invoker.generate_buildconfig_java } - _generate_productconfig_java = - defined(invoker.product_config_java_packages) && !_omit_dex + _generate_productconfig_java = defined(invoker.product_config_java_packages) # JNI generation usually goes hand-in-hand with buildconfig generation. _generate_final_jni = _generate_buildconfig_java @@ -2430,7 +2427,7 @@ _incremental_apk_path = "${_final_apk_path_no_ext}_incremental.apk" } - if (!_incremental_apk && !_omit_dex) { + if (!_incremental_apk) { # Bundle modules don't build the dex here, but need to write this path # to their .build_config.json file. if (_proguard_enabled) { @@ -2687,9 +2684,8 @@ } else { _generate_native_libraries_java = (!_is_bundle_module || _is_base_module) && - (_native_libs_deps != [] || _secondary_abi_native_libs_deps != [] || - defined(invoker.static_library_provider)) && - !_uses_static_library_synchronized_proguard && !_omit_dex + (_native_libs_deps != [] || _secondary_abi_native_libs_deps != []) && + !_uses_static_library_synchronized_proguard } if (_generate_native_libraries_java) { write_native_libraries_java("${_template_name}__native_libraries") { @@ -2698,17 +2694,7 @@ # Do not add a dep on the generated_file target in order to avoid having # to build the native libraries before this target. The dependency is # instead captured via a depfile. - if (_uses_static_library) { - _prefix = get_label_info(invoker.static_library_provider, - "target_gen_dir") + "/" + - get_label_info(invoker.static_library_provider, "name") - if (defined(invoker.static_library_provider_use_secondary_abi) && - invoker.static_library_provider_use_secondary_abi) { - native_libraries_list_file = "${_prefix}.secondary_abi_native_libs" - } else { - native_libraries_list_file = "${_prefix}.native_libs" - } - } else if (_native_libs_deps != []) { + if (_native_libs_deps != []) { native_libraries_list_file = _shared_library_list_file } else { native_libraries_list_file = _secondary_abi_shared_library_list_file @@ -2804,15 +2790,14 @@ ]) } + _java_target = "${_template_name}__java" + if (_is_bundle_module) { _add_view_trace_events = defined(invoker.add_view_trace_events) && invoker.add_view_trace_events && enable_trace_event_bytecode_rewriting } - # We cannot skip this target when omit_dex = true because it writes the - # build_config.json. - _java_target = "${_template_name}__java" java_library_impl(_java_target) { forward_variables_from(invoker, [ @@ -2944,7 +2929,7 @@ if (_uses_static_library_synchronized_proguard) { _final_dex_target_dep = "${invoker.static_library_provider}__dexsplitter" - } else if ((_is_bundle_module && _proguard_enabled) || _omit_dex) { + } else if (_is_bundle_module && _proguard_enabled) { _final_deps += [ ":$_java_target" ] } else if (_incremental_apk) { if (defined(invoker.enable_proguard_checks)) { @@ -3220,7 +3205,7 @@ deps = _deps + [ ":$_build_config_target" ] if ((!_proguard_enabled || _incremental_apk) && - enable_jdk_library_desugaring && !_omit_dex) { + enable_jdk_library_desugaring) { _all_jdk_libs = "//build/android:all_jdk_libs" deps += [ _all_jdk_libs ] jdk_libs_dex = get_label_info(_all_jdk_libs, "target_out_dir") + @@ -3500,7 +3485,6 @@ "expected_libs_and_assets_base", "generate_buildconfig_java", "generate_final_jni", - "generate_native_libraries_java", "include_size_info", "input_jars_paths", "use_modern_linker", @@ -3525,7 +3509,6 @@ "native_lib_placeholders", "never_incremental", "no_xml_namespaces", - "omit_dex", "png_to_webp", "post_process_package_resources_script", "processor_args_javac", @@ -3550,7 +3533,6 @@ "srcjar_deps", "static_library_dependent_targets", "static_library_provider", - "static_library_provider_use_secondary_abi", "static_library_synchronized_proguard", "target_sdk_version", "testonly", @@ -3650,7 +3632,6 @@ "load_library_from_apk", "loadable_modules", "product_config_java_packages", - "main_component_library", "manifest_package", "max_sdk_version", "min_sdk_version", @@ -3679,7 +3660,6 @@ "short_resource_paths", "srcjar_deps", "static_library_provider", - "static_library_provider_use_secondary_abi", "static_library_synchronized_proguard", "strip_resource_names", "strip_unused_resources",
diff --git a/build/fuchsia/cipd/BUILD.gn b/build/fuchsia/cipd/BUILD.gn index f04d48a..839ce6fd 100644 --- a/build/fuchsia/cipd/BUILD.gn +++ b/build/fuchsia/cipd/BUILD.gn
@@ -14,13 +14,6 @@ visibility = [ ":*" ] -# gn binary location. -if (host_os == "mac") { - _gn_path = "//buildtools/mac/gn" -} else if (host_os == "linux") { - _gn_path = "//buildtools/linux64/gn" -} - if (is_chrome_branded) { package_base_path = "chrome_internal/fuchsia" } else { @@ -92,6 +85,14 @@ _license_path = "${target_gen_dir}/${target_name}/LICENSE" _invoker_dir = get_label_info(":${invoker.target_name}", "dir") _license_target = "${_invoker_dir}:${invoker.target_name}${_archive_suffix}" + + # GN is used by the script and is thus an input. + if (host_os == "mac") { + _gn_path = "//buildtools/mac/gn" + } else if (host_os == "linux") { + _gn_path = "//buildtools/linux64/gn" + } + script = "//tools/licenses.py" inputs = [ "$_gn_path" ] outputs = [ _license_path ]
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index a225751c..9916bf6 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -8.20220519.2.1 +8.20220519.3.1
diff --git a/chrome/VERSION b/chrome/VERSION index 94d4830..1575c7d7 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=104 MINOR=0 -BUILD=5073 +BUILD=5074 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 42e4e794..fa26347 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -2916,6 +2916,12 @@ } } +# TODO(agrieve): Remove this once we switch to using bundle targets to +# generate APK stubs. +android_resources("trichrome_dummy_resources") { + sources = [ "trichrome/res_dummy/values/strings.xml" ] +} + chrome_public_unit_test_apk_manifest = "$root_gen_dir/chrome_public_unit_test_apk_manifest/AndroidManifest.xml" chrome_public_test_apk_manifest =
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 87220dc..6fb71709 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -235,19 +235,6 @@ use_chromium_linker = chromium_linker_supported } - if (_is_trichrome) { - static_library_provider_use_secondary_abi = _is_secondary_abi_primary - - # http://crbug.com/1042107. - if (is_component_build) { - if (android_64bit_target_cpu && _is_64_bit_browser) { - main_component_library = "libmonochrome_64.cr.so" - } else { - main_component_library = "libmonochrome.cr.so" - } - } - } - if (!_is_monochrome && !_is_trichrome) { deps += [ "//chrome/android:chrome_public_v8_assets",
diff --git a/chrome/android/expectations/trichrome_library_apk.AndroidManifest.expected b/chrome/android/expectations/trichrome_library_apk.AndroidManifest.expected index cb6d641c..fd2f714 100644 --- a/chrome/android/expectations/trichrome_library_apk.AndroidManifest.expected +++ b/chrome/android/expectations/trichrome_library_apk.AndroidManifest.expected
@@ -10,7 +10,6 @@ <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="31"/> <application android:extractNativeLibs="false" - android:hasCode="false" android:icon="@drawable/icon_webview" android:label="Trichrome Library" android:multiArch="true"
diff --git a/chrome/android/java/AndroidManifest_trichrome_library.xml b/chrome/android/java/AndroidManifest_trichrome_library.xml index 070efc3..97e9ddd 100644 --- a/chrome/android/java/AndroidManifest_trichrome_library.xml +++ b/chrome/android/java/AndroidManifest_trichrome_library.xml
@@ -18,7 +18,6 @@ <!-- TODO(torne): we should specify an icon, roundIcon, and label from resources. --> <application - android:hasCode="false" android:label="{{ application_label|default('Trichrome Library') }}" android:icon="@drawable/icon_webview" android:multiArch="true"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index a51749f..c5742ba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -179,6 +179,7 @@ import org.chromium.chrome.browser.ui.RootUiCoordinator; import org.chromium.chrome.browser.ui.TabObscuringHandler; import org.chromium.chrome.browser.ui.appmenu.AppMenuPropertiesDelegate; +import org.chromium.chrome.browser.ui.native_page.NativePage; import org.chromium.chrome.browser.undo_tab_close_snackbar.UndoBarController; import org.chromium.chrome.browser.usage_stats.UsageStatsService; import org.chromium.chrome.browser.util.ChromeAccessibilityUtil; @@ -2230,6 +2231,12 @@ ReadingListUtils.showReadingList(currentTab.isIncognito()); } + // At this point we know either the tab will close or the app will minimize. + NativePage nativePage = currentTab.getNativePage(); + if (nativePage != null) { + nativePage.notifyHidingWithBack(); + } + final boolean shouldCloseTab = backShouldCloseTab(currentTab); // Minimize the app if either:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index ad5813b4..1478e321 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -714,6 +714,14 @@ } @Override + public void notifyHidingWithBack() { + FeedReliabilityLogger feedReliabilityLogger = mFeedSurfaceProvider.getReliabilityLogger(); + if (feedReliabilityLogger != null) { + feedReliabilityLogger.onNavigateBack(); + } + } + + @Override public void onVoiceAvailabilityImpacted() { mNewTabPageLayout.updateActionButtonVisibility(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index 27516a8..d5ef3bb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -57,6 +57,7 @@ import org.chromium.base.test.util.FlakyTest; import org.chromium.base.test.util.UrlUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.feed.FeedReliabilityLogger; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -653,6 +654,17 @@ "feed_is_ablated"); } + @Test + @SmallTest + @Feature({"NewTabPage", "FeedNewTabPage"}) + public void testFeedReliabilityLoggingHideWithBack() throws IOException { + TestThreadUtils.runOnUiThreadBlocking(() -> { + ChromeTabbedActivity activity = (ChromeTabbedActivity) mActivityTestRule.getActivity(); + activity.handleBackPressed(); + verify(mFeedReliabilityLogger).onNavigateBack(); + }); + } + private void assertThumbnailInvalidAndRecapture() { Assert.assertTrue(mNtp.shouldCaptureThumbnail()); captureThumbnail();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImplTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImplTest.java index 0df232c7..9fcf062d 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImplTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImplTest.java
@@ -38,6 +38,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator; +import org.chromium.chrome.browser.ui.native_page.NativePage; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.feature_engagement.EventConstants; @@ -85,6 +86,8 @@ public Profile.Natives mMockProfileNatives; @Mock private ObservableSupplier<TabModelSelector> mTabModelSelectorSupplier; + @Mock + private NativePage mNativePage; @Rule public TestRule mProcessor = new Features.JUnitProcessor(); @@ -98,6 +101,7 @@ doReturn(false).when(mOverrideHomePageSupplier).get(); mocker.mock(ProfileJni.TEST_HOOKS, mMockProfileNatives); doReturn(mProfile).when(mMockProfileNatives).fromWebContents(any()); + doReturn(mNativePage).when(mTab).getNativePage(); TrackerFactory.setTrackerForTests(mTracker); doReturn(new ObservableSupplierImpl<>()).when(mTabModelSelectorSupplier).get(); mToolbarTabController = new ToolbarTabControllerImpl(mTabSupplier, @@ -112,6 +116,7 @@ assertFalse(mToolbarTabController.forward()); assertFalse(mToolbarTabController.back()); + verify(mNativePage, never()).notifyHidingWithBack(); } @Test @@ -138,6 +143,15 @@ } @Test + public void back_notifyNativePageHiding() { + doReturn(null).when(mBottomControlsCoordinatorSupplier).get(); + doReturn(true).when(mTab).canGoBack(); + + mToolbarTabController.back(); + verify(mNativePage).notifyHidingWithBack(); + } + + @Test public void stopOrReloadCurrentTab() { doReturn(false).when(mTab).isLoading(); mToolbarTabController.stopOrReloadCurrentTab();
diff --git a/chrome/android/proguard/trichrome.flags b/chrome/android/proguard/trichrome.flags new file mode 100644 index 0000000..68fb39a --- /dev/null +++ b/chrome/android/proguard/trichrome.flags
@@ -0,0 +1,8 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# TODO(agrieve): Once this -keep is removed, add a @CheckDiscard to LibraryLoaderConfig.java. +# Currently the Trichrome library just contains NativeLibraries, which we keep. +# https://crbug.com/901465 +-keep class org.chromium.build.NativeLibraries { *; }
diff --git a/chrome/android/trichrome.gni b/chrome/android/trichrome.gni index 1e2eec7..01b7f0b 100644 --- a/chrome/android/trichrome.gni +++ b/chrome/android/trichrome.gni
@@ -114,7 +114,7 @@ product_version_resources_dep = "//chrome/android:product_version_resources" } else { - omit_dex = true + generate_buildconfig_java = false } # TODO(torne): using icon_resources just to get a temporary icon @@ -194,6 +194,37 @@ } } } + + # http://crbug.com/1042107. + if (is_component_build) { + if (android_64bit_target_cpu && invoker.is_64_bit_browser) { + main_component_library = "libmonochrome_64.cr.so" + } else { + main_component_library = "libmonochrome.cr.so" + } + } + + if (!is_java_debug) { + proguard_enabled = true + proguard_configs = [ + "//base/android/proguard/chromium_apk.flags", + "//base/android/proguard/chromium_code.flags", + "//chrome/android/proguard/trichrome.flags", + ] + if (trichrome_synchronized_proguard) { + proguard_configs += [ + "//chrome/android/proguard/static_library_dex_reference_workarounds.flags", + "//base/android/proguard/enable_obfuscation.flags", + ] + } else { + # Disabling all obfuscation for the Trichrome library as a temporary + # workaround for crbug.com/1012842. There were naming conflicts between + # Library and Chrome, since each Proguard run doesn't know about the + # other, and thus handed out the first names (a, b, c) to both. + proguard_enable_obfuscation = false + } + } + deps += [ "//chrome/android:trichrome_dummy_resources" ] } }
diff --git a/chrome/android/trichrome/res_dummy/values/strings.xml b/chrome/android/trichrome/res_dummy/values/strings.xml new file mode 100644 index 0000000..a0d71c24 --- /dev/null +++ b/chrome/android/trichrome/res_dummy/values/strings.xml
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> + +<!-- DO NOT ADD MORE RESOURCES HERE --> +<resources> + <string name="dummy"></string> +</resources> \ No newline at end of file
diff --git a/chrome/android/trichrome/static_library_shared_java_code.md b/chrome/android/trichrome/static_library_shared_java_code.md new file mode 100644 index 0000000..a288902 --- /dev/null +++ b/chrome/android/trichrome/static_library_shared_java_code.md
@@ -0,0 +1,100 @@ +# Static Library Java code + +[TOC] + +## Overview + +This document describes how static library targets can be used to share common +Java code between multiple APKs. More detail can be found at +[go/proguarding-trichrome](goto.google.com/proguarding-trichrome). + +## TrichromeLibrary + +Currently (Jan 2020) trichrome library is the only target to make use of static +shared library APKs and is used to share common code used by both Chrome and +Webview. + +## Status + +Java code sharing is mostly implemented at this point but there is one remaining +blocker related to how +[native method resolution works in Webview](crbug.com/1025009). + +## How it works + +### Build variables + +For `android_apk_or_module` base templates: + +`static_library_provider`: Specifies that this target depends on a static shared +library APK. When synchronized proguard is turned on, the +`static_library_provider` becomes the target that provides the final dex file. + +`static_library_dependent_targets`: If set, generates final dex files for +itself and for all targets in the `static_library_dependent_targets` list. + +`static_library_synchronized_proguard`: Turns on synchronized proguard for +targets that also set `static_library_provider`. + +### .build_config + +`write_build_config.py` is responsible for figuring out where code and related +artifacts for the `static_library_provider` and +`static_library_dependent_targets` belongs. The main difference from regular +`.build_configs` is the mapping recording which input jars belong to each final +dex file. Ex: + +``` +"deps_info": { + ... + "static_library_dependent_classpath_configs": { + "gen/android_webview/trichrome_webview_apk.build_config.json": [ + "obj/android_webview/trichrome_webview_apk/trichrome_webview_apk.jar", + ... + ], + "gen/chrome/android/trichrome_chrome_bundle.build_config.json": [ + "lib.java/chrome/android/app_hooks_java.jar", + ... + "gen/chrome/android/trichrome_library_apk.build_config.json": [ + "lib.java/base/base_java.jar", + ... + ] + ... + } +} +``` + +### Synchronized ProGuard + +TrichromeChromeBundle (base module) and TrichromeWebview do not have a final +`dex` or `proguard` step. Instead the library APK creates a "fat" dex from the +`.build_config.json:deps_info:java_runtime_classpath`. + +Then, the mapping of `.build_config.json` -> owned input jars stored in the +`.build_config.json` is used by `dexsplitter` to generate final .dex files for +TrichromeLibrary, TrichromeChrome, and TrichromeWebview. + +### Resources + +For Java code to be shared between Chrome and Webview in [Trichrome][trichrome], +we ensure that Chrome and Webview use the same resource IDs. This requires a +few adjustments to how resources are created. + +1. Webview's resources are compiled first without any changes. +2. Chrome's resources are compiled second, but use the same resource IDs as + Webview when possible. +3. When synchronized proguarding is turned on, the `R.java` files generated in + the previous step are discarded. The shared static library APK target + (trichrome library) takes the output `R.txt` files from the previous steps + and includes those resources in its own `R.java` generation. + +[trichrome]: /chrome/android/trichrome/static_library_shared_java_code.md + +### Usage + +* Building trichrome_chrome_bundle or trichrome_webview_apk (and various arch + variants) will ensure the correct library target is also built. +* Using the generated wrapper script from the main APK is sufficient (no need + to explicitly install the library). + * `bin/trichrome_chrome_bundle run` will ensure TrichromeChromeBundle and + TrichromeLibrary are installed before launching Chrome.
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index 6ae82940..de985ff 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -85,7 +85,7 @@ #include <algorithm> -#include "base/debug/close_handle_hook_win.h" +#include "base/debug/handle_hooks_win.h" #include "base/files/important_file_writer_cleaner.h" #include "base/threading/platform_thread_win.h" #include "base/win/atl.h" @@ -808,8 +808,8 @@ *exit_code = 0; return true; // Got a --version switch; exit with a success error code. } -// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch -// of lacros-chrome is complete. + // TODO(crbug.com/1052397): Revisit the macro expression once build flag + // switch of lacros-chrome is complete. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) // This will directly exit if the user asked for help. HandleHelpSwitches(command_line); @@ -823,11 +823,25 @@ return true; } -// HandleVerifier detects and reports incorrect handle manipulations. It tracks -// handle operations on builds that support DCHECK only. -// TODO(crbug/1104358): Support 64-bit handle hooks. -#if DCHECK_IS_ON() && !defined(ARCH_CPU_64_BITS) - base::debug::InstallHandleHooks(); + // HandleVerifier detects and reports incorrect handle manipulations. It + // tracks handle operations on builds that support DCHECK only. +#if DCHECK_IS_ON() + // This portion of the hook setup is just for child processes. Browser part is + // in ChromeBrowserMainPartsWin::PostProfileInit. + if (!is_browser) { + // Performing EAT interception first is safer in the presence of other + // threads attempting to call CloseHandle. +#if defined(ARCH_CPU_32_BITS) + // Patching EAT of kernel32.dll is only supported on 32-bit because RVA can + // only hold 32-bit values. + base::debug::HandleHooks::AddEATPatch(); +#endif + // Patch once. Cannot monitor for further modules in a child process as + // monitoring needs ModuleWatcher, but likely no more should really load in + // a child process from this point on. If we miss any then we will lose some + // detection but still generate no false positive crashes. + base::debug::HandleHooks::PatchLoadedModules(); + } #else base::win::DisableHandleVerifier(); #endif @@ -1076,6 +1090,18 @@ lacros_resources_dir.Append(FILE_PATH_LITERAL("resources.pak")), user_data_dir.Append(crosapi::kSharedResourcesPackName), ui::kScaleFactorNone); + ui::DataPackWithResourceSharing::MaybeGenerateFallbackAndMapping( + ash_resources_dir.Append(FILE_PATH_LITERAL("chrome_100_percent.pak")), + lacros_resources_dir.Append( + FILE_PATH_LITERAL("chrome_100_percent.pak")), + user_data_dir.Append(crosapi::kSharedChrome100PercentPackName), + ui::k100Percent); + ui::DataPackWithResourceSharing::MaybeGenerateFallbackAndMapping( + ash_resources_dir.Append(FILE_PATH_LITERAL("chrome_200_percent.pak")), + lacros_resources_dir.Append( + FILE_PATH_LITERAL("chrome_200_percent.pak")), + user_data_dir.Append(crosapi::kSharedChrome200PercentPackName), + ui::k200Percent); } } #endif
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 55a0a7a..5511012 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -13064,6 +13064,9 @@ <message name="IDS_INPUT_OVERLAY_EDUCATIONAL_BETA" desc="Label marking the feature as 'Beta', this has to be removed after the feature is fully approved."> Beta </message> + <message name="IDS_INPUT_OVERLAY_SETTINGS_NUDGE" desc="Label displayed next to the Settings UI's entry point so the user is aware."> + Click here to customize controls + </message> </if> <!-- Privacy Sandbox Dialog strings -->
diff --git a/chrome/app/generated_resources_grd/IDS_INPUT_OVERLAY_SETTINGS_NUDGE.png.sha1 b/chrome/app/generated_resources_grd/IDS_INPUT_OVERLAY_SETTINGS_NUDGE.png.sha1 new file mode 100644 index 0000000..cc0b027 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_INPUT_OVERLAY_SETTINGS_NUDGE.png.sha1
@@ -0,0 +1 @@ +b60e34179fcc2ab32e3727ec98536f280e51be5b \ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index 80e85b8..de7f049 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -1917,6 +1917,9 @@ <message name="IDS_SETTINGS_CROSTINI_SUBTEXT" desc="Description for the section for enabling and managing Crostini."> Run Linux tools, editors, and IDEs on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. <ph name="LINK_BEGIN"><a target="_blank" href="$2<ex>https://google.com/</ex>"></ph>Learn more<ph name="LINK_END"></a></ph> </message> + <message name="IDS_SETTINGS_CROSTINI_SUBTEXT_NOT_SUPPORTED" desc="Description for the Developers section when crostini is not supported due to hardware limitation or account restrictions."> + Linux is not supported on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. <ph name="LINK_BEGIN"><a target="_blank" href="$2<ex>https://google.com/</ex>"></ph>Learn more<ph name="LINK_END"></a></ph> + </message> <message name="IDS_SETTINGS_CROSTINI_REMOVE" desc="Label for the row to open a dialog confirming removal of Crostini."> Remove Linux development environment </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CROSTINI_SUBTEXT_NOT_SUPPORTED.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CROSTINI_SUBTEXT_NOT_SUPPORTED.png.sha1 new file mode 100644 index 0000000..d39ae44c --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CROSTINI_SUBTEXT_NOT_SUPPORTED.png.sha1
@@ -0,0 +1 @@ +329a2b7307dc1face48c6c475238225e74b77908 \ No newline at end of file
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index 7c3c24e..f1d2c439 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -239,6 +239,7 @@ "sharesheet_share_with_others.icon", "sharesheet_text.icon", "shutdown_guest_os.icon", + "tip.icon", ] }
diff --git a/chrome/app/vector_icons/tip.icon b/chrome/app/vector_icons/tip.icon new file mode 100644 index 0000000..118ba3e4 --- /dev/null +++ b/chrome/app/vector_icons/tip.icon
@@ -0,0 +1,25 @@ +// Copyright 2022 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. + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 10.42f, 7.08f, +LINE_TO, 8.33f, 2.5f, +LINE_TO, 6.25f, 7.08f, +LINE_TO, 1.67f, 9.17f, +LINE_TO, 6.25f, 11.25f, +LINE_TO, 8.33f, 15.83f, +LINE_TO, 10.42f, 11.25f, +LINE_TO, 15, 9.17f, +LINE_TO, 10.42f, 7.08f, +CLOSE, +MOVE_TO, 15, 10.83f, +LINE_TO, 13.96f, 13.13f, +LINE_TO, 11.67f, 14.17f, +LINE_TO, 13.96f, 15.21f, +LINE_TO, 15, 17.5f, +LINE_TO, 16.04f, 15.21f, +LINE_TO, 18.33f, 14.17f, +LINE_TO, 16.04f, 13.13f, +LINE_TO, 15, 10.83f, +CLOSE
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index d091dfe..ff7efb1 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1537,8 +1537,6 @@ "segmentation_platform/default_model/feed_user_segment.h", "segmentation_platform/default_model/low_user_engagement_model.cc", "segmentation_platform/default_model/low_user_engagement_model.h", - "segmentation_platform/default_model/metadata_writer.cc", - "segmentation_platform/default_model/metadata_writer.h", "segmentation_platform/default_model/query_tiles_model.cc", "segmentation_platform/default_model/query_tiles_model.h", "segmentation_platform/model_provider_factory_impl.cc", @@ -5811,6 +5809,8 @@ "mac/auth_session_request.mm", "mac/bluetooth_utility.h", "mac/bluetooth_utility.mm", + "mac/chrome_browser_main_extra_parts_mac.h", + "mac/chrome_browser_main_extra_parts_mac.mm", "mac/dock.h", "mac/dock.mm", "mac/exception_processor.h", @@ -7702,6 +7702,7 @@ "//chrome/browser/media:mojo_bindings_js", "//chrome/browser/resources/accessibility:build_ts", "//chrome/browser/resources/local_state:build", + "//chrome/browser/resources/memory_internals:build_ts", "//chrome/browser/resources/predictors:build_ts", "//chrome/browser/ui/webui/internals/user_education:mojo_bindings_js", "//components/site_engagement/core/mojom:mojo_bindings_webui_js",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index d6f5fa6..885dfff 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -76,7 +76,6 @@ #include "components/autofill_assistant/browser/features.h" #include "components/browser_sync/browser_sync_switches.h" #include "components/browsing_data/core/features.h" -#include "components/certificate_transparency/ct_features.h" #include "components/commerce/core/commerce_feature_list.h" #include "components/commerce/core/flag_descriptions.h" #include "components/component_updater/component_updater_command_line_config_policy.h" @@ -1498,6 +1497,26 @@ {" alternate hover card format", kTabHoverCardImagesAlternateFormat, std::size(kTabHoverCardImagesAlternateFormat), nullptr}}; +const FeatureEntry::FeatureParam kSharedHighlightingMaxContextWords5[] = { + {shared_highlighting::kSharedHighlightingRefinedMaxContextWordsName, "5"}}; +const FeatureEntry::FeatureParam kSharedHighlightingMaxContextWords10[] = { + {shared_highlighting::kSharedHighlightingRefinedMaxContextWordsName, "10"}}; +const FeatureEntry::FeatureParam kSharedHighlightingMaxContextWords15[] = { + {shared_highlighting::kSharedHighlightingRefinedMaxContextWordsName, "15"}}; +const FeatureEntry::FeatureParam kSharedHighlightingMaxContextWords20[] = { + {shared_highlighting::kSharedHighlightingRefinedMaxContextWordsName, "20"}}; + +const FeatureEntry::FeatureVariation + kSharedHighlightingMaxContextWordsVariations[] = { + {" - maxContextWords: 5", kSharedHighlightingMaxContextWords5, + std::size(kSharedHighlightingMaxContextWords5), nullptr}, + {" - maxContextWords: 10", kSharedHighlightingMaxContextWords10, + std::size(kSharedHighlightingMaxContextWords10), nullptr}, + {" - maxContextWords: 15", kSharedHighlightingMaxContextWords15, + std::size(kSharedHighlightingMaxContextWords15), nullptr}, + {" - maxContextWords: 20", kSharedHighlightingMaxContextWords20, + std::size(kSharedHighlightingMaxContextWords20), nullptr}}; + #if !BUILDFLAG(IS_ANDROID) const FeatureEntry::FeatureParam kNtpChromeCartModuleFakeData[] = { @@ -6943,6 +6962,14 @@ flag_descriptions::kSharedHighlightingRefinedBlocklistDescription, kOsAll, FEATURE_VALUE_TYPE( shared_highlighting::kSharedHighlightingRefinedBlocklist)}, + {"shared-highlighting-refined-maxcontextwords", + flag_descriptions::kSharedHighlightingRefinedMaxContextWordsName, + flag_descriptions::kSharedHighlightingRefinedMaxContextWordsDescription, + kOsAll, + FEATURE_WITH_PARAMS_VALUE_TYPE( + shared_highlighting::kSharedHighlightingRefinedMaxContextWords, + kSharedHighlightingMaxContextWordsVariations, + "SharedHighlightingRefinedMaxContextWords")}, #if BUILDFLAG(IS_CHROMEOS_ASH) {"shimless-rma-flow", flag_descriptions::kShimlessRMAFlowName, @@ -8330,19 +8357,6 @@ autofill::features:: kAutofillEnableVirtualCardManagementInDesktopSettingsPage)}, - {"certificate-transparency-2022-policy", - flag_descriptions::kCertificateTransparency2022PolicyName, - flag_descriptions::kCertificateTransparency2022PolicyDescription, kOsAll, - FEATURE_VALUE_TYPE(certificate_transparency::features:: - kCertificateTransparency2022Policy)}, - - {"certificate-transparency-2022-policy-all-certs", - flag_descriptions::kCertificateTransparency2022PolicyAllCertsName, - flag_descriptions::kCertificateTransparency2022PolicyAllCertsDescription, - kOsAll, - FEATURE_VALUE_TYPE(certificate_transparency::features:: - kCertificateTransparency2022PolicyAllCerts)}, - {"leak-detection-unauthenticated", flag_descriptions::kLeakDetectionUnauthenticated, flag_descriptions::kLeakDetectionUnauthenticatedDescription, kOsAll,
diff --git a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc index 5a7bc60..2035c386 100644 --- a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc +++ b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc
@@ -6,9 +6,14 @@ #include <memory> +#include "ash/components/arc/compat_mode/style/arc_color_provider.h" #include "ash/frame/non_client_frame_view_ash.h" +#include "ash/public/cpp/style/color_provider.h" #include "ash/shell.h" +#include "ash/style/ash_color_provider.h" +#include "ash/style/pill_button.h" #include "base/bind.h" +#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ash/arc/input_overlay/ui/edit_mode_exit_view.h" #include "chrome/browser/ash/arc/input_overlay/ui/educational_view.h" #include "chrome/browser/ash/arc/input_overlay/ui/error_view.h" @@ -35,6 +40,8 @@ constexpr int kEditModeExitHeight = 184; constexpr SkColor kMenuEntryBgColor = SkColorSetA(SK_ColorWHITE, 0x99); constexpr int kCornerRadius = 8; +constexpr int kNudgeVerticalAlign = 8; +constexpr int kNudgeHeight = 40; } // namespace @@ -95,6 +102,51 @@ } } +void DisplayOverlayController::AddNudgeView(views::Widget* overlay_widget) { + if (nudge_view_) + return; + DCHECK(overlay_widget); + auto nudge_view = std::make_unique<ash::PillButton>( + base::BindRepeating(&DisplayOverlayController::OnNudgeDismissed, + base::Unretained(this)), + l10n_util::GetStringUTF16(IDS_INPUT_OVERLAY_SETTINGS_NUDGE), + ash::PillButton::Type::kIcon, &kTipIcon); + nudge_view->SetSize( + gfx::Size(nudge_view->GetPreferredSize().width(), kNudgeHeight)); + nudge_view->SetButtonTextColor(GetContentLayerColor( + ash::AshColorProvider::ContentLayerType::kTextColorPrimary)); + auto* color_provider = ash::AshColorProvider::Get(); + DCHECK(color_provider); + // TODO(djacobo|cuicuiruan): Retrieve colors via a single provider. + nudge_view->SetBackgroundColor(color_provider->GetContentLayerColor( + ash::AshColorProvider::ContentLayerType::kButtonLabelColorBlue)); + nudge_view->SetIconColor(GetContentLayerColor( + ash::AshColorProvider::ContentLayerType::kIconColorPrimary)); + nudge_view->SetPosition(CalculateNudgePosition(nudge_view->width())); + + auto* parent = overlay_widget->GetContentsView(); + DCHECK(parent); + nudge_view_ = parent->AddChildView(std::move(nudge_view)); +} + +void DisplayOverlayController::RemoveNudgeView() { + if (!nudge_view_) + return; + nudge_view_->parent()->RemoveChildViewT(nudge_view_); + nudge_view_ = nullptr; +} + +void DisplayOverlayController::OnNudgeDismissed() { + touch_injector_->set_first_launch(false); + RemoveNudgeView(); +} + +gfx::Point DisplayOverlayController::CalculateNudgePosition(int nudge_width) { + gfx::Point nudge_position = CalculateMenuEntryPosition(); + return gfx::Point(nudge_position.x() - nudge_width - kMenuEntrySideMargin, + nudge_position.y() + kNudgeVerticalAlign); +} + void DisplayOverlayController::AddMenuEntryView(views::Widget* overlay_widget) { if (menu_entry_) return; @@ -213,7 +265,6 @@ } void DisplayOverlayController::OnEducationalViewDismissed() { - touch_injector_->set_first_launch(false); SetDisplayMode(DisplayMode::kView); } @@ -274,6 +325,7 @@ RemoveMenuEntryView(); RemoveInputMappingView(); RemoveEditModeExitView(); + RemoveNudgeView(); break; case DisplayMode::kEducation: AddEducationalView(); @@ -284,8 +336,11 @@ RemoveInputMenuView(); RemoveEditModeExitView(); RemoveEducationalView(); + RemoveNudgeView(); AddInputMappingView(overlay_widget); AddMenuEntryView(overlay_widget); + if (touch_injector_->first_launch()) + AddNudgeView(overlay_widget); overlay_widget->GetNativeWindow()->SetEventTargetingPolicy( aura::EventTargetingPolicy::kNone); break; @@ -293,6 +348,7 @@ RemoveInputMenuView(); RemoveMenuEntryView(); RemoveEducationalView(); + RemoveNudgeView(); AddEditModeExitView(overlay_widget); overlay_widget->GetNativeWindow()->SetEventTargetingPolicy( aura::EventTargetingPolicy::kTargetAndDescendants); @@ -445,7 +501,7 @@ void DisplayOverlayController::ProcessPressedEvent( const ui::LocatedEvent& event) { - if (!action_edit_menu_ && !error_ && !input_menu_view_) + if (!action_edit_menu_ && !error_ && !input_menu_view_ && !nudge_view_) return; auto root_location = event.root_location(); @@ -467,6 +523,10 @@ if (!bounds.Contains(root_location)) SetDisplayMode(DisplayMode::kView); } + + // Dismiss the nudge, regardless where the click was. + if (nudge_view_) + OnNudgeDismissed(); } void DisplayOverlayController::DismissEducationalViewForTesting() {
diff --git a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h index 9fbf917..614ed8c 100644 --- a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h +++ b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h
@@ -22,6 +22,10 @@ class Widget; } // namespace views +namespace ash { +class PillButton; +} // namespace ash + namespace arc { class ArcInputOverlayManagerTest; namespace input_overlay { @@ -85,6 +89,12 @@ void AddOverlay(DisplayMode display_mode); void RemoveOverlayIfAny(); + // On charge of Add/Remove nudge view. + void AddNudgeView(views::Widget* overlay_widget); + void RemoveNudgeView(); + void OnNudgeDismissed(); + gfx::Point CalculateNudgePosition(int nudge_width); + void AddMenuEntryView(views::Widget* overlay_widget); void RemoveMenuEntryView(); void OnMenuEntryPressed(); @@ -133,6 +143,7 @@ raw_ptr<EditModeExitView> edit_mode_view_ = nullptr; raw_ptr<ErrorView> error_ = nullptr; raw_ptr<EducationalView> educational_view_ = nullptr; + raw_ptr<ash::PillButton> nudge_view_ = nullptr; DisplayMode display_mode_ = DisplayMode::kNone; };
diff --git a/chrome/browser/ash/crosapi/browser_manager.cc b/chrome/browser/ash/crosapi/browser_manager.cc index 4effeef..8cc7b92 100644 --- a/chrome/browser/ash/crosapi/browser_manager.cc +++ b/chrome/browser/ash/crosapi/browser_manager.cc
@@ -154,6 +154,13 @@ kMaxValue = kForcedByPolicyLacrosOnly }; +// Resources file sharing mode. +enum class ResourcesFileSharingMode { + kDefault = 0, + // Failed to handle cached shared resources properly. + kError = 1, +}; + using LaunchParamsFromBackground = BrowserManager::LaunchParamsFromBackground; // Pointer to the global instance of BrowserManager. @@ -195,22 +202,20 @@ return false; } -// Return false when there is a failure that might break resource file sharing -// feature. -bool ClearOrMoveSharedResourceFile(bool clear_shared_resource_file) { - base::FilePath shared_resource_path = - browser_util::GetUserDataDir().Append(crosapi::kSharedResourcesPackName); +ResourcesFileSharingMode ClearOrMoveSharedResourceFileInternal( + bool clear_shared_resource_file, + base::FilePath shared_resource_path) { // If shared resource pak doesn't exit, do nothing. if (!base::PathExists(shared_resource_path)) - return true; + return ResourcesFileSharingMode::kDefault; // Clear shared resource file cache if `clear_shared_resource_file` is true. if (clear_shared_resource_file) { if (!base::DeleteFile(shared_resource_path)) { LOG(ERROR) << "Failed to delete cached shared resource file."; - return false; + return ResourcesFileSharingMode::kError; } - return true; + return ResourcesFileSharingMode::kDefault; } base::FilePath renamed_shared_resource_path = @@ -220,9 +225,41 @@ if (!base::Move(shared_resource_path, renamed_shared_resource_path)) { LOG(ERROR) << "Failed to move cached shared resource file to temporary " << "location."; - return false; + return ResourcesFileSharingMode::kError; } - return true; + return ResourcesFileSharingMode::kDefault; +} + +ResourcesFileSharingMode ClearOrMoveSharedResourceFile( + bool clear_shared_resource_file) { + // Check 3 resource paks, resources.pak, chrome_100_percent.pak and + // chrome_200_percent.pak. + ResourcesFileSharingMode resources_file_sharing_mode = + ResourcesFileSharingMode::kDefault; + // Return kError if any of the resources failed to clear or move. + // Make sure that ClearOrMoveSharedResourceFileInternal() runs for all + // resources even if it already fails for some resource. + if (ClearOrMoveSharedResourceFileInternal( + clear_shared_resource_file, browser_util::GetUserDataDir().Append( + crosapi::kSharedResourcesPackName)) == + ResourcesFileSharingMode::kError) { + resources_file_sharing_mode = ResourcesFileSharingMode::kError; + } + if (ClearOrMoveSharedResourceFileInternal( + clear_shared_resource_file, + browser_util::GetUserDataDir().Append( + crosapi::kSharedChrome100PercentPackName)) == + ResourcesFileSharingMode::kError) { + resources_file_sharing_mode = ResourcesFileSharingMode::kError; + } + if (ClearOrMoveSharedResourceFileInternal( + clear_shared_resource_file, + browser_util::GetUserDataDir().Append( + crosapi::kSharedChrome200PercentPackName)) == + ResourcesFileSharingMode::kError) { + resources_file_sharing_mode = ResourcesFileSharingMode::kError; + } + return resources_file_sharing_mode; } // This method runs some work on a background thread prior to launching lacros. @@ -265,7 +302,8 @@ // Clear shared resource file cache if it's initial lacros launch after ash // reboot. If not, rename shared resource file cache to temporal name on // Lacros launch. - if (!ClearOrMoveSharedResourceFile(clear_shared_resource_file)) + if (ClearOrMoveSharedResourceFile(clear_shared_resource_file) == + ResourcesFileSharingMode::kError) params.enable_resource_file_sharing = false; return params;
diff --git a/chrome/browser/ash/crosapi/environment_provider.cc b/chrome/browser/ash/crosapi/environment_provider.cc index 92128cee..34e5c33 100644 --- a/chrome/browser/ash/crosapi/environment_provider.cc +++ b/chrome/browser/ash/crosapi/environment_provider.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profiles_state.h" +#include "chrome/browser/web_applications/preinstalled_web_app_config_utils.h" #include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "chromeos/crosapi/mojom/policy_namespace.mojom.h" #include "chromeos/dbus/cros_disks/cros_disks_client.h" @@ -130,6 +131,11 @@ default_paths->share_cache = file_manager::util::GetShareCacheFilePath(profile); + default_paths->preinstalled_web_app_config = + web_app::GetPreinstalledWebAppConfigDirFromCommandLine(profile); + default_paths->preinstalled_web_app_extra_config = + web_app::GetPreinstalledWebAppExtraConfigDirFromCommandLine(profile); + return default_paths; }
diff --git a/chrome/browser/ash/dbus/encrypted_reporting_service_provider.cc b/chrome/browser/ash/dbus/encrypted_reporting_service_provider.cc index 868cbe5..287607f 100644 --- a/chrome/browser/ash/dbus/encrypted_reporting_service_provider.cc +++ b/chrome/browser/ash/dbus/encrypted_reporting_service_provider.cc
@@ -172,9 +172,7 @@ } upload_provider_->RequestUploadEncryptedRecords( - request.need_encryption_keys(), - std::make_unique<std::vector<reporting::EncryptedRecord>>( - std::move(records)), + request.need_encryption_keys(), std::move(records), base::BindPostTask( origin_thread_runner_, base::BindOnce(&SendStatusAsResponse, std::move(response),
diff --git a/chrome/browser/ash/drive/OWNERS b/chrome/browser/ash/drive/OWNERS index ce1c9d0..31b8eee 100644 --- a/chrome/browser/ash/drive/OWNERS +++ b/chrome/browser/ash/drive/OWNERS
@@ -1,8 +1 @@ -austinct@chromium.org -hashimoto@chromium.org -hidehiko@chromium.org -hirono@chromium.org -kinaba@chromium.org -sammc@chromium.org -slangley@chromium.org -yoshiki@chromium.org +file://ui/file_manager/OWNERS \ No newline at end of file
diff --git a/chrome/browser/ash/file_manager/extract_io_task.cc b/chrome/browser/ash/file_manager/extract_io_task.cc index 284875fd..d0fea72 100644 --- a/chrome/browser/ash/file_manager/extract_io_task.cc +++ b/chrome/browser/ash/file_manager/extract_io_task.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/files/file_util.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/strcat.h" #include "base/task/thread_pool.h" #include "chrome/browser/ash/file_manager/fileapi_util.h" @@ -21,6 +22,10 @@ namespace file_manager { namespace io_task { +void RecordUmaExtractStatus(ExtractStatus status) { + UMA_HISTOGRAM_ENUMERATION(kExtractTaskStatusHistogramName, status); +} + ExtractIOTask::ExtractIOTask( std::vector<storage::FileSystemURL> source_urls, storage::FileSystemURL parent_folder, @@ -52,6 +57,9 @@ progress_.state = success ? State::kSuccess : State::kError; DCHECK_GT(extractCount_, 0); if (--extractCount_ == 0) { + RecordUmaExtractStatus(progress_.state == State::kSuccess + ? ExtractStatus::kSuccess + : ExtractStatus::kUnknownError); Complete(); } } @@ -118,6 +126,7 @@ progress_.outputs.emplace_back(progress_.destination_folder, base::File::FILE_ERROR_NO_SPACE); progress_.state = State::kError; + RecordUmaExtractStatus(ExtractStatus::kInsufficientDiskSpace); Complete(); return; } @@ -175,6 +184,7 @@ if (!chromeos::FileSystemBackend::CanHandleURL(parent_folder_) || sizingCount_ == 0) { progress_.state = State::kError; + RecordUmaExtractStatus(ExtractStatus::kUnknownError); Complete(); } else { CheckSizeThenExtract(); @@ -183,6 +193,7 @@ void ExtractIOTask::Cancel() { progress_.state = State::kCancelled; + RecordUmaExtractStatus(ExtractStatus::kCancelled); // Any inflight operation will be cancelled when the task is destroyed. }
diff --git a/chrome/browser/ash/file_manager/extract_io_task.h b/chrome/browser/ash/file_manager/extract_io_task.h index 3466c78..6dfd098 100644 --- a/chrome/browser/ash/file_manager/extract_io_task.h +++ b/chrome/browser/ash/file_manager/extract_io_task.h
@@ -21,6 +21,22 @@ namespace file_manager { namespace io_task { +// Histogram name for FileBrowser.ExtractTask. +inline constexpr char kExtractTaskStatusHistogramName[] = + "FileBrowser.ExtractTask.Status"; + +// Extract archive status. These values are persisted to logs. Entries should +// not be renumbered and numeric values should never be reused. +// See enum FileManagerExtractStatus in enums.xml. +enum class ExtractStatus { + kSuccess = 0, + kUnknownError = 1, + kCancelled = 2, + kInsufficientDiskSpace = 3, + kPasswordError = 4, + kMaxValue = kPasswordError, +}; + class ExtractIOTask : public IOTask { public: // Create a task to extract any ZIP files in |source_urls|. These
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular_unittest.cc b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular_unittest.cc index 49fcffb..fddcae6 100644 --- a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular_unittest.cc +++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular_unittest.cc
@@ -243,6 +243,7 @@ easy_unlock_service_regular_->Shutdown(); PowerManagerClient::Shutdown(); TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr); + display::Screen::SetScreenInstance(nullptr); } // Most tests will want to pass `should_initialize_all_dependencies` == true,
diff --git a/chrome/browser/ash/login/screens/consolidated_consent_screen_browsertest.cc b/chrome/browser/ash/login/screens/consolidated_consent_screen_browsertest.cc index 06ceeb4..7777995 100644 --- a/chrome/browser/ash/login/screens/consolidated_consent_screen_browsertest.cc +++ b/chrome/browser/ash/login/screens/consolidated_consent_screen_browsertest.cc
@@ -104,21 +104,22 @@ // Google EUlA Dialog const test::UIPath kGoogleEulaDialog = {kConsolidatedConsentId, "googleEulaDialog"}; -const test::UIPath kGoogleEulaWebview = {kConsolidatedConsentId, - "googleEulaWebview"}; +const test::UIPath kGoogleEulaWebview = { + kConsolidatedConsentId, "consolidatedConsentGoogleEulaWebview"}; const test::UIPath kGoogleEulaOkButton = {kConsolidatedConsentId, "googleEulaOkButton"}; // CROS EULA Dialog const test::UIPath kCrosEulaDialog = {kConsolidatedConsentId, "crosEulaDialog"}; const test::UIPath kCrosEulaWebview = {kConsolidatedConsentId, - "crosEulaWebview"}; + "consolidatedConsentCrosEulaWebview"}; const test::UIPath kCrosEulaOkButton = {kConsolidatedConsentId, "crosEulaOkButton"}; // ARC ToS Dialog const test::UIPath kArcTosDialog = {kConsolidatedConsentId, "arcTosDialog"}; -const test::UIPath kArcTosWebview = {kConsolidatedConsentId, "arcTosWebview"}; +const test::UIPath kArcTosWebview = {kConsolidatedConsentId, + "consolidatedConsentArcTosWebview"}; const test::UIPath kArcTosOkButton = {kConsolidatedConsentId, "arcTosOkButton"}; // Privacy Policy Dialog
diff --git a/chrome/browser/ash/login/screens/guest_tos_screen_browsertest.cc b/chrome/browser/ash/login/screens/guest_tos_screen_browsertest.cc index f07c450..2ea88a88 100644 --- a/chrome/browser/ash/login/screens/guest_tos_screen_browsertest.cc +++ b/chrome/browser/ash/login/screens/guest_tos_screen_browsertest.cc
@@ -39,12 +39,13 @@ // Google EUlA Dialog const test::UIPath kGoogleEulaDialog = {kGuestTostId, "googleEulaDialog"}; -const test::UIPath kGoogleEulaWebview = {kGuestTostId, "googleEulaWebview"}; +const test::UIPath kGoogleEulaWebview = {kGuestTostId, + "guestTosGoogleEulaWebview"}; const test::UIPath kGoogleEulaOkButton = {kGuestTostId, "googleEulaOkButton"}; // CROS EULA Dialog const test::UIPath kCrosEulaDialog = {kGuestTostId, "crosEulaDialog"}; -const test::UIPath kCrosEulaWebview = {kGuestTostId, "crosEulaWebview"}; +const test::UIPath kCrosEulaWebview = {kGuestTostId, "guestTosCrosEulaWebview"}; const test::UIPath kCrosEulaOkButton = {kGuestTostId, "crosEulaOkButton"}; } // namespace
diff --git a/chrome/browser/ash/printing/oauth2/authorization_zone_impl.cc b/chrome/browser/ash/printing/oauth2/authorization_zone_impl.cc index 7800ccc6..808233f 100644 --- a/chrome/browser/ash/printing/oauth2/authorization_zone_impl.cc +++ b/chrome/browser/ash/printing/oauth2/authorization_zone_impl.cc
@@ -78,6 +78,18 @@ return uri.GetNormalized(false); } +// Calls `callback`. Adds a prefix with `context` to an error sent in `data`. +void PrefixForError(StatusCallback callback, + const std::string& context, + StatusCode status, + const std::string& data) { + std::string msg = data; + if (status != StatusCode::kOK) { + msg = "[" + context + "] " + data; + } + std::move(callback).Run(status, msg); +} + } // namespace AuthorizationZoneImpl::WaitingAuthorization::WaitingAuthorization( @@ -104,6 +116,7 @@ void AuthorizationZoneImpl::InitAuthorization(const std::string& scope, StatusCallback callback) { DCHECK_LE(waiting_authorizations_.size(), kMaxNumberOfSessions); + AddContextToErrorMessage(callback); // If there are too many callbacks waiting, remove the oldest one. if (waiting_authorizations_.size() == kMaxNumberOfSessions) { @@ -132,6 +145,36 @@ } } +void AuthorizationZoneImpl::FinishAuthorization(const GURL& redirect_url, + StatusCallback callback) { + AddContextToErrorMessage(callback); + // TODO(pawliczek) + // This method is supposed to parse `redirect_url`, then match + // PendingAuthorization structure using the `state` field and finalize + // the authorization on the server side by obtaining the first access token. +} + +void AuthorizationZoneImpl::GetEndpointAccessToken( + const chromeos::Uri& ipp_endpoint, + const std::string& scope, + StatusCallback callback) { + AddContextToErrorMessage(callback); + // TODO(pawliczek) + // This method is supposed to return endpoint access token for given + // `ipp_endpoint`. If the given `ipp_endpoint` is not known yet, this method + // will request from the server a new endpoint access token for given + // `ipp_endpoint` and `scope`. +} + +void AuthorizationZoneImpl::MarkEndpointAccessTokenAsExpired( + const chromeos::Uri& ipp_endpoint, + const std::string& endpoint_access_token) { + // TODO(pawliczek) + // This method removes given `ipp_endpoint` from the list of known ipp + // endpoints. It happens only if its endpoint access token equals + // `endpoint_access_token`. +} + void AuthorizationZoneImpl::AuthorizationProcedure() { DCHECK_LE(pending_authorizations_.size(), kMaxNumberOfSessions); @@ -165,6 +208,13 @@ waiting_authorizations_.clear(); } +void AuthorizationZoneImpl::AddContextToErrorMessage(StatusCallback& callback) { + // Wrap the `callback` with the function PrefixForError(...) defined above. + const std::string prefix = server_data_.AuthorizationServerURI().spec(); + auto new_call = base::BindOnce(&PrefixForError, std::move(callback), prefix); + callback = std::move(new_call); +} + std::unique_ptr<AuthorizationZone> AuthorizationZone::Create( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& authorization_server_uri,
diff --git a/chrome/browser/ash/printing/oauth2/authorization_zone_impl.h b/chrome/browser/ash/printing/oauth2/authorization_zone_impl.h index 424cfae7..f0c54a7 100644 --- a/chrome/browser/ash/printing/oauth2/authorization_zone_impl.h +++ b/chrome/browser/ash/printing/oauth2/authorization_zone_impl.h
@@ -47,15 +47,15 @@ StatusCallback callback) override; // AuthorizationZone interface. void FinishAuthorization(const GURL& redirect_url, - StatusCallback callback) override {} + StatusCallback callback) override; // AuthorizationZone interface. void GetEndpointAccessToken(const chromeos::Uri& ipp_endpoint, const std::string& scope, - StatusCallback callback) override {} + StatusCallback callback) override; // AuthorizationZone interface. void MarkEndpointAccessTokenAsExpired( const chromeos::Uri& ipp_endpoint, - const std::string& endpoint_access_token) override {} + const std::string& endpoint_access_token) override; private: // This method processes (and removes) all elements from @@ -65,6 +65,9 @@ // Callback for AuthorizationServerData::Initialize(...). void OnInitializeCallback(StatusCode status, const std::string& data); + // Adds context info to error messages returned with `callback`. + void AddContextToErrorMessage(StatusCallback& callback); + // Represents started authorization procedure waiting for opening // communication with the server. This object is created when // InitAuthorization(...) is called and its callback does not return yet.
diff --git a/chrome/browser/ash/printing/oauth2/authorization_zone_unittest.cc b/chrome/browser/ash/printing/oauth2/authorization_zone_unittest.cc index 3db414b..f21338f 100644 --- a/chrome/browser/ash/printing/oauth2/authorization_zone_unittest.cc +++ b/chrome/browser/ash/printing/oauth2/authorization_zone_unittest.cc
@@ -128,6 +128,21 @@ } } +TEST_F(PrintingOAuth2AuthorizationZoneTest, PrefixInErrorMessage) { + CallbackResult cr; + CreateAuthorizationZone(""); + + // Respond with error to Metadata Request. + authorization_zone_->InitAuthorization("", BindResult(cr)); + server_.ReceiveGET(metadata_uri_); + server_.ResponseWithJSON(net::HttpStatusCode::HTTP_INTERNAL_SERVER_ERROR, {}); + + // Check if the error message begins with the URI of the server. + EXPECT_EQ(cr.status, printing::oauth2::StatusCode::kServerError); + const std::string msg_prefix = "[" + authorization_server_uri_ + "]"; + EXPECT_EQ(cr.data.substr(0, msg_prefix.length()), msg_prefix); +} + } // namespace } // namespace oauth2 } // namespace printing
diff --git a/chrome/browser/ash/remote_apps/remote_apps_manager.cc b/chrome/browser/ash/remote_apps/remote_apps_manager.cc index 97814ab..4f41decc 100644 --- a/chrome/browser/ash/remote_apps/remote_apps_manager.cc +++ b/chrome/browser/ash/remote_apps/remote_apps_manager.cc
@@ -203,7 +203,7 @@ DCHECK_EQ(sync_pb::AppListSpecifics::TYPE_FOLDER, sync_item->item_type); remote_folder->SetMetadata( app_list::GenerateItemMetadataFromSyncItem(*sync_item)); - remote_folder->SetIsPersistent(true); + remote_folder->SetIsSystemFolder(true); app_list_syncable_service_->AddItem(std::move(remote_folder)); return; } @@ -212,7 +212,7 @@ DCHECK(model_->HasFolder(folder_id)); const RemoteAppsModel::FolderInfo& info = model_->GetFolderInfo(folder_id); remote_folder->SetChromeName(info.name); - remote_folder->SetIsPersistent(true); + remote_folder->SetIsSystemFolder(true); remote_folder->SetChromeIsFolder(true); syncer::StringOrdinal position = info.add_to_front ? model_updater_->GetPositionBeforeFirstItem()
diff --git a/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn b/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn index 8d5ce21..5beceec 100644 --- a/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn +++ b/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn
@@ -33,6 +33,7 @@ deps = [ ":window_management", + "//chrome/browser/ash/system_extensions", "//chrome/browser/web_applications:web_applications_test_support", "//chrome/test:test_support", ]
diff --git a/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc b/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc index 6ddf38a2..b29b43bc 100644 --- a/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc +++ b/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc
@@ -4,20 +4,31 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/path_service.h" #include "base/strings/strcat.h" #include "base/strings/string_piece_forward.h" #include "base/strings/stringprintf.h" #include "base/test/bind.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/ash/system_extensions/system_extensions_install_manager.h" +#include "chrome/browser/ash/system_extensions/system_extensions_provider.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h" #include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h" +#include "chrome/common/chrome_paths.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/console_message.h" +#include "content/public/browser/service_worker_context.h" +#include "content/public/browser/service_worker_context_observer.h" +#include "content/public/browser/storage_partition.h" +#include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_navigation_observer.h" @@ -27,6 +38,8 @@ namespace { +constexpr SystemExtensionId kTestSystemExtensionId = {1, 2, 3, 4}; + static constexpr char kEventListenerCode[] = R"( self.addEventListener('message', async (event) => { try { @@ -58,6 +71,60 @@ } )"; +// Used to wait for a message to get added to the Service Worker console. +// Returns the first message added to the console. +class ServiceWorkerConsoleObserver + : public content::ServiceWorkerContextObserver { + public: + ServiceWorkerConsoleObserver(Profile* profile, const GURL& scope) + : profile_(profile), scope_(scope) { + auto* worker_context = + profile->GetDefaultStoragePartition()->GetServiceWorkerContext(); + worker_context->AddObserver(this); + } + ~ServiceWorkerConsoleObserver() override = default; + + // Get the first message added to the console since the observer was + // constructed. Will wait if there are no messages yet. + const std::u16string& WaitAndGetNextConsoleMessage() { + if (!message_.has_value()) + run_loop_.Run(); + + return message_.value(); + } + + void OnReportConsoleMessage(int64_t version_id, + const GURL& scope, + const content::ConsoleMessage& message) override { + if (scope != scope_) + return; + + auto* worker_context = + profile_->GetDefaultStoragePartition()->GetServiceWorkerContext(); + worker_context->RemoveObserver(this); + + // Shouldn't happen because we unregistered as observers. + DCHECK(!message_.has_value()); + + message_ = message.message; + run_loop_.Quit(); + } + + private: + Profile* const profile_; + const GURL scope_; + + absl::optional<std::u16string> message_; + base::RunLoop run_loop_; +}; + +base::FilePath GetWindowManagerExtensionDir() { + base::FilePath test_dir; + base::PathService::Get(chrome::DIR_TEST_DATA, &test_dir); + return test_dir.Append("system_extensions") + .Append("window_manager_extension"); +} + class CrosWindowBrowserTest : public InProcessBrowserTest { public: CrosWindowBrowserTest() { @@ -129,6 +196,19 @@ base::test::ScopedFeatureList feature_list_; }; +class CrosWindowExtensionBrowserTest : public InProcessBrowserTest { + public: + CrosWindowExtensionBrowserTest() { + feature_list_.InitWithFeatures( + {features::kSystemExtensions, + ::features::kEnableServiceWorkersForChromeUntrusted}, + {}); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + } // namespace IN_PROC_BROWSER_TEST_F(CrosWindowBrowserTest, CrosWindowMoveTo) { @@ -562,4 +642,29 @@ RunTest(test_code); } +IN_PROC_BROWSER_TEST_F(CrosWindowExtensionBrowserTest, StartEvent) { + auto* provider = SystemExtensionsProvider::Get(browser()->profile()); + auto& install_manager = provider->install_manager(); + + // TODO(b/230811571): Rather than using the console to wait for the + // observer to get called, we should add support for running async functions + // to content::ServiceWorkerContext::ExecuteScriptForTest. + ServiceWorkerConsoleObserver sw_console_observer( + browser()->profile(), + GURL("chrome-untrusted://system-extension-echo-01020304/")); + + base::RunLoop run_loop; + install_manager.InstallUnpackedExtensionFromDir( + GetWindowManagerExtensionDir(), + base::BindLambdaForTesting([&](InstallStatusOrSystemExtensionId result) { + ASSERT_TRUE(result.ok()); + ASSERT_EQ(kTestSystemExtensionId, result.value()); + run_loop.Quit(); + })); + run_loop.Run(); + + EXPECT_EQ(u"start event fired", + sw_console_observer.WaitAndGetNextConsoleMessage()); +} + } // namespace ash
diff --git a/chrome/browser/ash/system_extensions/system_extensions_install_manager.cc b/chrome/browser/ash/system_extensions/system_extensions_install_manager.cc index 99a3ba1..81e4a5b 100644 --- a/chrome/browser/ash/system_extensions/system_extensions_install_manager.cc +++ b/chrome/browser/ash/system_extensions/system_extensions_install_manager.cc
@@ -25,7 +25,9 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/webui_config_map.h" #include "content/public/common/url_constants.h" +#include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/common/storage_key/storage_key.h" +#include "third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration_options.mojom.h" #include "url/gurl.h" @@ -177,6 +179,53 @@ for (auto& observer : observers_) observer.OnServiceWorkerRegistered(system_extension_id, status_code); + + auto it = system_extensions_.find(system_extension_id); + if (it == system_extensions_.end()) { + LOG(ERROR) << "Tried to start service worker for non-existent extension"; + return; + } + + const SystemExtension& system_extension = it->second; + const GURL& scope = system_extension.base_url; + + // TODO(b/221123297): Only dispatch `start` event for window manager + // system extensions. This is OK for now, because we only have window + // manager extensions. + auto* worker_context = + profile_->GetDefaultStoragePartition()->GetServiceWorkerContext(); + worker_context->StartWorkerForScope( + scope, blink::StorageKey(url::Origin::Create(scope)), + base::BindOnce( + &SystemExtensionsInstallManager::DispatchWindowManagerStartEvent, + weak_ptr_factory_.GetWeakPtr(), system_extension_id), + base::BindOnce([](blink::ServiceWorkerStatusCode status_code) { + LOG(ERROR) << "Failed to start service worker: " + << blink::ServiceWorkerStatusToString(status_code); + })); +} + +void SystemExtensionsInstallManager::DispatchWindowManagerStartEvent( + const SystemExtensionId& system_extension_id, + int64_t version_id, + int process_id, + int thread_id) { + auto it = system_extensions_.find(system_extension_id); + if (it == system_extensions_.end()) { + LOG(ERROR) << "Tried to dispatch event to service worker for " + << "non-existent extension"; + return; + } + + auto* worker_context = + profile_->GetDefaultStoragePartition()->GetServiceWorkerContext(); + auto* remote_interfaces = worker_context->GetRemoteInterfaces(version_id); + if (!remote_interfaces) + return; + + mojo::Remote<blink::mojom::CrosWindowManagementStartObserver> observer; + remote_interfaces->GetInterface(observer.BindNewPipeAndPassReceiver()); + observer->DispatchStartEvent(); } bool SystemExtensionsInstallManager::IOHelper::CopyExtensionAssets(
diff --git a/chrome/browser/ash/system_extensions/system_extensions_install_manager.h b/chrome/browser/ash/system_extensions/system_extensions_install_manager.h index cff8920..ec76073 100644 --- a/chrome/browser/ash/system_extensions/system_extensions_install_manager.h +++ b/chrome/browser/ash/system_extensions/system_extensions_install_manager.h
@@ -86,6 +86,10 @@ void RegisterServiceWorker(const SystemExtensionId& id); void OnRegisterServiceWorker(const SystemExtensionId& id, blink::ServiceWorkerStatusCode status_code); + void DispatchWindowManagerStartEvent(const SystemExtensionId& id, + int64_t version_id, + int process_id, + int thread_id); Profile* profile_;
diff --git a/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc b/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc index 90fc5b6..e6ffe0c 100644 --- a/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc +++ b/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc
@@ -45,6 +45,7 @@ #include "content/public/test/browser_test.h" #include "content/public/test/test_utils.h" #include "extensions/browser/entry_info.h" +#include "media/base/media_switches.h" #include "services/media_session/public/mojom/media_controller.mojom.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" @@ -105,6 +106,14 @@ feature_list_.InitAndEnableFeature(ash::features::kMediaAppHandlesPdf); } + void SetUpCommandLine(base::CommandLine* command_line) override { + SystemWebAppIntegrationTest::SetUpCommandLine(command_line); + + // Use a fake audio stream. Some tests make noise otherwise, and could fight + // with parallel tests for access to the audio device. + command_line->AppendSwitch(switches::kDisableAudioOutput); + } + void MediaAppLaunchWithFile(); void MediaAppWithLaunchSystemWebAppAsync(); void MediaAppEligibleOpenTask(); @@ -362,9 +371,9 @@ // Launch the App for the first time. web_app::SystemAppLaunchParams audio_params; audio_params.launch_paths.push_back(TestFile(kFilePng800x600)); - web_app::LaunchSystemWebAppAsync(browser()->profile(), - ash::SystemWebAppType::MEDIA, audio_params); - web_app::FlushSystemWebAppLaunchesForTesting(browser()->profile()); + web_app::LaunchSystemWebAppAsync(profile(), ash::SystemWebAppType::MEDIA, + audio_params); + web_app::FlushSystemWebAppLaunchesForTesting(profile()); Browser* first_browser = chrome::FindBrowserWithActiveWindow(); content::WebContents* app = PrepareActiveBrowserForTest(); @@ -373,9 +382,9 @@ // Launch the App for the second time. web_app::SystemAppLaunchParams image_params; image_params.launch_paths.push_back(TestFile(kFileJpeg640x480)); - web_app::LaunchSystemWebAppAsync(browser()->profile(), - ash::SystemWebAppType::MEDIA, image_params); - web_app::FlushSystemWebAppLaunchesForTesting(browser()->profile()); + web_app::LaunchSystemWebAppAsync(profile(), ash::SystemWebAppType::MEDIA, + image_params); + web_app::FlushSystemWebAppLaunchesForTesting(profile()); app = PrepareActiveBrowserForTest(3); Browser* second_browser = chrome::FindBrowserWithActiveWindow(); @@ -390,9 +399,9 @@ image_params.launch_paths = {TestFile(kFilePng800x600), TestFile(kFileJpeg640x480)}; - web_app::LaunchSystemWebAppAsync(browser()->profile(), - ash::SystemWebAppType::MEDIA, image_params); - web_app::FlushSystemWebAppLaunchesForTesting(browser()->profile()); + web_app::LaunchSystemWebAppAsync(profile(), ash::SystemWebAppType::MEDIA, + image_params); + web_app::FlushSystemWebAppLaunchesForTesting(profile()); const BrowserList* browser_list = BrowserList::GetInstance(); EXPECT_EQ(2u, browser_list->size()); // 1 extra for the browser test browser. @@ -409,12 +418,13 @@ web_app::SystemAppLaunchParams pdf_params; pdf_params.launch_paths = {TestFile(kFilePdfTall), TestFile(kFilePdfImg)}; - web_app::LaunchSystemWebAppAsync(browser()->profile(), - ash::SystemWebAppType::MEDIA, pdf_params); - web_app::FlushSystemWebAppLaunchesForTesting(browser()->profile()); + web_app::LaunchSystemWebAppAsync(profile(), ash::SystemWebAppType::MEDIA, + pdf_params); + web_app::FlushSystemWebAppLaunchesForTesting(profile()); + WaitForBrowserCount(3); // 1 extra for the browser test browser. const BrowserList* browser_list = BrowserList::GetInstance(); - EXPECT_EQ(3u, browser_list->size()); // 1 extra for the browser test browser. + EXPECT_EQ(3u, browser_list->size()); content::TitleWatcher watcher1( browser_list->get(1)->tab_strip_model()->GetActiveWebContents(), @@ -429,8 +439,7 @@ // Test that the Media App appears as a handler for files in the App Service. IN_PROC_BROWSER_TEST_P(MediaAppIntegrationTest, MediaAppHandlesIntents) { WaitForTestSystemAppInstall(); - auto* proxy = - apps::AppServiceProxyFactory::GetForProfile(browser()->profile()); + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile()); const std::string media_app_id = *GetManager().GetAppIdForSystemApp(ash::SystemWebAppType::MEDIA);
diff --git a/chrome/browser/chrome_browser_main_mac.mm b/chrome/browser/chrome_browser_main_mac.mm index 0cb701b8..341458a 100644 --- a/chrome/browser/chrome_browser_main_mac.mm +++ b/chrome/browser/chrome_browser_main_mac.mm
@@ -56,8 +56,7 @@ StartupData* startup_data) : ChromeBrowserMainPartsPosix(is_integration_test, startup_data) {} -ChromeBrowserMainPartsMac::~ChromeBrowserMainPartsMac() { -} +ChromeBrowserMainPartsMac::~ChromeBrowserMainPartsMac() = default; int ChromeBrowserMainPartsMac::PreEarlyInitialization() { if (base::mac::WasLaunchedAsLoginItemRestoreState()) { @@ -69,7 +68,6 @@ base::CommandLine::ForCurrentProcess(); singleton_command_line->AppendSwitch(switches::kNoStartupWindow); } - return ChromeBrowserMainPartsPosix::PreEarlyInitialization(); }
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc index 600097b..dc6f7b0 100644 --- a/chrome/browser/chrome_browser_main_win.cc +++ b/chrome/browser/chrome_browser_main_win.cc
@@ -20,6 +20,8 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/command_line.h" +#include "base/dcheck_is_on.h" +#include "base/debug/handle_hooks_win.h" #include "base/enterprise_util.h" #include "base/environment.h" #include "base/feature_list.h" @@ -44,6 +46,7 @@ #include "base/win/windows_version.h" #include "base/win/wrapped_window_proc.h" #include "build/branding_buildflags.h" +#include "build/build_config.h" #include "chrome/browser/about_flags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/enterprise/util/critical_policy_section_metrics_win.h" @@ -383,74 +386,6 @@ return true; } -// Used as the callback for ModuleWatcher events in this process. Dispatches -// them to the ModuleDatabase. -// Note: This callback may be invoked on any thread, even those not owned by the -// task scheduler, under the loader lock, directly on the thread where the -// DLL is currently loading. -void OnModuleEvent(const ModuleWatcher::ModuleEvent& event) { - { - TRACE_EVENT1("browser", "OnModuleEvent", "module_path", - event.module_path.BaseName().AsUTF8Unsafe()); - - switch (event.event_type) { - case ModuleWatcher::ModuleEventType::kModuleAlreadyLoaded: { - // kModuleAlreadyLoaded comes from the enumeration of loaded modules - // using CreateToolhelp32Snapshot(). - uint32_t time_date_stamp = 0; - if (TryGetModuleTimeDateStamp(event.module_load_address, - event.module_path, event.module_size, - &time_date_stamp)) { - ModuleDatabase::HandleModuleLoadEvent( - content::PROCESS_TYPE_BROWSER, event.module_path, - event.module_size, time_date_stamp); - } else { - // Failed to get the TimeDateStamp directly from memory. The next step - // to try is to read the file on disk. This must be done in a blocking - // task. - base::ThreadPool::PostTask( - FROM_HERE, - {base::MayBlock(), base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, - base::BindOnce(&HandleModuleLoadEventWithoutTimeDateStamp, - event.module_path, event.module_size)); - } - break; - } - case ModuleWatcher::ModuleEventType::kModuleLoaded: { - ModuleDatabase::HandleModuleLoadEvent( - content::PROCESS_TYPE_BROWSER, event.module_path, event.module_size, - GetModuleTimeDateStamp(event.module_load_address)); - break; - } - } - } - // Since OnModuleEvent can be invoked from any thread, the above trace event's - // END might be the last event on this thread, emit an empty event to force - // the END to be flushed. TODO(crbug.com/1021571): Remove this once fixed. - PERFETTO_INTERNAL_ADD_EMPTY_EVENT(); -} - -// Helper function for initializing the module database subsystem and populating -// the provided |module_watcher|. -void SetupModuleDatabase(std::unique_ptr<ModuleWatcher>* module_watcher) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(module_watcher); - - bool third_party_blocking_policy_enabled = -#if BUILDFLAG(GOOGLE_CHROME_BRANDING) - ModuleDatabase::IsThirdPartyBlockingPolicyEnabled(); -#else - false; -#endif - - ModuleDatabase::GetTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(&InitializeModuleDatabase, - third_party_blocking_policy_enabled)); - - *module_watcher = ModuleWatcher::Create(base::BindRepeating(&OnModuleEvent)); -} - void ShowCloseBrowserFirstMessageBox() { chrome::ShowWarningMessageBox( nullptr, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), @@ -663,6 +598,18 @@ .get()); #endif +#if DCHECK_IS_ON() + // Patching EAT of kernel32.dll is only supported on 32-bit because RVA can + // only hold 32-bit values. +#if defined(ARCH_CPU_32_BITS) + base::debug::HandleHooks::AddEATPatch(); +#endif + // Patch currently loaded modules. Future ones will get patched by the module + // watcher. Note: if any modules load between now and when SetupModuleDatabase + // is called then these will be missed. + base::debug::HandleHooks::PatchLoadedModules(); +#endif // DCHECK_IS_ON() + // Create the module database and hook up the in-process module watcher. This // needs to be done before any child processes are initialized as the // ModuleDatabase is an endpoint for IPC from child processes. @@ -934,3 +881,82 @@ // duplicates, perhaps harmonize with switches::RemoveSwitchesForAutostart. return restart_command; } + +// Used as the callback for ModuleWatcher events in this process. Dispatches +// them to the ModuleDatabase. +// Note: This callback may be invoked on any thread, even those not owned by the +// task scheduler, under the loader lock, directly on the thread where the +// DLL is currently loading. +void ChromeBrowserMainPartsWin::OnModuleEvent( + const ModuleWatcher::ModuleEvent& event) { + { + TRACE_EVENT1("browser", "OnModuleEvent", "module_path", + event.module_path.BaseName().AsUTF8Unsafe()); + + switch (event.event_type) { + case ModuleWatcher::ModuleEventType::kModuleAlreadyLoaded: { + // kModuleAlreadyLoaded comes from the enumeration of loaded modules + // using CreateToolhelp32Snapshot(). + uint32_t time_date_stamp = 0; + if (TryGetModuleTimeDateStamp(event.module_load_address, + event.module_path, event.module_size, + &time_date_stamp)) { + ModuleDatabase::HandleModuleLoadEvent( + content::PROCESS_TYPE_BROWSER, event.module_path, + event.module_size, time_date_stamp); + } else { + // Failed to get the TimeDateStamp directly from memory. The next step + // to try is to read the file on disk. This must be done in a blocking + // task. + base::ThreadPool::PostTask( + FROM_HERE, + {base::MayBlock(), base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, + base::BindOnce(&HandleModuleLoadEventWithoutTimeDateStamp, + event.module_path, event.module_size)); + } + break; + } + case ModuleWatcher::ModuleEventType::kModuleLoaded: { +#if DCHECK_IS_ON() && defined(ARCH_CPU_64_BITS) + // This is only needed on 64-bit because on 32-bit the EAT from kernel32 + // is already patched. This is thread safe against itself as this is + // always called under loader lock. + HMODULE module = + reinterpret_cast<HMODULE>(event.module_load_address.get()); + base::debug::HandleHooks::AddIATPatch(module); +#endif // DCHECK_IS_ON() && defined(ARCH_CPU_64_BITS) + ModuleDatabase::HandleModuleLoadEvent( + content::PROCESS_TYPE_BROWSER, event.module_path, event.module_size, + GetModuleTimeDateStamp(event.module_load_address)); + break; + } + } + } + // Since OnModuleEvent can be invoked from any thread, the above trace event's + // END might be the last event on this thread, emit an empty event to force + // the END to be flushed. TODO(crbug.com/1021571): Remove this once fixed. + PERFETTO_INTERNAL_ADD_EMPTY_EVENT(); +} + +// Helper function for initializing the module database subsystem and populating +// the provided |module_watcher|. +void ChromeBrowserMainPartsWin::SetupModuleDatabase( + std::unique_ptr<ModuleWatcher>* module_watcher) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(module_watcher); + + bool third_party_blocking_policy_enabled = +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + ModuleDatabase::IsThirdPartyBlockingPolicyEnabled(); +#else + false; +#endif + + ModuleDatabase::GetTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&InitializeModuleDatabase, + third_party_blocking_policy_enabled)); + + *module_watcher = ModuleWatcher::Create(base::BindRepeating( + &ChromeBrowserMainPartsWin::OnModuleEvent, base::Unretained(this))); +}
diff --git a/chrome/browser/chrome_browser_main_win.h b/chrome/browser/chrome_browser_main_win.h index 66bcce9..87e802df 100644 --- a/chrome/browser/chrome_browser_main_win.h +++ b/chrome/browser/chrome_browser_main_win.h
@@ -10,8 +10,7 @@ #include <memory> #include "chrome/browser/chrome_browser_main.h" - -class ModuleWatcher; +#include "chrome/common/conflicts/module_watcher_win.h" namespace base { class CommandLine; @@ -77,6 +76,9 @@ const base::CommandLine& command_line); private: + void OnModuleEvent(const ModuleWatcher::ModuleEvent& event); + void SetupModuleDatabase(std::unique_ptr<ModuleWatcher>* module_watcher); + // Watches module load events and forwards them to the ModuleDatabase. std::unique_ptr<ModuleWatcher> module_watcher_; };
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 357182f7..99660dd1 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -343,6 +343,7 @@ #include "chrome/browser/browser_process_platform_part_mac.h" #include "chrome/browser/chrome_browser_main_mac.h" #include "chrome/browser/mac/auth_session_request.h" +#include "chrome/browser/mac/chrome_browser_main_extra_parts_mac.h" #include "components/soda/constants.h" #include "sandbox/mac/seatbelt_exec.h" #include "sandbox/policy/mac/params.h" @@ -1453,6 +1454,10 @@ #endif #endif +#if BUILDFLAG(IS_MAC) + main_parts->AddParts(std::make_unique<ChromeBrowserMainExtraPartsMac>()); +#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) // TODO(jamescook): Combine with `ChromeBrowserMainPartsAsh`. main_parts->AddParts(std::make_unique<ChromeBrowserMainExtraPartsAsh>());
diff --git a/chrome/browser/dev_ui_browser_resources.grd b/chrome/browser/dev_ui_browser_resources.grd index 255ca4b9..4889cf9 100644 --- a/chrome/browser/dev_ui_browser_resources.grd +++ b/chrome/browser/dev_ui_browser_resources.grd
@@ -35,7 +35,7 @@ <include name="IDR_LOCAL_STATE_HTML" file="resources\local_state\local_state.html" type="BINDATA" /> <include name="IDR_LOCAL_STATE_JS" file="${root_gen_dir}\chrome\browser\resources\local_state\local_state.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_MEMORY_INTERNALS_HTML" file="resources\memory_internals\memory_internals.html" type="BINDATA" /> - <include name="IDR_MEMORY_INTERNALS_JS" file="resources\memory_internals\memory_internals.js" type="BINDATA" /> + <include name="IDR_MEMORY_INTERNALS_JS" file="${root_gen_dir}\chrome\browser\resources\memory_internals\tsc\memory_internals.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PREDICTORS_AUTOCOMPLETE_ACTION_PREDICTOR_JS" file="${root_gen_dir}\chrome\browser\resources\predictors\autocomplete_action_predictor.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PREDICTORS_HTML" file="resources\predictors\predictors.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_PREDICTORS_JS" file="${root_gen_dir}\chrome\browser\resources\predictors\predictors.js" use_base_dir="false" type="BINDATA" />
diff --git a/chrome/browser/devtools/devtools_browsertest.cc b/chrome/browser/devtools/devtools_browsertest.cc index b9c1c70..4b8fec7 100644 --- a/chrome/browser/devtools/devtools_browsertest.cc +++ b/chrome/browser/devtools/devtools_browsertest.cc
@@ -2963,7 +2963,7 @@ const auto result = FetchFromDevToolsWindow("http://www.google.com"); EXPECT_THAT(result.error, ::testing::StartsWith( - "a JavaScript error:\nTypeError: Failed to fetch\n")); + "a JavaScript error: \"TypeError: Failed to fetch\n")); CloseDevToolsWindow(); } @@ -2976,7 +2976,7 @@ "devtools://devtools/bundled/devtools_compatibility.js"); EXPECT_THAT(result.error, ::testing::StartsWith( - "a JavaScript error:\nTypeError: Failed to fetch\n")); + "a JavaScript error: \"TypeError: Failed to fetch\n")); } IN_PROC_BROWSER_TEST_F(DevToolsTest, HostBindingsSyncIntegration) {
diff --git a/chrome/browser/download/download_prefs_unittest.cc b/chrome/browser/download/download_prefs_unittest.cc index ba12c18..a94ed196 100644 --- a/chrome/browser/download/download_prefs_unittest.cc +++ b/chrome/browser/download/download_prefs_unittest.cc
@@ -500,9 +500,12 @@ account_id.GetAccountIdKey())); const base::FilePath ash_resources_dir = base::FilePath("/opt/google/chrome"); base::FilePath share_cache_dir = profile.GetPath().AppendASCII("ShareCache"); + base::FilePath preinstalled_web_app_config_dir; + base::FilePath preinstalled_web_app_extra_config_dir; chrome::SetLacrosDefaultPaths( documents_path, default_dir, drivefs_dir, removable_media_dir, - android_files_dir, linux_files_dir, ash_resources_dir, share_cache_dir); + android_files_dir, linux_files_dir, ash_resources_dir, share_cache_dir, + preinstalled_web_app_config_dir, preinstalled_web_app_extra_config_dir); #endif // Test a valid subdirectory of downloads.
diff --git a/chrome/browser/drive/OWNERS b/chrome/browser/drive/OWNERS index 2563657..73220a8 100644 --- a/chrome/browser/drive/OWNERS +++ b/chrome/browser/drive/OWNERS
@@ -1,5 +1 @@ -hashimoto@chromium.org -hidehiko@chromium.org -hirono@chromium.org -kinaba@chromium.org -yoshiki@chromium.org +file://ui/file_manager/OWNERS
diff --git a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_browsertest.cc b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_browsertest.cc index c87fec7..fc750c7 100644 --- a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_browsertest.cc +++ b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_browsertest.cc
@@ -115,7 +115,7 @@ content::EvalJs(FrameToUseForConnecting(), script); EXPECT_THAT( result.error, - testing::StartsWith("a JavaScript error:\nTypeError: Cannot read " + testing::StartsWith("a JavaScript error: \"TypeError: Cannot read " "properties of undefined (reading 'connect')")); }
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc index 2020979..6e8acc6f5 100644 --- a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
@@ -1081,7 +1081,8 @@ api::enterprise_reporting_private::EventType::EVENT_TYPE_USER; std::unique_ptr<base::ListValue> params = std::make_unique<base::ListValue>(); - params->Append(enqueue_record_request.ToValue()); + params->Append( + base::Value::FromUniquePtrValue(enqueue_record_request.ToValue())); // Set up DM token policy::SetDMTokenForTesting( @@ -1108,7 +1109,8 @@ api::enterprise_reporting_private::EventType::EVENT_TYPE_USER; std::unique_ptr<base::ListValue> params = std::make_unique<base::ListValue>(); - params->Append(enqueue_record_request.ToValue()); + params->Append( + base::Value::FromUniquePtrValue(enqueue_record_request.ToValue())); policy::SetDMTokenForTesting( policy::DMToken::CreateValidTokenForTesting(kTestDMTokenValue)); @@ -1136,7 +1138,8 @@ api::enterprise_reporting_private::EventType::EVENT_TYPE_USER; std::unique_ptr<base::ListValue> params = std::make_unique<base::ListValue>(); - params->Append(enqueue_record_request.ToValue()); + params->Append( + base::Value::FromUniquePtrValue(enqueue_record_request.ToValue())); policy::SetDMTokenForTesting( policy::DMToken::CreateValidTokenForTesting(kTestDMTokenValue)); @@ -1161,7 +1164,8 @@ api::enterprise_reporting_private::EventType::EVENT_TYPE_USER; std::unique_ptr<base::ListValue> params = std::make_unique<base::ListValue>(); - params->Append(enqueue_record_request.ToValue()); + params->Append( + base::Value::FromUniquePtrValue(enqueue_record_request.ToValue())); // Set up invalid DM token policy::SetDMTokenForTesting(policy::DMToken::CreateInvalidTokenForTesting());
diff --git a/chrome/browser/extensions/api/search/search_api_unittest.cc b/chrome/browser/extensions/api/search/search_api_unittest.cc index baeaee9..3e69925 100644 --- a/chrome/browser/extensions/api/search/search_api_unittest.cc +++ b/chrome/browser/extensions/api/search/search_api_unittest.cc
@@ -15,8 +15,6 @@ #include "content/public/test/web_contents_tester.h" #include "extensions/browser/api_test_utils.h" #include "extensions/common/extension_builder.h" -#include "ui/display/test/scoped_screen_override.h" -#include "ui/display/test/test_screen.h" namespace extensions { @@ -74,8 +72,6 @@ std::unique_ptr<TestBrowserWindow> browser_window_; std::unique_ptr<Browser> browser_; - display::test::TestScreen test_screen_; - std::unique_ptr<display::test::ScopedScreenOverride> scoped_screen_override_; scoped_refptr<extensions::SearchQueryFunction> function_; }; @@ -91,8 +87,6 @@ params.type = Browser::TYPE_NORMAL; params.window = browser_window_.get(); browser_ = std::unique_ptr<Browser>(Browser::Create(params)); - scoped_screen_override_ = - std::make_unique<display::test::ScopedScreenOverride>(&test_screen_); // Mock TemplateURLService. auto* template_url_service = static_cast<TemplateURLService*>(
diff --git a/chrome/browser/extensions/api/system_display/system_display_extension_apitest.cc b/chrome/browser/extensions/api/system_display/system_display_extension_apitest.cc index a42a5749..837d0bd 100644 --- a/chrome/browser/extensions/api/system_display/system_display_extension_apitest.cc +++ b/chrome/browser/extensions/api/system_display/system_display_extension_apitest.cc
@@ -15,16 +15,11 @@ #include "extensions/browser/api/system_display/system_display_api.h" #include "extensions/browser/api_test_utils.h" #include "extensions/browser/mock_display_info_provider.h" -#include "extensions/browser/mock_screen.h" #include "extensions/common/api/system_display.h" #include "ui/display/display.h" -#include "ui/display/screen.h" -#include "ui/display/test/scoped_screen_override.h" namespace extensions { -using display::Screen; -using display::test::ScopedScreenOverride; using ContextType = ExtensionBrowserTest::ContextType; class SystemDisplayExtensionApiTest @@ -39,27 +34,19 @@ void SetUpOnMainThread() override { ExtensionApiTest::SetUpOnMainThread(); - ANNOTATE_LEAKING_OBJECT_PTR(Screen::GetScreen()); - scoped_screen_override_ = - std::make_unique<ScopedScreenOverride>(screen_.get()); DisplayInfoProvider::InitializeForTesting(provider_.get()); } void TearDownOnMainThread() override { ExtensionApiTest::TearDownOnMainThread(); - scoped_screen_override_.reset(); } protected: std::unique_ptr<MockDisplayInfoProvider> provider_ = std::make_unique<MockDisplayInfoProvider>(); - - private: - std::unique_ptr<Screen> screen_ = std::make_unique<MockScreen>(); - std::unique_ptr<ScopedScreenOverride> scoped_screen_override_; }; -// TODO(crbug.com/1231357): MockScreen causes random failures on Windows. +// TODO(crbug.com/1231357): Revisit this after screen creation refactoring. #if !BUILDFLAG(IS_WIN) INSTANTIATE_TEST_SUITE_P(PersistentBackground,
diff --git a/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc b/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc index 005577b..7154cba7 100644 --- a/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc +++ b/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
@@ -33,8 +33,6 @@ #include "extensions/common/constants.h" #include "extensions/common/extension_builder.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "ui/display/test/scoped_screen_override.h" -#include "ui/display/test/test_screen.h" #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/test/ash_test_helper.h" @@ -48,8 +46,6 @@ namespace extensions { -using display::test::ScopedScreenOverride; - namespace { std::unique_ptr<base::ListValue> RunTabsQueryFunction( @@ -127,13 +123,15 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) ash::AshTestHelper test_helper_; -#else - display::test::TestScreen test_screen_; - std::unique_ptr<ScopedScreenOverride> scoped_screen_override_; #endif }; void TabsApiUnitTest::SetUp() { +#if BUILDFLAG(IS_CHROMEOS_ASH) + ash::AshTestHelper::InitParams ash_params; + ash_params.start_session = true; + test_helper_.SetUp(std::move(ash_params)); +#endif // Force TabManager/TabLifecycleUnitSource creation. g_browser_process->GetTabManager(); @@ -145,14 +143,6 @@ params.type = Browser::TYPE_NORMAL; params.window = browser_window_.get(); browser_.reset(Browser::Create(params)); -#if BUILDFLAG(IS_CHROMEOS_ASH) - ash::AshTestHelper::InitParams ash_params; - ash_params.start_session = true; - test_helper_.SetUp(std::move(ash_params)); -#else - scoped_screen_override_ = - std::make_unique<ScopedScreenOverride>(&test_screen_); -#endif } void TabsApiUnitTest::TearDown() {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 6172728..723193a 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -779,16 +779,6 @@ "expiry_milestone": -1 }, { - "name": "certificate-transparency-2022-policy", - "owners": [ "carlosil", "asymmetric", "trusty-transport@chromium.org" ], - "expiry_milestone": 102 - }, - { - "name": "certificate-transparency-2022-policy-all-certs", - "owners": [ "carlosil", "asymmetric", "trusty-transport@chromium.org" ], - "expiry_milestone": 102 - }, - { "name": "check-offline-capability", "owners": [ "asamidoi", "//content/browser/service_worker/OWNERS" ], "expiry_milestone": 93 @@ -5382,6 +5372,11 @@ "expiry_milestone": 105 }, { + "name": "shared-highlighting-refined-maxcontextwords", + "owners": ["wissemgamra", "jeffreycohen", "chrome-with-friends-robots@google.com" ], + "expiry_milestone": 107 + }, + { "name": "shared-highlighting-v2", "owners": ["jeffreycohen", "kristipark", "cheickcisse@google.com", "chrome-with-friends-robots@google.com"], "expiry_milestone": 99
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 0fa48525..bad7bf8 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -576,24 +576,6 @@ "eligibility requirements for showing app banners, such as having a " "manifest, are met."; -const char kCertificateTransparency2022PolicyName[] = - "Certificate Transparency 2022 Policy"; -const char kCertificateTransparency2022PolicyDescription[] = - "Enables the 2022 policy for Certificate Transparency requirements for " - "certificates issued after April 15, 2022. This policy increases the " - "number of SCTs required for certificates with a lifetime over 180 days, " - "and replaces the one Google log requirement with log operator diversity " - "requirements."; - -const char kCertificateTransparency2022PolicyAllCertsName[] = - "Certificate Transparency 2022 Policy All Certificates"; -const char kCertificateTransparency2022PolicyAllCertsDescription[] = - "Enables the 2022 policy for Certificate Transparency requirements for " - "all certificates regardless of issuance date. This policy increases the " - "number of SCTs required for certificates with a lifetime over 180 days, " - "and replaces the one Google log requirement with log operator diversity " - "requirements."; - const char kCheckOfflineCapabilityName[] = "Check offline capability for PWAs"; const char kCheckOfflineCapabilityDescription[] = "Use advanced offline capability check to decide whether the browser " @@ -2918,6 +2900,11 @@ const char kSharedHighlightingRefinedBlocklistDescription[] = "Narrow the Blocklist for enabling Shared Highlighting."; +const char kSharedHighlightingRefinedMaxContextWordsName[] = + "Shared Highlighting Max Context Words Refinement"; +const char kSharedHighlightingRefinedMaxContextWordsDescription[] = + "Experiment with different Max Context Words for Shared Highlighting."; + const char kDraw1PredictedPoint12Ms[] = "1 point 12ms ahead."; const char kDraw2PredictedPoints6Ms[] = "2 points, each 6ms ahead."; const char kDraw1PredictedPoint6Ms[] = "1 point 6ms ahead.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 6a2f7b0..99908d28 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -319,12 +319,6 @@ extern const char kCanvasOopRasterizationName[]; extern const char kCanvasOopRasterizationDescription[]; -extern const char kCertificateTransparency2022PolicyName[]; -extern const char kCertificateTransparency2022PolicyDescription[]; - -extern const char kCertificateTransparency2022PolicyAllCertsName[]; -extern const char kCertificateTransparency2022PolicyAllCertsDescription[]; - extern const char kCheckOfflineCapabilityName[]; extern const char kCheckOfflineCapabilityDescription[]; @@ -1640,6 +1634,9 @@ extern const char kSharedHighlightingRefinedBlocklistName[]; extern const char kSharedHighlightingRefinedBlocklistDescription[]; +extern const char kSharedHighlightingRefinedMaxContextWordsName[]; +extern const char kSharedHighlightingRefinedMaxContextWordsDescription[]; + extern const char kDraw1PredictedPoint12Ms[]; extern const char kDraw2PredictedPoints6Ms[]; extern const char kDraw1PredictedPoint6Ms[];
diff --git a/chrome/browser/mac/chrome_browser_main_extra_parts_mac.h b/chrome/browser/mac/chrome_browser_main_extra_parts_mac.h new file mode 100644 index 0000000..6f2faad --- /dev/null +++ b/chrome/browser/mac/chrome_browser_main_extra_parts_mac.h
@@ -0,0 +1,32 @@ +// Copyright 2022 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_MAC_CHROME_BROWSER_MAIN_EXTRA_PARTS_MAC_H_ +#define CHROME_BROWSER_MAC_CHROME_BROWSER_MAIN_EXTRA_PARTS_MAC_H_ + +#include <memory> + +#include "chrome/browser/chrome_browser_main_extra_parts.h" + +namespace display { +class ScopedNativeScreen; +} + +class ChromeBrowserMainExtraPartsMac : public ChromeBrowserMainExtraParts { + public: + ChromeBrowserMainExtraPartsMac(); + ChromeBrowserMainExtraPartsMac(const ChromeBrowserMainExtraPartsMac&) = + delete; + ChromeBrowserMainExtraPartsMac& operator=( + const ChromeBrowserMainExtraPartsMac&) = delete; + ~ChromeBrowserMainExtraPartsMac() override; + + // ChromeBrowserMainExtraParts: + void PreEarlyInitialization() override; + + private: + std::unique_ptr<display::ScopedNativeScreen> screen_; +}; + +#endif // CHROME_BROWSER_MAC_CHROME_BROWSER_MAIN_EXTRA_PARTS_MAC_H_
diff --git a/chrome/browser/mac/chrome_browser_main_extra_parts_mac.mm b/chrome/browser/mac/chrome_browser_main_extra_parts_mac.mm new file mode 100644 index 0000000..3094e1f --- /dev/null +++ b/chrome/browser/mac/chrome_browser_main_extra_parts_mac.mm
@@ -0,0 +1,14 @@ +// Copyright 2022 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/mac/chrome_browser_main_extra_parts_mac.h" + +#include "ui/display/screen.h" + +ChromeBrowserMainExtraPartsMac::ChromeBrowserMainExtraPartsMac() = default; +ChromeBrowserMainExtraPartsMac::~ChromeBrowserMainExtraPartsMac() = default; + +void ChromeBrowserMainExtraPartsMac::PreEarlyInitialization() { + screen_ = std::make_unique<display::ScopedNativeScreen>(); +}
diff --git a/chrome/browser/metrics/usage_scenario/tab_usage_scenario_tracker_unittest.cc b/chrome/browser/metrics/usage_scenario/tab_usage_scenario_tracker_unittest.cc index 310c743..dcb59b0 100644 --- a/chrome/browser/metrics/usage_scenario/tab_usage_scenario_tracker_unittest.cc +++ b/chrome/browser/metrics/usage_scenario/tab_usage_scenario_tracker_unittest.cc
@@ -40,17 +40,16 @@ delete; void SetUp() override { + display::Screen::SetScreenInstance(&screen_); ChromeRenderViewHostTestHarness::SetUp(); - previous_screen_ = display::Screen::SetScreenInstance(&screen_); tab_usage_scenario_tracker_ = std::make_unique<TabUsageScenarioTracker>(&usage_scenario_data_store_); } void TearDown() override { tab_usage_scenario_tracker_.reset(); - display::Screen::SetScreenInstance(previous_screen_); - previous_screen_ = nullptr; ChromeRenderViewHostTestHarness::TearDown(); + display::Screen::SetScreenInstance(nullptr); } std::unique_ptr<content::WebContents> CreateWebContents() { @@ -83,7 +82,6 @@ protected: display::test::TestScreen screen_; - raw_ptr<display::Screen> previous_screen_; UsageScenarioDataStoreImpl usage_scenario_data_store_; std::unique_ptr<TabUsageScenarioTracker> tab_usage_scenario_tracker_; ukm::TestAutoSetUkmRecorder ukm_recorder_;
diff --git a/chrome/browser/policy/messaging_layer/public/report_client.cc b/chrome/browser/policy/messaging_layer/public/report_client.cc index b26d082e..28c7ddd 100644 --- a/chrome/browser/policy/messaging_layer/public/report_client.cc +++ b/chrome/browser/policy/messaging_layer/public/report_client.cc
@@ -77,8 +77,7 @@ class ReportingClient::Uploader : public UploaderInterface { public: using UploadCallback = - base::OnceCallback<Status(bool, - std::unique_ptr<std::vector<EncryptedRecord>>)>; + base::OnceCallback<Status(bool, std::vector<EncryptedRecord>)>; static std::unique_ptr<Uploader> Create(bool need_encryption_key, UploadCallback upload_callback) { @@ -123,7 +122,7 @@ private: bool completed_{false}; const bool need_encryption_key_; - std::unique_ptr<std::vector<EncryptedRecord>> encrypted_records_; + std::vector<EncryptedRecord> encrypted_records_; UploadCallback upload_callback_; }; @@ -140,7 +139,6 @@ bool need_encryption_key, ReportingClient::Uploader::UploadCallback upload_callback) : need_encryption_key_(need_encryption_key), - encrypted_records_(std::make_unique<std::vector<EncryptedRecord>>()), upload_callback_(std::move(upload_callback)) {} void ReportingClient::Uploader::Helper::ProcessRecord( @@ -150,7 +148,7 @@ std::move(processed_cb).Run(false); return; } - encrypted_records_->emplace_back(std::move(data)); + encrypted_records_.emplace_back(std::move(data)); std::move(processed_cb).Run(true); } @@ -163,8 +161,8 @@ return; } for (uint64_t i = 0; i < count; ++i) { - encrypted_records_->emplace_back(); - *encrypted_records_->rbegin()->mutable_sequence_information() = start; + encrypted_records_.emplace_back(); + *encrypted_records_.rbegin()->mutable_sequence_information() = start; start.set_sequencing_id(start.sequencing_id() + 1); } std::move(processed_cb).Run(true); @@ -181,8 +179,7 @@ return; } completed_ = true; - DCHECK(encrypted_records_); - if (encrypted_records_->empty() && !need_encryption_key_) { + if (encrypted_records_.empty() && !need_encryption_key_) { return; } DCHECK(upload_callback_); @@ -344,7 +341,7 @@ base::BindOnce( [](EncryptedReportingUploadProvider* upload_provider, bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records) { + std::vector<EncryptedRecord> records) { upload_provider->RequestUploadEncryptedRecords( need_encryption_key, std::move(records), base::DoNothing());
diff --git a/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.cc b/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.cc index 0a8e97d..9c739d9 100644 --- a/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.cc +++ b/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.cc
@@ -70,7 +70,7 @@ DmServerUploader::DmServerUploader( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, RecordHandler* handler, ReportSuccessfulUploadCallback report_success_upload_cb, EncryptionKeyAttachedCallback encryption_key_attached_cb, @@ -95,13 +95,13 @@ return; } // Early exit if we don't have any records and do not need encryption key. - if (encrypted_records_->empty() && !need_encryption_key_) { + if (encrypted_records_.empty() && !need_encryption_key_) { Complete( Status(error::INVALID_ARGUMENT, "No records received for upload.")); return; } - if (!encrypted_records_->empty()) { + if (!encrypted_records_.empty()) { ProcessRecords(); } @@ -113,13 +113,13 @@ Status process_status; const int64_t expected_generation_id = - encrypted_records_->front().sequence_information().generation_id(); + encrypted_records_.front().sequence_information().generation_id(); int64_t expected_sequencing_id = - encrypted_records_->front().sequence_information().sequencing_id(); + encrypted_records_.front().sequence_information().sequencing_id(); // Will stop processing records on the first record that fails to pass. size_t records_added = 0; - for (const EncryptedRecord& encrypted_record : *encrypted_records_) { + for (const auto& encrypted_record : encrypted_records_) { process_status = IsRecordValid(encrypted_record, expected_generation_id, expected_sequencing_id); if (!process_status.ok()) { @@ -136,7 +136,7 @@ } // Discarding the remaining records. - encrypted_records_->resize(records_added); + encrypted_records_.resize(records_added); } void DmServerUploader::HandleRecords() { @@ -205,7 +205,7 @@ Status DmServerUploadService::EnqueueUpload( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, ReportSuccessfulUploadCallback report_upload_success_cb, EncryptionKeyAttachedCallback encryption_key_attached_cb) { Start<DmServerUploader>(need_encryption_key, std::move(records),
diff --git a/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.h b/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.h index 3f181f3..0cbc02f 100644 --- a/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.h +++ b/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.h
@@ -80,7 +80,7 @@ // Any errors will result in |upload_complete| being called with a Status. virtual void HandleRecords( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, DmServerUploadService::CompletionCallback upload_complete, DmServerUploadService::EncryptionKeyAttachedCallback encryption_key_attached_cb) = 0; @@ -100,7 +100,7 @@ public: DmServerUploader( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, RecordHandler* handler, ReportSuccessfulUploadCallback report_success_upload_cb, EncryptionKeyAttachedCallback encryption_key_attached_cb, @@ -135,7 +135,7 @@ const int64_t expected_sequencing_id) const; const bool need_encryption_key_; - std::unique_ptr<std::vector<EncryptedRecord>> encrypted_records_; + std::vector<EncryptedRecord> encrypted_records_; const ReportSuccessfulUploadCallback report_success_upload_cb_; const EncryptionKeyAttachedCallback encryption_key_attached_cb_; raw_ptr<RecordHandler> handler_; @@ -161,7 +161,7 @@ Status EnqueueUpload( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, ReportSuccessfulUploadCallback report_upload_success_cb, EncryptionKeyAttachedCallback encryption_key_attached_cb);
diff --git a/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service_unittest.cc b/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service_unittest.cc index 120ebff9..847880e 100644 --- a/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service_unittest.cc +++ b/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service_unittest.cc
@@ -51,7 +51,7 @@ ~TestRecordHandler() override = default; void HandleRecords(bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, DmServerUploadService::CompletionCallback upload_complete, DmServerUploadService::EncryptionKeyAttachedCallback encryption_key_attached_cb) override { @@ -62,7 +62,7 @@ MOCK_METHOD(void, HandleRecords_, (bool, - std::unique_ptr<std::vector<EncryptedRecord>>&, + std::vector<EncryptedRecord>&, DmServerUploadService::CompletionCallback, DmServerUploadService::EncryptionKeyAttachedCallback)); }; @@ -71,8 +71,7 @@ public: DmServerTest() : sequenced_task_runner_(base::ThreadPool::CreateSequencedTaskRunner({})), - handler_(std::make_unique<TestRecordHandler>()), - records_(std::make_unique<std::vector<EncryptedRecord>>()) {} + handler_(std::make_unique<TestRecordHandler>()) {} protected: content::BrowserTaskEnvironment task_envrionment_{ @@ -81,7 +80,7 @@ scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; std::unique_ptr<TestRecordHandler> handler_; - std::unique_ptr<std::vector<EncryptedRecord>> records_; + std::vector<EncryptedRecord> records_; const base::TimeDelta kMaxDelay_ = base::Seconds(1); }; @@ -105,7 +104,7 @@ TEST_P(DmServerUploaderTest, ProcessesRecord) { // Add an empty record. - records_->emplace_back(); + records_.emplace_back(); const bool force_confirm_flag = force_confirm(); EXPECT_CALL(*handler_, HandleRecords_(_, _, _, _)) @@ -157,7 +156,7 @@ sequence_information->set_generation_id(kGenerationId); sequence_information->set_sequencing_id(i); sequence_information->set_priority(Priority::IMMEDIATE); - records_->push_back(std::move(encrypted_record)); + records_.push_back(std::move(encrypted_record)); } const bool force_confirm_flag = force_confirm(); @@ -199,7 +198,7 @@ TEST_P(DmServerUploaderTest, ReportsFailureToProcess) { // Add an empty record. - records_->emplace_back(); + records_.emplace_back(); EXPECT_CALL(*handler_, HandleRecords_(_, _, _, _)) .WillOnce(WithArgs<2>( @@ -281,7 +280,7 @@ TEST_P(DmServerFailureTest, ReportsFailureToUpload) { const error::Code& error_code = GetParam(); // Add an empty record. - records_->emplace_back(); + records_.emplace_back(); EXPECT_CALL(*handler_, HandleRecords_(_, _, _, _)) .WillOnce(WithArgs<2>(Invoke(
diff --git a/chrome/browser/policy/messaging_layer/upload/fake_upload_client.cc b/chrome/browser/policy/messaging_layer/upload/fake_upload_client.cc index 7907579..9fdada4f 100644 --- a/chrome/browser/policy/messaging_layer/upload/fake_upload_client.cc +++ b/chrome/browser/policy/messaging_layer/upload/fake_upload_client.cc
@@ -93,11 +93,11 @@ Status FakeUploadClient::EnqueueUpload( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, ReportSuccessfulUploadCallback report_upload_success_cb, EncryptionKeyAttachedCallback encryption_key_attached_cb) { UploadEncryptedReportingRequestBuilder builder; - for (auto record : *records) { + for (auto record : records) { builder.AddRecord((std::move(record))); } auto request_result = builder.Build();
diff --git a/chrome/browser/policy/messaging_layer/upload/fake_upload_client.h b/chrome/browser/policy/messaging_layer/upload/fake_upload_client.h index 0baaf615..885ae03 100644 --- a/chrome/browser/policy/messaging_layer/upload/fake_upload_client.h +++ b/chrome/browser/policy/messaging_layer/upload/fake_upload_client.h
@@ -22,7 +22,7 @@ Status EnqueueUpload( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, ReportSuccessfulUploadCallback report_upload_success_cb, EncryptionKeyAttachedCallback encryption_key_attached_cb) override;
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc index b190950..1b4ca5a4 100644 --- a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc +++ b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc
@@ -72,7 +72,7 @@ public: ReportUploader( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, policy::CloudPolicyClient* client, DmServerUploadService::CompletionCallback upload_complete_cb, DmServerUploadService::EncryptionKeyAttachedCallback @@ -107,7 +107,7 @@ const base::Value::Dict& value); bool need_encryption_key_; - std::unique_ptr<std::vector<EncryptedRecord>> records_; + std::vector<EncryptedRecord> records_; raw_ptr<policy::CloudPolicyClient> client_; // Encryption key delivery callback. @@ -133,7 +133,7 @@ RecordHandlerImpl::ReportUploader::ReportUploader( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, policy::CloudPolicyClient* client, DmServerUploadService::CompletionCallback client_cb, DmServerUploadService::EncryptionKeyAttachedCallback @@ -157,14 +157,7 @@ return; } - if (records_ == nullptr) { - Status null_records = Status(error::INVALID_ARGUMENT, "records_ was null"); - LOG(ERROR) << null_records; - Complete(null_records); - return; - } - - if (records_->empty() && !need_encryption_key_) { + if (records_.empty() && !need_encryption_key_) { Status empty_records = Status(error::INVALID_ARGUMENT, "records_ was empty"); LOG(ERROR) << empty_records; @@ -181,8 +174,8 @@ base::Unretained(this)); UploadEncryptedReportingRequestBuilder request_builder{need_encryption_key_}; - for (auto record : *records_) { - request_builder.AddRecord((std::move(record))); + for (auto record : records_) { + request_builder.AddRecord(std::move(record)); } // Assign random UUID as the request id for server side log correlation @@ -196,7 +189,7 @@ } // Records have been captured in the request, safe to clear the vector. - records_->clear(); + records_.clear(); content::GetUIThreadTaskRunner({})->PostTask( FROM_HERE, @@ -313,11 +306,11 @@ if (gap_record_result.has_value()) { LOG(ERROR) << "Data Loss. Record was unprocessable by the server: " << *failed_uploaded_record; - records_->push_back(std::move(gap_record_result.value())); + records_.push_back(std::move(gap_record_result.value())); } } - if (!records_->empty()) { + if (!records_.empty()) { // Upload the next record but do not request encryption key again. StartUpload(); return; @@ -431,7 +424,7 @@ void RecordHandlerImpl::HandleRecords( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, DmServerUploadService::CompletionCallback upload_complete_cb, DmServerUploadService::EncryptionKeyAttachedCallback encryption_key_attached_cb) {
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.h b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.h index c6bc2ab..6cd8d27 100644 --- a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.h +++ b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.h
@@ -33,7 +33,7 @@ // Base class RecordHandler method implementation. void HandleRecords(bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> record, + std::vector<EncryptedRecord> record, DmServerUploadService::CompletionCallback upload_complete, DmServerUploadService::EncryptionKeyAttachedCallback encryption_key_attached_cb) override;
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc b/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc index 6863044..be14080e 100644 --- a/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc +++ b/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc
@@ -93,12 +93,11 @@ std::unique_ptr<policy::MockCloudPolicyClient> client_; }; -std::unique_ptr<std::vector<EncryptedRecord>> BuildTestRecordsVector( +std::vector<EncryptedRecord> BuildTestRecordsVector( int64_t number_of_test_records, int64_t generation_id) { - std::unique_ptr<std::vector<EncryptedRecord>> test_records = - std::make_unique<std::vector<EncryptedRecord>>(); - test_records->reserve(number_of_test_records); + std::vector<EncryptedRecord> test_records; + test_records.reserve(number_of_test_records); for (int64_t i = 0; i < number_of_test_records; i++) { EncryptedRecord encrypted_record; encrypted_record.set_encrypted_wrapped_record( @@ -108,7 +107,7 @@ sequence_information->set_generation_id(generation_id); sequence_information->set_sequencing_id(i); sequence_information->set_priority(Priority::IMMEDIATE); - test_records->push_back(std::move(encrypted_record)); + test_records.push_back(std::move(encrypted_record)); } return test_records; } @@ -120,7 +119,7 @@ const auto force_confirm_by_server = force_confirm(); DmServerUploadService::SuccessfulUploadResponse expected_response{ - .sequence_information = test_records->back().sequence_information(), + .sequence_information = test_records.back().sequence_information(), .force_confirm = force_confirm()}; EXPECT_CALL(*client_, UploadEncryptedReport(IsDataUploadRequestValid(), _, _)) @@ -217,7 +216,7 @@ static constexpr int64_t kGenerationId = 1234; // test records that has one record with missing sequence information. auto test_records = BuildTestRecordsVector(kNumTestRecords, kGenerationId); - test_records->back().clear_sequence_information(); + test_records.back().clear_sequence_information(); // The response should show an error and UploadEncryptedReport should not have // been even called, because UploadEncryptedReportingRequestBuilder::Build() @@ -272,7 +271,7 @@ const DmServerUploadService::SuccessfulUploadResponse expected_response{ .sequence_information = - (*test_records)[kNumTestRecords - 1].sequence_information(), + test_records[kNumTestRecords - 1].sequence_information(), .force_confirm = force_confirm()}; // Once for failure, and once for gap. @@ -350,7 +349,7 @@ const auto force_confirm_by_server = force_confirm(); DmServerUploadService::SuccessfulUploadResponse expected_response{ - .sequence_information = test_records->back().sequence_information(), + .sequence_information = test_records.back().sequence_information(), .force_confirm = force_confirm()}; EXPECT_CALL(*client_, UploadEncryptedReport(IsDataUploadRequestValid(), _, _))
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_client.cc b/chrome/browser/policy/messaging_layer/upload/upload_client.cc index 7bee165..d03bc09 100644 --- a/chrome/browser/policy/messaging_layer/upload/upload_client.cc +++ b/chrome/browser/policy/messaging_layer/upload/upload_client.cc
@@ -40,12 +40,10 @@ Status UploadClient::EnqueueUpload( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, ReportSuccessfulUploadCallback report_upload_success_cb, EncryptionKeyAttachedCallback encryption_key_attached_cb) { - DCHECK(records); - - if (records->empty() && !need_encryption_key) { + if (records.empty() && !need_encryption_key) { return Status::StatusOK(); }
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_client.h b/chrome/browser/policy/messaging_layer/upload/upload_client.h index db94c491..41f52b3 100644 --- a/chrome/browser/policy/messaging_layer/upload/upload_client.h +++ b/chrome/browser/policy/messaging_layer/upload/upload_client.h
@@ -45,7 +45,7 @@ virtual Status EnqueueUpload( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> record, + std::vector<EncryptedRecord> record, ReportSuccessfulUploadCallback report_upload_success_cb, EncryptionKeyAttachedCallback encryption_key_attached_cb);
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc b/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc index 3c05fb43..c8ff8cd3 100644 --- a/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc +++ b/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc
@@ -124,18 +124,16 @@ std::string serialized_record; wrapped_record.SerializeToString(&serialized_record); - std::unique_ptr<std::vector<EncryptedRecord>> records = - std::make_unique<std::vector<EncryptedRecord>>(); + std::vector<EncryptedRecord> records; for (int64_t i = 0; i < kExpectedCallTimes; i++) { EncryptedRecord encrypted_record; encrypted_record.set_encrypted_wrapped_record(serialized_record); - SequenceInformation* sequence_information = encrypted_record.mutable_sequence_information(); sequence_information->set_sequencing_id(static_cast<int64_t>(i)); sequence_information->set_generation_id(kGenerationId); sequence_information->set_priority(Priority::IMMEDIATE); - records->push_back(encrypted_record); + records.push_back(encrypted_record); } StrictMock<TestEncryptionKeyAttached> encryption_key_attached; @@ -196,7 +194,7 @@ // Save last record seq info for verification. const SequenceInformation last_record_seq_info = - records->back().sequence_information(); + records.back().sequence_information(); test::TestEvent<StatusOr<std::unique_ptr<UploadClient>>> e; UploadClient::Create(client.get(), e.cb());
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_provider.cc b/chrome/browser/policy/messaging_layer/upload/upload_provider.cc index 498336e8..b2282007 100644 --- a/chrome/browser/policy/messaging_layer/upload/upload_provider.cc +++ b/chrome/browser/policy/messaging_layer/upload/upload_provider.cc
@@ -43,7 +43,7 @@ // Uploads encrypted records (can be invoked on any thread). void EnqueueUpload(bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, base::OnceCallback<void(Status)> enqueued_cb) const; private: @@ -65,10 +65,9 @@ // Uploads encrypted records on sequenced task runner (and thus capable of // detecting whether upload client is ready or not). If not ready, // it will wait and then upload. - void EnqueueUploadInternal( - bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, - base::OnceCallback<void(Status)> enqueued_cb); + void EnqueueUploadInternal(bool need_encryption_key, + std::vector<EncryptedRecord> records, + base::OnceCallback<void(Status)> enqueued_cb); // Sequence task runner and checker used during // |PostNewCloudPolicyClientRequest| processing. @@ -97,8 +96,7 @@ // because it did not yet get a confirmation from server), we will only // hold to one set of records. // Guarded by sequenced_task_runner_. - base::flat_map</*generation_id*/ int64_t, - std::unique_ptr<std::vector<EncryptedRecord>>> + base::flat_map</*generation_id*/ int64_t, std::vector<EncryptedRecord>> stored_records_; bool stored_need_encryption_key_{false}; @@ -211,7 +209,7 @@ upload_client_request_in_progress_ = false; // Upload client is ready, upload all previously stored requests (if any). - auto records = std::make_unique<std::vector<EncryptedRecord>>(); + std::vector<EncryptedRecord> records; while (!stored_records_.empty() || stored_need_encryption_key_) { if (!stored_records_.empty()) { records = std::move(stored_records_.begin()->second); @@ -230,7 +228,7 @@ void EncryptedReportingUploadProvider::UploadHelper::EnqueueUpload( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, base::OnceCallback<void(Status)> enqueued_cb) const { sequenced_task_runner_->PostTask( FROM_HERE, @@ -241,16 +239,15 @@ void EncryptedReportingUploadProvider::UploadHelper::EnqueueUploadInternal( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, base::OnceCallback<void(Status)> enqueued_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequenced_task_checker_); if (upload_client_ == nullptr) { stored_need_encryption_key_ |= need_encryption_key; int64_t generation_id = 0; - if (records && !records->empty() && - records->begin()->has_sequence_information() && - records->begin()->sequence_information().has_generation_id()) { - generation_id = records->begin()->sequence_information().generation_id(); + if (!records.empty() && records.begin()->has_sequence_information() && + records.begin()->sequence_information().has_generation_id()) { + generation_id = records.begin()->sequence_information().generation_id(); } stored_records_.emplace(generation_id, std::move(records)); // Report success even though the upload has not been executed. @@ -285,7 +282,7 @@ void EncryptedReportingUploadProvider::RequestUploadEncryptedRecords( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, base::OnceCallback<void(Status)> result_cb) { DCHECK(helper_); helper_->EnqueueUpload(need_encryption_key, std::move(records),
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_provider.h b/chrome/browser/policy/messaging_layer/upload/upload_provider.h index 07d11bb7..28b63a2 100644 --- a/chrome/browser/policy/messaging_layer/upload/upload_provider.h +++ b/chrome/browser/policy/messaging_layer/upload/upload_provider.h
@@ -49,7 +49,7 @@ // Called to upload records and/or request encryption key. void RequestUploadEncryptedRecords( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records, + std::vector<EncryptedRecord> records, base::OnceCallback<void(Status)> result_cb); private:
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_provider_unittest.cc b/chrome/browser/policy/messaging_layer/upload/upload_provider_unittest.cc index b16fe2e..0825a56 100644 --- a/chrome/browser/policy/messaging_layer/upload/upload_provider_unittest.cc +++ b/chrome/browser/policy/messaging_layer/upload/upload_provider_unittest.cc
@@ -108,7 +108,7 @@ Status CallRequestUploadEncryptedRecord( bool need_encryption_key, - std::unique_ptr<std::vector<EncryptedRecord>> records) { + std::vector<EncryptedRecord> records) { test::TestEvent<Status> result; service_provider_->RequestUploadEncryptedRecords( need_encryption_key, std::move(records), result.cb()); @@ -134,8 +134,8 @@ UploadEncryptedReport(IsDataUploadRequestValid(), _, _)) .WillOnce(MakeUploadEncryptedReportAction()); - auto records = std::make_unique<std::vector<EncryptedRecord>>(); - records->push_back(record_); + std::vector<EncryptedRecord> records; + records.push_back(record_); const auto status = CallRequestUploadEncryptedRecord( /*need_encryption_key=*/false, std::move(records)); EXPECT_OK(status) << status;
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index 2a2563e..5a2f92a 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -122,7 +122,6 @@ "components:closure_compile", "domain_reliability_internals:closure_compile", "engagement:closure_compile", - "memory_internals:closure_compile", ] if (is_linux || is_chromeos || is_win || is_mac) { deps += [
diff --git a/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.html b/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.html index 1249795a..13cb8e6a 100644 --- a/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.html +++ b/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.html
@@ -106,7 +106,7 @@ [[i18nDynamic(locale, 'consolidatedConsentGoogleEulaTitle')]] </h1> <div slot="content" class="flex layout vertical"> - <webview id="googleEulaWebview" role="document" + <webview id="consolidatedConsentGoogleEulaWebview" role="document" class="oobe-tos-webview tos-webview" on-contentload="onGoogleEulaContentLoad_"> </webview> @@ -128,7 +128,7 @@ [[i18nDynamic(locale, 'consolidatedConsentCrosEulaTitle')]] </h1> <div slot="content" class="flex layout vertical"> - <webview id="crosEulaWebview" role="document" + <webview id="consolidatedConsentCrosEulaWebview" role="document" class="oobe-tos-webview tos-webview" on-contentload="onCrosEulaContentLoad_"> </webview> @@ -149,7 +149,7 @@ [[i18nDynamic(locale, 'consolidatedConsentArcTermsTitle')]] </h1> <div slot="content" class="flex layout vertical"> - <webview id="arcTosWebview" role="document" + <webview id="consolidatedConsentArcTosWebview" role="document" class="oobe-tos-webview tos-webview" on-contentload="onArcTosContentLoad_"> </webview>
diff --git a/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js b/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js index 8a57aaf..05c5b2b 100644 --- a/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js +++ b/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js
@@ -256,7 +256,7 @@ } this.isArcTosInitialized_ = true; - const webview = this.$.arcTosWebview; + const webview = this.$.consolidatedConsentArcTosWebview; webview.removeContentScripts(['preProcess']); var language = this.getCurrentLanguage_(); @@ -299,10 +299,11 @@ this.googleEulaLoading_ = true; this.crosEulaLoading_ = true; this.loadEulaWebview_( - this.$.googleEulaWebview, this.googleEulaUrl_, + this.$.consolidatedConsentGoogleEulaWebview, this.googleEulaUrl_, false /* clear_anchors */); this.loadEulaWebview_( - this.$.crosEulaWebview, this.crosEulaUrl_, true /* clear_anchors */); + this.$.consolidatedConsentCrosEulaWebview, this.crosEulaUrl_, + true /* clear_anchors */); } if (this.shouldShowArcTos_(isTosHidden, isArcEnabled)) { @@ -326,7 +327,7 @@ } loadArcTosWebview_(online_tos_url) { - const webview = this.$.arcTosWebview; + const webview = this.$.consolidatedConsentArcTosWebview; var loadFailureCallback = () => { this.setUIStep(ConsolidatedConsentScreenState.ERROR); @@ -406,7 +407,7 @@ } onArcTosContentLoad_() { - const webview = this.$.arcTosWebview; + const webview = this.$.consolidatedConsentArcTosWebview; webview.executeScript({code: 'getPrivacyPolicyLink();'}, (results) => { if (results && results.length == 1 && typeof results[0] == 'string') { this.loadPrivacyPolicyWebview_(results[0]); @@ -721,7 +722,7 @@ // Enable loading content script 'playstore.js' when fetching ToS from // the test server. - var termsView = this.$.arcTosWebview; + var termsView = this.$.consolidatedConsentArcTosWebview; termsView.removeContentScripts(['postProcess']); termsView.addContentScripts([{ name: 'postProcess',
diff --git a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.html b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.html index c387679..71bf83fd 100644 --- a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.html +++ b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.html
@@ -59,7 +59,7 @@ [[i18nDynamic(locale, 'guestTosGoogleEulaTitle')]] </h1> <div slot="content" class="flex layout vertical"> - <webview id="googleEulaWebview" role="document" + <webview id="guestTosGoogleEulaWebview" role="document" class="oobe-tos-webview tos-webview" on-contentload="onGoogleEulaContentLoad_"> </webview> @@ -80,7 +80,7 @@ [[i18nDynamic(locale, 'guestTosCrosEulaTitle')]] </h1> <div slot="content" class="flex layout vertical"> - <webview id="crosEulaWebview" role="document" + <webview id="guestTosCrosEulaWebview" role="document" class="oobe-tos-webview tos-webview"> </webview> </div>
diff --git a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js index e4453d4..9260099a 100644 --- a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js +++ b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js
@@ -85,9 +85,10 @@ const crosEulaUrl = data['crosEulaUrl']; this.loadEulaWebview_( - this.$.googleEulaWebview, googleEulaUrl, false /* clear_anchors */); + this.$.guestTosGoogleEulaWebview, googleEulaUrl, + false /* clear_anchors */); this.loadEulaWebview_( - this.$.crosEulaWebview, crosEulaUrl, true /* clear_anchors */); + this.$.guestTosCrosEulaWebview, crosEulaUrl, true /* clear_anchors */); } /** Initial UI State for screen */
diff --git a/chrome/browser/resources/history/app.ts b/chrome/browser/resources/history/app.ts index ec71ede0..c52b96ec 100644 --- a/chrome/browser/resources/history/app.ts +++ b/chrome/browser/resources/history/app.ts
@@ -19,6 +19,7 @@ import {CrDrawerElement} from 'chrome://resources/cr_elements/cr_drawer/cr_drawer.js'; import {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js'; import {FindShortcutMixin, FindShortcutMixinInterface} from 'chrome://resources/cr_elements/find_shortcut_mixin.js'; +import {assert} from 'chrome://resources/js/assert_ts.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {hasKeyModifiers} from 'chrome://resources/js/util.m.js'; @@ -241,6 +242,7 @@ private tabsIcons_: Array<string>; private tabsNames_: Array<string>; private toolbarShadow_: boolean; + private historyClustersViewStartTime_: Date|null = null; constructor() { super(); @@ -259,6 +261,8 @@ this.eventTracker_.add( document, 'keydown', e => this.onKeyDown_(e as KeyboardEvent)); + this.eventTracker_.add( + document, 'visibilitychange', this.onVisibilityChange_.bind(this)); this.addWebUIListener( 'sign-in-state-changed', (signedIn: boolean) => this.onSignInStateChanged_(signedIn)); @@ -404,6 +408,21 @@ } } + private onVisibilityChange_() { + if (this.selectedPage_ !== Page.HISTORY_CLUSTERS) { + return; + } + + if (document.visibilityState === 'hidden') { + this.recordHistoryClustersDuration_(); + } else if ( + document.visibilityState === 'visible' && + this.historyClustersViewStartTime_ === null) { + // Restart the timer if the user switches back to the History tab. + this.historyClustersViewStartTime_ = new Date(); + } + } + private onDeleteCommand_() { if (this.$.toolbar.count === 0 || this.pendingDelete_) { return; @@ -460,10 +479,18 @@ return querying && !incremental && searchTerm !== ''; } - private selectedPageChanged_() { + private selectedPageChanged_(newPage: Page, oldPage: Page) { this.unselectAll(); this.historyViewChanged_(); this.maybeUpdateSelectedHistoryTab_(); + + if (oldPage === Page.HISTORY_CLUSTERS && + newPage !== Page.HISTORY_CLUSTERS) { + this.recordHistoryClustersDuration_(); + } + if (newPage === Page.HISTORY_CLUSTERS) { + this.historyClustersViewStartTime_ = new Date(); + } } private updateScrollTarget_() { @@ -507,6 +534,18 @@ this.recordHistoryPageView_(); } + // Records the history clusters page duration. + private recordHistoryClustersDuration_() { + assert(this.historyClustersViewStartTime_ !== null); + + const duration = + new Date().getTime() - this.historyClustersViewStartTime_.getTime(); + this.browserService_!.recordLongTime( + 'History.Clusters.WebUISessionDuration', duration); + + this.historyClustersViewStartTime_ = null; + } + private hasDrawerChanged_() { const drawer = this.$.drawer.getIfExists(); if (!this.hasDrawer_ && drawer && drawer.open) {
diff --git a/chrome/browser/resources/history/browser_service.ts b/chrome/browser/resources/history/browser_service.ts index 73990400..ff10c52f 100644 --- a/chrome/browser/resources/history/browser_service.ts +++ b/chrome/browser/resources/history/browser_service.ts
@@ -33,6 +33,7 @@ recordHistogram(histogram: string, value: number, max: number): void; recordAction(action: string): void; recordTime(histogram: string, time: number): void; + recordLongTime(histogram: string, time: number): void; navigateToUrl(url: string, target: string, e: MouseEvent): void; otherDevicesInitialized(): void; queryHistoryContinuation(): Promise<QueryResult>; @@ -96,6 +97,13 @@ chrome.send('metricsHandler:recordTime', [histogram, time]); } + recordLongTime(histogram: string, time: number) { + // It's a bit odd that this is the only one to use chrome.metricsPrivate, + // but that's because the other code predates chrome.metricsPrivate. + // In any case, the MetricsHandler doesn't support long time histograms. + chrome.metricsPrivate.recordLongTime(histogram, time); + } + navigateToUrl(url: string, target: string, e: MouseEvent) { chrome.send( 'navigateToUrl',
diff --git a/chrome/browser/resources/memory_internals/BUILD.gn b/chrome/browser/resources/memory_internals/BUILD.gn index 6ab9dbc..0918d56 100644 --- a/chrome/browser/resources/memory_internals/BUILD.gn +++ b/chrome/browser/resources/memory_internals/BUILD.gn
@@ -2,15 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//third_party/closure_compiler/compile_js.gni") +import("//tools/typescript/ts_library.gni") -js_type_check("closure_compile") { - deps = [ ":memory_internals" ] -} - -js_library("memory_internals") { - deps = [ - "//ui/webui/resources/js:cr.m", - "//ui/webui/resources/js:util.m", - ] +ts_library("build_ts") { + root_dir = "." + out_dir = "$target_gen_dir/tsc" + in_files = [ "memory_internals.ts" ] + definitions = [ "//tools/typescript/definitions/chrome_send.d.ts" ] + deps = [ "//ui/webui/resources:library" ] }
diff --git a/chrome/browser/resources/memory_internals/memory_internals.js b/chrome/browser/resources/memory_internals/memory_internals.ts similarity index 85% rename from chrome/browser/resources/memory_internals/memory_internals.js rename to chrome/browser/resources/memory_internals/memory_internals.ts index c10e06c..89993984 100644 --- a/chrome/browser/resources/memory_internals/memory_internals.js +++ b/chrome/browser/resources/memory_internals/memory_internals.ts
@@ -5,6 +5,13 @@ import {addWebUIListener, sendWithPromise} from 'chrome://resources/js/cr.m.js'; import {$} from 'chrome://resources/js/util.m.js'; +type Process = [number, string, boolean]; + +type ProcessList = { + message: string, + processes: Process[], +}; + function requestProcessList() { sendWithPromise('requestProcessList').then(onProcessListReceived); } @@ -13,17 +20,18 @@ chrome.send('saveDump'); } -function reportProcess(pid) { +function reportProcess(pid: number) { chrome.send('reportProcess', [pid]); } -function startProfiling(pid) { +function startProfiling(pid: number) { chrome.send('startProfiling', [pid]); } // celltype should either be "td" or "th". The contents of the |cols| will be // added as children of each table cell if they are non-null. -function addListRow(table, celltype, cols) { +function addListRow( + table: HTMLElement, celltype: string, cols: Array<Text|HTMLElement|null>) { const tr = document.createElement('tr'); for (const col of cols) { const cell = document.createElement(celltype); @@ -35,7 +43,7 @@ table.appendChild(tr); } -function onProcessListReceived(data) { +function onProcessListReceived(data: ProcessList) { $('message').innerText = data['message']; const proclist = $('proclist'); @@ -80,7 +88,7 @@ $('refresh').onclick = requestProcessList; $('save').onclick = saveDump; - addWebUIListener('save-dump-progress', progress => { + addWebUIListener('save-dump-progress', (progress: string) => { $('save-dump-text').innerText = progress; });
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_page.html b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_page.html index c743998..3b5b440 100644 --- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_page.html +++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_page.html
@@ -9,14 +9,23 @@ <div class="start"> $i18n{crostiniPageLabel} <div class="secondary" id="secondaryText"> - <localized-link - localized-string="[[i18nAdvanced('crostiniSubtext')]]"> - </localized-link> + <template is="dom-if" if="[[showCrostini]]" restamp> + <localized-link + localized-string="[[i18nAdvanced('crostiniSubtext')]]"> + </localized-link> + </template> + <template is="dom-if" if="[[!showCrostini]]" restamp> + <localized-link localized-string="[[i18nAdvanced( + 'crostiniSubtextNotSupported')]]"> + </localized-link> + </template> </div> </div> - <template is="dom-if" if="[[!allowCrostini]]" restamp> - <cr-policy-indicator indicator-type="userPolicy"> - </cr-policy-indicator> + <template is="dom-if" if="[[showCrostini]]" restamp> + <template is="dom-if" if="[[!allowCrostini]]" restamp> + <cr-policy-indicator indicator-type="userPolicy"> + </cr-policy-indicator> + </template> </template> <template is="dom-if" if="[[prefs.crostini.enabled.value]]"> <cr-icon-button class="subpage-arrow"
diff --git a/chrome/browser/resources/settings/chromeos/os_route.js b/chrome/browser/resources/settings/chromeos/os_route.js index 19c1c71..867108f0 100644 --- a/chrome/browser/resources/settings/chromeos/os_route.js +++ b/chrome/browser/resources/settings/chromeos/os_route.js
@@ -218,10 +218,10 @@ } // Crostini section. + r.CROSTINI = + createSection(r.ADVANCED, mojom.CROSTINI_SECTION_PATH, Section.kCrostini); if (loadTimeData.valueExists('showCrostini') && loadTimeData.getBoolean('showCrostini')) { - r.CROSTINI = createSection( - r.ADVANCED, mojom.CROSTINI_SECTION_PATH, Section.kCrostini); r.CROSTINI_DETAILS = createSubpage( r.CROSTINI, mojom.CROSTINI_DETAILS_SUBPAGE_PATH, Subpage.kCrostiniDetails);
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html index 892fff5..2499a9e 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html +++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
@@ -214,7 +214,7 @@ <iron-icon icon="os-settings:print"></iron-icon> $i18n{printingPageTitle} </a> - <a href="/crostini" hidden="[[!showCrostini]]" class="item"> + <a href="/crostini" class="item"> <iron-icon icon="os-settings:developer-tags"></iron-icon> $i18n{crostiniPageTitle} </a>
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html index 7fba828e..f7bb5d7 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html +++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
@@ -241,14 +241,13 @@ <os-settings-printing-page prefs="{{prefs}}"> </os-settings-printing-page> </settings-section> - <template is="dom-if" if="[[showCrostini]]" restamp> - <settings-section page-title="$i18n{crostiniPageTitle}" - section="crostini"> - <settings-crostini-page prefs="{{prefs}}" - allow-crostini="[[allowCrostini_]]"> - </settings-crostini-page> - </settings-section> - </template> + <settings-section page-title="$i18n{crostiniPageTitle}" + section="crostini"> + <settings-crostini-page prefs="{{prefs}}" + allow-crostini="[[allowCrostini_]]" + show-crostini="[[showCrostini]]"> + </settings-crostini-page> + </settings-section> <template is="dom-if" if="[[!isAccessibilityOSSettingsVisibilityEnabled_]]"> <settings-section page-title="$i18n{a11yPageTitle}" section="osAccessibility">
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html index fb17b913..981f73fd 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html +++ b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html
@@ -120,7 +120,6 @@ <template is="dom-if" id="drawerTemplate"> <os-settings-menu show-apps="[[showApps_]]" - show-crostini="[[showCrostini_]]" show-plugin-vm="[[showPluginVm_]]" show-reset="[[showReset_]]" show-startup="[[showStartup_]]" @@ -137,7 +136,6 @@ <div id="left"> <template is="dom-if" if="[[showNavMenu_]]"> <os-settings-menu page-visibility="[[pageVisibility_]]" - show-crostini="[[showCrostini_]]" show-reset="[[showReset_]]" show-startup="[[showStartup_]]" have-play-store-app="[[havePlayStoreApp_]]"
diff --git a/chrome/browser/segmentation_platform/default_model/chrome_start_model_android.cc b/chrome/browser/segmentation_platform/default_model/chrome_start_model_android.cc index f8b8fd2..83026a3 100644 --- a/chrome/browser/segmentation_platform/default_model/chrome_start_model_android.cc +++ b/chrome/browser/segmentation_platform/default_model/chrome_start_model_android.cc
@@ -4,11 +4,13 @@ #include "chrome/browser/segmentation_platform/default_model/chrome_start_model_android.h" +#include <array> + #include "base/metrics/field_trial_params.h" #include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/flags/android/chrome_feature_list.h" -#include "chrome/browser/segmentation_platform/default_model/metadata_writer.h" #include "chrome/browser/ui/android/start_surface/start_surface_android.h" +#include "components/segmentation_platform/internal/metadata/metadata_writer.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/public/model_provider.h" @@ -36,61 +38,24 @@ // InputFeatures. constexpr int32_t kProfileSigninStatusEnums[] = {0 /* All profiles syncing */, 2 /* Mixed sync status */}; -constexpr MetadataWriter::UMAFeature kChromeStartUMAFeatures[] = { - MetadataWriter::UMAFeature{ - .signal_type = proto::SignalType::USER_ACTION, - .name = "ContentSuggestions.Feed.CardAction.Open", - .bucket_count = 7, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{ - .signal_type = proto::SignalType::USER_ACTION, - .name = "ContentSuggestions.Feed.CardAction.OpenInNewIncognitoTab", - .bucket_count = 7, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{ - .signal_type = proto::SignalType::USER_ACTION, - .name = "ContentSuggestions.Feed.CardAction.OpenInNewTab", - .bucket_count = 7, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "MobileNTPMostVisited", - .bucket_count = 7, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "MobileNewTabOpened", - .bucket_count = 7, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "MobileMenuRecentTabs", - .bucket_count = 7, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "MobileMenuHistory", - .bucket_count = 7, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::HISTOGRAM_ENUM, - .name = "UMA.ProfileSignInStatus", - .bucket_count = 7, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 2, - .accepted_enum_ids = kProfileSigninStatusEnums}}; - -#define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0])) +constexpr std::array<MetadataWriter::UMAFeature, 8> kChromeStartUMAFeatures = { + MetadataWriter::UMAFeature::FromUserAction( + "ContentSuggestions.Feed.CardAction.Open", + 7), + MetadataWriter::UMAFeature::FromUserAction( + "ContentSuggestions.Feed.CardAction.OpenInNewIncognitoTab", + 7), + MetadataWriter::UMAFeature::FromUserAction( + "ContentSuggestions.Feed.CardAction.OpenInNewTab", + 7), + MetadataWriter::UMAFeature::FromUserAction("MobileNTPMostVisited", 7), + MetadataWriter::UMAFeature::FromUserAction("MobileNewTabOpened", 7), + MetadataWriter::UMAFeature::FromUserAction("MobileMenuRecentTabs", 7), + MetadataWriter::UMAFeature::FromUserAction("MobileMenuHistory", 7), + MetadataWriter::UMAFeature::FromEnumHistogram("UMA.ProfileSignInStatus", + 7, + kProfileSigninStatusEnums, + 2)}; } // namespace @@ -111,8 +76,8 @@ kDiscreteMappings, 1); // Set features. - writer.AddUmaFeatures(kChromeStartUMAFeatures, - ARRAY_SIZE(kChromeStartUMAFeatures)); + writer.AddUmaFeatures(kChromeStartUMAFeatures.data(), + kChromeStartUMAFeatures.size()); constexpr int kModelVersion = 1; base::SequencedTaskRunnerHandle::Get()->PostTask( @@ -124,7 +89,7 @@ void ChromeStartModel::ExecuteModelWithInput(const std::vector<float>& inputs, ExecutionCallback callback) { // Invalid inputs. - if (inputs.size() != ARRAY_SIZE(kChromeStartUMAFeatures)) { + if (inputs.size() != kChromeStartUMAFeatures.size()) { base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), absl::nullopt)); return;
diff --git a/chrome/browser/segmentation_platform/default_model/chrome_start_model_android_unittest.cc b/chrome/browser/segmentation_platform/default_model/chrome_start_model_android_unittest.cc index c3d62af..edd98512 100644 --- a/chrome/browser/segmentation_platform/default_model/chrome_start_model_android_unittest.cc +++ b/chrome/browser/segmentation_platform/default_model/chrome_start_model_android_unittest.cc
@@ -6,7 +6,7 @@ #include "base/run_loop.h" #include "base/test/task_environment.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace segmentation_platform {
diff --git a/chrome/browser/segmentation_platform/default_model/feed_user_segment.cc b/chrome/browser/segmentation_platform/default_model/feed_user_segment.cc index 69f5a9b..bdb4f4ca 100644 --- a/chrome/browser/segmentation_platform/default_model/feed_user_segment.cc +++ b/chrome/browser/segmentation_platform/default_model/feed_user_segment.cc
@@ -4,10 +4,12 @@ #include "chrome/browser/segmentation_platform/default_model/feed_user_segment.h" +#include <array> + #include "base/metrics/field_trial_params.h" #include "base/strings/strcat.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "chrome/browser/segmentation_platform/default_model/metadata_writer.h" +#include "components/segmentation_platform/internal/metadata/metadata_writer.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/public/config.h" #include "components/segmentation_platform/public/model_provider.h" @@ -47,66 +49,23 @@ }}; // InputFeatures. -constexpr MetadataWriter::UMAFeature kFeedUserUMAFeatures[] = { - MetadataWriter::UMAFeature{ - .signal_type = proto::SignalType::USER_ACTION, - .name = "ContentSuggestions.Feed.CardAction.Open", - .bucket_count = 14, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{ - .signal_type = proto::SignalType::USER_ACTION, - .name = "ContentSuggestions.Feed.CardAction.OpenInNewIncognitoTab", - .bucket_count = 14, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{ - .signal_type = proto::SignalType::USER_ACTION, - .name = "ContentSuggestions.Feed.CardAction.OpenInNewTab", - .bucket_count = 14, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "MobileNTPMostVisited", - .bucket_count = 14, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "MobileNewTabOpened", - .bucket_count = 14, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "Home", - .bucket_count = 14, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "MobileMenuRecentTabs", - .bucket_count = 14, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "MobileMenuHistory", - .bucket_count = 14, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "MobileTabReturnedToCurrentTab", - .bucket_count = 14, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}}; - -#define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0])) +constexpr std::array<MetadataWriter::UMAFeature, 9> kFeedUserUMAFeatures = { + MetadataWriter::UMAFeature::FromUserAction( + "ContentSuggestions.Feed.CardAction.Open", + 14), + MetadataWriter::UMAFeature::FromUserAction( + "ContentSuggestions.Feed.CardAction.OpenInNewIncognitoTab", + 14), + MetadataWriter::UMAFeature::FromUserAction( + "ContentSuggestions.Feed.CardAction.OpenInNewTab", + 14), + MetadataWriter::UMAFeature::FromUserAction("MobileNTPMostVisited", 14), + MetadataWriter::UMAFeature::FromUserAction("MobileNewTabOpened", 14), + MetadataWriter::UMAFeature::FromUserAction("Home", 14), + MetadataWriter::UMAFeature::FromUserAction("MobileMenuRecentTabs", 14), + MetadataWriter::UMAFeature::FromUserAction("MobileMenuHistory", 14), + MetadataWriter::UMAFeature::FromUserAction("MobileTabReturnedToCurrentTab", + 14)}; float GetScoreForSubsegment(FeedUserSubsegment subgroup) { for (const auto& score_and_type : kFeedUserScoreToSubGroup) { @@ -174,7 +133,8 @@ kFeedUserScoreToSubGroup.data(), kFeedUserScoreToSubGroup.size()); // Set features. - writer.AddUmaFeatures(kFeedUserUMAFeatures, ARRAY_SIZE(kFeedUserUMAFeatures)); + writer.AddUmaFeatures(kFeedUserUMAFeatures.data(), + kFeedUserUMAFeatures.size()); constexpr int kModelVersion = 1; base::SequencedTaskRunnerHandle::Get()->PostTask( @@ -186,7 +146,7 @@ void FeedUserSegment::ExecuteModelWithInput(const std::vector<float>& inputs, ExecutionCallback callback) { // Invalid inputs. - if (inputs.size() != ARRAY_SIZE(kFeedUserUMAFeatures)) { + if (inputs.size() != kFeedUserUMAFeatures.size()) { base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), absl::nullopt)); return;
diff --git a/chrome/browser/segmentation_platform/default_model/feed_user_segment_unittest.cc b/chrome/browser/segmentation_platform/default_model/feed_user_segment_unittest.cc index 71ea016..af0e807 100644 --- a/chrome/browser/segmentation_platform/default_model/feed_user_segment_unittest.cc +++ b/chrome/browser/segmentation_platform/default_model/feed_user_segment_unittest.cc
@@ -6,44 +6,10 @@ #include "base/run_loop.h" #include "base/test/task_environment.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace segmentation_platform { -namespace { - -// TODO(ssid): Use metadata_utils or share common code for this function. -int ConvertToDiscreteScore(const std::string& mapping_key, - float input_score, - const proto::SegmentationModelMetadata& metadata) { - auto iter = metadata.discrete_mappings().find(mapping_key); - if (iter == metadata.discrete_mappings().end()) { - iter = - metadata.discrete_mappings().find(metadata.default_discrete_mapping()); - if (iter == metadata.discrete_mappings().end()) - return 0; - } - DCHECK(iter != metadata.discrete_mappings().end()); - - const auto& mapping = iter->second; - - // Iterate over the entries and find the largest entry whose min result is - // equal to or less than the input. - int discrete_result = 0; - float largest_score_below_input_score = std::numeric_limits<float>::min(); - for (int i = 0; i < mapping.entries_size(); i++) { - const auto& entry = mapping.entries(i); - if (entry.min_result() <= input_score && - entry.min_result() > largest_score_below_input_score) { - largest_score_below_input_score = entry.min_result(); - discrete_result = entry.rank(); - } - } - - return discrete_result; -} - -} // namespace class FeedUserModelTest : public testing::Test { public: @@ -117,32 +83,36 @@ absl::optional<float> result = ExpectExecutionWithInput(input); ASSERT_TRUE(result); - EXPECT_EQ("NoNTPOrHomeOpened", - FeedUserSegment::GetSubsegmentName(ConvertToDiscreteScore( - "feed_user_segment_subsegment", *result, *fetched_metadata_))); + EXPECT_EQ( + "NoNTPOrHomeOpened", + FeedUserSegment::GetSubsegmentName(metadata_utils::ConvertToDiscreteScore( + "feed_user_segment_subsegment", *result, *fetched_metadata_))); input[4] = 3; input[5] = 2; result = ExpectExecutionWithInput(input); ASSERT_TRUE(result); - EXPECT_EQ("UsedNtpWithoutModules", - FeedUserSegment::GetSubsegmentName(ConvertToDiscreteScore( - "feed_user_segment_subsegment", *result, *fetched_metadata_))); + EXPECT_EQ( + "UsedNtpWithoutModules", + FeedUserSegment::GetSubsegmentName(metadata_utils::ConvertToDiscreteScore( + "feed_user_segment_subsegment", *result, *fetched_metadata_))); input[3] = 3; result = ExpectExecutionWithInput(input); ASSERT_TRUE(result); - EXPECT_EQ("MvtOnly", - FeedUserSegment::GetSubsegmentName(ConvertToDiscreteScore( - "feed_user_segment_subsegment", *result, *fetched_metadata_))); + EXPECT_EQ( + "MvtOnly", + FeedUserSegment::GetSubsegmentName(metadata_utils::ConvertToDiscreteScore( + "feed_user_segment_subsegment", *result, *fetched_metadata_))); input[0] = 1; input[2] = 2; result = ExpectExecutionWithInput(input); ASSERT_TRUE(result); - EXPECT_EQ("ActiveOnFeedAndNtpFeatures", - FeedUserSegment::GetSubsegmentName(ConvertToDiscreteScore( - "feed_user_segment_subsegment", *result, *fetched_metadata_))); + EXPECT_EQ( + "ActiveOnFeedAndNtpFeatures", + FeedUserSegment::GetSubsegmentName(metadata_utils::ConvertToDiscreteScore( + "feed_user_segment_subsegment", *result, *fetched_metadata_))); EXPECT_FALSE(ExpectExecutionWithInput({})); EXPECT_FALSE(ExpectExecutionWithInput({1, 2}));
diff --git a/chrome/browser/segmentation_platform/default_model/low_user_engagement_model.cc b/chrome/browser/segmentation_platform/default_model/low_user_engagement_model.cc index 626ad6b..69e6eab9 100644 --- a/chrome/browser/segmentation_platform/default_model/low_user_engagement_model.cc +++ b/chrome/browser/segmentation_platform/default_model/low_user_engagement_model.cc
@@ -4,10 +4,12 @@ #include "chrome/browser/segmentation_platform/default_model/low_user_engagement_model.h" +#include <array> + #include "base/logging.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" -#include "chrome/browser/segmentation_platform/default_model/metadata_writer.h" +#include "components/segmentation_platform/internal/metadata/metadata_writer.h" namespace segmentation_platform { @@ -33,7 +35,7 @@ {kChromeStartDiscreteMappingMinResult, kChromeStartDiscreteMappingRank}}; // InputFeatures. -constexpr MetadataWriter::UMAFeature kChromeStartUMAFeatures[] = { +constexpr std::array<MetadataWriter::UMAFeature, 1> kChromeStartUMAFeatures = { MetadataWriter::UMAFeature{ .signal_type = proto::SignalType::HISTOGRAM_VALUE, .name = "Session.TotalDuration", @@ -42,8 +44,6 @@ .aggregation = proto::Aggregation::BUCKETED_COUNT, .enum_ids_size = 0}}; -#define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0])) - } // namespace LowUserEngagementModel::LowUserEngagementModel() @@ -63,8 +63,8 @@ kDiscreteMappings, 1); // Set features. - writer.AddUmaFeatures(kChromeStartUMAFeatures, - ARRAY_SIZE(kChromeStartUMAFeatures)); + writer.AddUmaFeatures(kChromeStartUMAFeatures.data(), + kChromeStartUMAFeatures.size()); constexpr int kModelVersion = 1; base::SequencedTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/browser/segmentation_platform/default_model/low_user_engagement_model_unittest.cc b/chrome/browser/segmentation_platform/default_model/low_user_engagement_model_unittest.cc index e9b1f16..dbd9a6f1 100644 --- a/chrome/browser/segmentation_platform/default_model/low_user_engagement_model_unittest.cc +++ b/chrome/browser/segmentation_platform/default_model/low_user_engagement_model_unittest.cc
@@ -6,7 +6,7 @@ #include "base/run_loop.h" #include "base/test/task_environment.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace segmentation_platform {
diff --git a/chrome/browser/segmentation_platform/default_model/metadata_writer.h b/chrome/browser/segmentation_platform/default_model/metadata_writer.h deleted file mode 100644 index 953699d..0000000 --- a/chrome/browser/segmentation_platform/default_model/metadata_writer.h +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2022 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_SEGMENTATION_PLATFORM_DEFAULT_MODEL_METADATA_WRITER_H_ -#define CHROME_BROWSER_SEGMENTATION_PLATFORM_DEFAULT_MODEL_METADATA_WRITER_H_ - -#include <cinttypes> -#include <cstddef> - -#include "components/segmentation_platform/internal/proto/model_metadata.pb.h" - -namespace segmentation_platform { - -// TODO(ssid): Move these functions to components/segmentation to be used by all -// the default models. - -// Utility to write metadata proto for default models. -class MetadataWriter { - public: - explicit MetadataWriter(proto::SegmentationModelMetadata* metadata); - ~MetadataWriter(); - - MetadataWriter(MetadataWriter&) = delete; - MetadataWriter& operator=(MetadataWriter&) = delete; - - // Defines a feature based on UMA metric. - struct UMAFeature { - const proto::SignalType signal_type{proto::SignalType::UNKNOWN_SIGNAL_TYPE}; - const char* name{nullptr}; - const uint64_t bucket_count{0}; - const uint64_t tensor_length{0}; - const proto::Aggregation aggregation{proto::Aggregation::UNKNOWN}; - const size_t enum_ids_size{0}; - const int32_t* const accepted_enum_ids = nullptr; - }; - - // Appends list of UMA features in order. - void AddUmaFeatures(const UMAFeature features[], size_t features_size); - - // Appends a list of discrete mapping in order. - void AddDiscreteMappingEntries(const std::string& key, - const std::pair<float, int>* mappings, - size_t mappings_size); - - // Writes the model metadata with the given parameters. - void SetSegmentationMetadataConfig(proto::TimeUnit time_unit, - uint64_t bucket_duration, - int64_t signal_storage_length, - int64_t min_signal_collection_length, - int64_t result_time_to_live); - - private: - proto::SegmentationModelMetadata* const metadata_; -}; - -} // namespace segmentation_platform - -#endif // CHROME_BROWSER_SEGMENTATION_PLATFORM_DEFAULT_MODEL_METADATA_WRITER_H_
diff --git a/chrome/browser/segmentation_platform/default_model/query_tiles_model.cc b/chrome/browser/segmentation_platform/default_model/query_tiles_model.cc index 307819b..f63f6d7 100644 --- a/chrome/browser/segmentation_platform/default_model/query_tiles_model.cc +++ b/chrome/browser/segmentation_platform/default_model/query_tiles_model.cc
@@ -4,8 +4,10 @@ #include "chrome/browser/segmentation_platform/default_model/query_tiles_model.h" +#include <array> + #include "base/threading/sequenced_task_runner_handle.h" -#include "chrome/browser/segmentation_platform/default_model/metadata_writer.h" +#include "components/segmentation_platform/internal/metadata/metadata_writer.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/public/model_provider.h" @@ -32,19 +34,11 @@ {kQueryTilesDiscreteMappingMinResult, kQueryTilesDiscreteMappingRank}}; // InputFeatures. -constexpr MetadataWriter::UMAFeature kQueryTilesUMAFeatures[2] = { - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "MobileNTPMostVisited", - .bucket_count = 7, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}, - MetadataWriter::UMAFeature{.signal_type = proto::SignalType::USER_ACTION, - .name = "Search.QueryTiles.NTP.Tile.Clicked", - .bucket_count = 7, - .tensor_length = 1, - .aggregation = proto::Aggregation::COUNT, - .enum_ids_size = 0}}; +constexpr std::array<MetadataWriter::UMAFeature, 2> kQueryTilesUMAFeatures = { + MetadataWriter::UMAFeature::FromUserAction("MobileNTPMostVisited", 7), + MetadataWriter::UMAFeature::FromUserAction( + "Search.QueryTiles.NTP.Tile.Clicked", + 7)}; } // namespace @@ -65,9 +59,8 @@ kDiscreteMappings, 1); // Set features. - writer.AddUmaFeatures( - kQueryTilesUMAFeatures, - sizeof(kQueryTilesUMAFeatures) / sizeof(kQueryTilesUMAFeatures[0])); + writer.AddUmaFeatures(kQueryTilesUMAFeatures.data(), + kQueryTilesUMAFeatures.size()); base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, @@ -78,7 +71,7 @@ void QueryTilesModel::ExecuteModelWithInput(const std::vector<float>& inputs, ExecutionCallback callback) { // Invalid inputs. - if (inputs.size() != 2) { + if (inputs.size() != kQueryTilesUMAFeatures.size()) { base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), absl::nullopt)); return;
diff --git a/chrome/browser/segmentation_platform/default_model/query_tiles_model_unittest.cc b/chrome/browser/segmentation_platform/default_model/query_tiles_model_unittest.cc index 82da0b7..82949d74 100644 --- a/chrome/browser/segmentation_platform/default_model/query_tiles_model_unittest.cc +++ b/chrome/browser/segmentation_platform/default_model/query_tiles_model_unittest.cc
@@ -6,7 +6,7 @@ #include "base/run_loop.h" #include "base/test/task_environment.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace segmentation_platform {
diff --git a/chrome/browser/storage/shared_storage_browsertest.cc b/chrome/browser/storage/shared_storage_browsertest.cc index 982a5390..d61f9ef4 100644 --- a/chrome/browser/storage/shared_storage_browsertest.cc +++ b/chrome/browser/storage/shared_storage_browsertest.cc
@@ -57,8 +57,8 @@ } std::string GetSharedStorageDisabledErrorMessage() { - return base::StrCat({"a JavaScript error:\nError: ", - content::GetSharedStorageDisabledMessage(), "\n"}); + return base::StrCat({"a JavaScript error: \"Error: ", + content::GetSharedStorageDisabledMessage(), "\"\n"}); } } // namespace @@ -260,7 +260,7 @@ if (!SuccessExpected()) { // Shared Storage will be disabled. - EXPECT_EQ("a JavaScript error:\nError: sharedStorage is disabled\n", + EXPECT_EQ("a JavaScript error: \"Error: sharedStorage is disabled\"\n", result.error); EXPECT_EQ(0u, console_observer.messages().size()); return;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 5546366..65a57c7 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -4195,6 +4195,8 @@ "views/collected_cookies_views.h", "views/commander_frontend_views.cc", "views/commander_frontend_views.h", + "views/commerce/ntp_discount_consent_dialog_view.cc", + "views/commerce/ntp_discount_consent_dialog_view.h", "views/confirm_bubble_views.cc", "views/confirm_bubble_views.h", "views/constrained_web_dialog_delegate_views.cc", @@ -4943,6 +4945,8 @@ "views/web_apps/pwa_confirmation_bubble_view.h", "views/web_apps/web_app_confirmation_view.cc", "views/web_apps/web_app_confirmation_view.h", + "views/web_apps/web_app_detailed_install_dialog.cc", + "views/web_apps/web_app_detailed_install_dialog.h", "views/web_apps/web_app_identity_update_confirmation_view.cc", "views/web_apps/web_app_identity_update_confirmation_view.h", "views/web_apps/web_app_info_image_source.cc", @@ -5581,6 +5585,7 @@ "//components/permissions", "//components/sessions", "//components/translate/content/browser", + "//components/url_formatter", "//components/zoom", "//content/public/browser", "//content/public/common",
diff --git a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java index a1e1c70..6d4e185 100644 --- a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java +++ b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java
@@ -93,6 +93,11 @@ } /** + * Notify the native page that it is about to be navigated back or hidden by a back press. + */ + default void notifyHidingWithBack() {} + + /** * Called after a page has been removed from the view hierarchy and will no longer be used. */ void destroy();
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java index 16758e6..8509664 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java
@@ -21,6 +21,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator; +import org.chromium.chrome.browser.ui.native_page.NativePage; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.feature_engagement.EventConstants; import org.chromium.components.feature_engagement.Tracker; @@ -90,6 +91,11 @@ Tab tab = mTabSupplier.get(); if (tab != null && tab.canGoBack()) { + NativePage nativePage = tab.getNativePage(); + if (nativePage != null) { + nativePage.notifyHidingWithBack(); + } + tab.goBack(); mOnSuccessRunnable.run(); return true;
diff --git a/chrome/browser/ui/app_list/app_list_model_updater.h b/chrome/browser/ui/app_list/app_list_model_updater.h index 3dcc97c..abf12dd 100644 --- a/chrome/browser/ui/app_list/app_list_model_updater.h +++ b/chrome/browser/ui/app_list/app_list_model_updater.h
@@ -78,7 +78,8 @@ virtual void SetAppStatus(const std::string& id, ash::AppStatus app_status) {} virtual void SetItemPosition(const std::string& id, const syncer::StringOrdinal& new_position) {} - virtual void SetItemIsPersistent(const std::string& id, bool is_persistent) {} + virtual void SetItemIsSystemFolder(const std::string& id, + bool is_system_folder) {} virtual void SetIsNewInstall(const std::string& id, bool is_new_install) {} virtual void SetItemFolderId(const std::string& id, const std::string& folder_id) = 0;
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 1ac9eae..6b709cc 100644 --- a/chrome/browser/ui/app_list/app_list_syncable_service.cc +++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -245,7 +245,7 @@ const AppListSyncableService::SyncItem& folder_item) { if (folder_item.item_type != sync_pb::AppListSpecifics::TYPE_FOLDER) return false; - return folder_item.is_persistent_folder; + return folder_item.is_system_folder; } // Updates `target` if `target` is different from a valid new value. Returns @@ -583,7 +583,7 @@ auto iter = sync_items_.find(id); if (iter != sync_items_.end()) return iter->second.get(); - return NULL; + return nullptr; } void AppListSyncableService::AppListSyncableService::AddPageBreakItem( @@ -808,7 +808,7 @@ const std::string& item_id = app_item->id(); if (item_id.empty()) { LOG(ERROR) << "ChromeAppListItem item with empty ID"; - return NULL; + return nullptr; } SyncItem* sync_item = FindSyncItem(item_id); if (sync_item) { @@ -820,7 +820,7 @@ } if (RemoveDefaultApp(app_item, sync_item)) - return NULL; + return nullptr; // Fall through. The REMOVE_DEFAULT_APP entry has been deleted, now a new // App entry can be added. @@ -1777,9 +1777,9 @@ changed = true; } - if (sync_item->is_persistent_folder != app_item->is_persistent()) { - DCHECK(!sync_item->is_persistent_folder); - sync_item->is_persistent_folder = app_item->is_persistent(); + if (sync_item->is_system_folder != app_item->is_system_folder()) { + DCHECK(!sync_item->is_system_folder); + sync_item->is_system_folder = app_item->is_system_folder(); // Do not mark the item as changed - the persistent value is not expected to // be persisted to local state, nor synced. Also, it's expected to be set as // part of folder item creation flow, so no further processing should be @@ -1829,7 +1829,7 @@ auto oem_folder = std::make_unique<ChromeAppListItem>(profile_, folder_id, model_updater_.get()); oem_folder->SetChromeName(oem_folder_name_); - oem_folder->SetIsPersistent(true); + oem_folder->SetIsSystemFolder(true); oem_folder->SetChromeIsFolder(true); SyncItem* current_sync_data = FindSyncItem(folder_id); @@ -1865,7 +1865,7 @@ model_updater_.get()); crostini_folder.SetChromeName( l10n_util::GetStringUTF8(IDS_APP_LIST_CROSTINI_DEFAULT_FOLDER_NAME)); - crostini_folder.SetIsPersistent(true); + crostini_folder.SetIsSystemFolder(true); crostini_folder.SetChromeIsFolder(true); // Calculate the Crostini folder's position. @@ -1913,7 +1913,7 @@ new_folder_item->SetMetadata( app_list::GenerateItemMetadataFromSyncItem(*folder_sync_item)); if (IsSystemCreatedSyncFolder(*folder_sync_item)) - new_folder_item->SetIsPersistent(true); + new_folder_item->SetIsSystemFolder(true); model_updater_->AddItem(std::move(new_folder_item)); return true; }
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.h b/chrome/browser/ui/app_list/app_list_syncable_service.h index b80d3140..33e085c 100644 --- a/chrome/browser/ui/app_list/app_list_syncable_service.h +++ b/chrome/browser/ui/app_list/app_list_syncable_service.h
@@ -70,12 +70,11 @@ syncer::StringOrdinal item_pin_ordinal; ash::IconColor item_color; - // Indicates whether the item represents a persistent folder - i.e. a folder - // that was not created explicitly by a user, and which should not be - // removed if it's left with a single child. + // Indicates whether the item represents a system-created folder - i.e. a + // folder that was not created explicitly by a user. // Unlike other properties, this value is not persisted to local state, nor // synced. It reflects the associated ChromeAppListItem state. - bool is_persistent_folder = false; + bool is_system_folder = false; // Whether the `item_ordinal` should be fixed after initial sync data is // received during a user session.
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc index bb2c59b..6aee17ee 100644 --- a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc +++ b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc
@@ -115,8 +115,8 @@ } // Matches a chrome app item if its persistence field is set to true. -MATCHER(IsPersistentApp, "") { - return arg->is_persistent(); +MATCHER(IsSystemFolder, "") { + return arg->is_system_folder(); } // Get a set of all apps in |model|. @@ -921,7 +921,7 @@ IsChromeApp(_, kDummyApp2Name, ash::kCrostiniFolderId), testing::AllOf( IsChromeApp(ash::kCrostiniFolderId, kRootFolderName, ""), - IsPersistentApp()))); + IsSystemFolder()))); } // Test that the Terminal app is removed when Crostini is disabled.
diff --git a/chrome/browser/ui/app_list/chrome_app_list_item.cc b/chrome/browser/ui/app_list/chrome_app_list_item.cc index 951db40..0d09e3e 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_item.cc +++ b/chrome/browser/ui/app_list/chrome_app_list_item.cc
@@ -209,11 +209,11 @@ metadata_->position = position; } -void ChromeAppListItem::SetIsPersistent(bool is_persistent) { - metadata_->is_persistent = is_persistent; +void ChromeAppListItem::SetIsSystemFolder(bool is_system_folder) { + metadata_->is_system_folder = is_system_folder; AppListModelUpdater* updater = model_updater(); if (updater) - updater->SetItemIsPersistent(id(), is_persistent); + updater->SetItemIsSystemFolder(id(), is_system_folder); } void ChromeAppListItem::SetIsPageBreak(bool is_page_break) {
diff --git a/chrome/browser/ui/app_list/chrome_app_list_item.h b/chrome/browser/ui/app_list/chrome_app_list_item.h index 38c9f7f..0c0ce3a 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_item.h +++ b/chrome/browser/ui/app_list/chrome_app_list_item.h
@@ -63,7 +63,7 @@ const std::string& name() const { return metadata_->name; } ash::AppStatus app_status() const { return metadata_->app_status; } bool is_folder() const { return metadata_->is_folder; } - bool is_persistent() const { return metadata_->is_persistent; } + bool is_system_folder() const { return metadata_->is_system_folder; } const gfx::ImageSkia& icon() const { return metadata_->icon; } const ash::IconColor& icon_color() const { return metadata_->icon_color; } bool is_page_break() const { return metadata_->is_page_break; } @@ -83,7 +83,7 @@ void SetAppStatus(ash::AppStatus app_status); void SetFolderId(const std::string& folder_id); void SetIsPageBreak(bool is_page_break); - void SetIsPersistent(bool is_persistent); + void SetIsSystemFolder(bool is_system_folder); void SetIsNewInstall(bool is_new_install); // The following methods won't make changes to Ash and it should be called
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc index 643fe80..f40a43ac 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc +++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
@@ -411,13 +411,13 @@ model_.SetItemMetadata(id, std::move(data)); } -void ChromeAppListModelUpdater::SetItemIsPersistent(const std::string& id, - bool is_persistent) { +void ChromeAppListModelUpdater::SetItemIsSystemFolder(const std::string& id, + bool is_system_folder) { ash::AppListItem* item = model_.FindItem(id); if (!item) return; std::unique_ptr<ash::AppListItemMetadata> data = item->CloneMetadata(); - data->is_persistent = is_persistent; + data->is_system_folder = is_system_folder; model_.SetItemMetadata(id, std::move(data)); }
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.h b/chrome/browser/ui/app_list/chrome_app_list_model_updater.h index c08b4a8..17ddcc0e 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.h +++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.h
@@ -68,7 +68,8 @@ void SetAppStatus(const std::string& id, ash::AppStatus app_status) override; void SetItemPosition(const std::string& id, const syncer::StringOrdinal& new_position) override; - void SetItemIsPersistent(const std::string& id, bool is_persistent) override; + void SetItemIsSystemFolder(const std::string& id, + bool is_system_folder) override; void SetIsNewInstall(const std::string& id, bool is_new_install) override; void SetItemFolderId(const std::string& id, const std::string& folder_id) override;
diff --git a/chrome/browser/ui/browser_dialogs.h b/chrome/browser/ui/browser_dialogs.h index 0de2227..af39e4e4 100644 --- a/chrome/browser/ui/browser_dialogs.h +++ b/chrome/browser/ui/browser_dialogs.h
@@ -228,6 +228,15 @@ AppInstallationAcceptanceCallback callback, PwaInProductHelpState iph_state = PwaInProductHelpState::kNotShown); +// Shows the Web App detailed install dialog. +// The dialog shows app's detailed information including screenshots. Users then +// confirm or cancel install in this dialog. +void ShowWebAppDetailedInstallDialog( + content::WebContents* web_contents, + std::unique_ptr<WebAppInstallInfo> web_app_info, + AppInstallationAcceptanceCallback callback, + PwaInProductHelpState iph_state = PwaInProductHelpState::kNotShown); + // Sets whether |ShowPWAInstallBubble| should accept immediately without any // user interaction. void SetAutoAcceptPWAInstallConfirmationForTesting(bool auto_accept);
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc index b3a5d1b..97aafaf 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
@@ -30,6 +30,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "content/public/test/browser_test.h" +#include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/switches.h" @@ -677,12 +678,156 @@ ASSERT_FALSE(IsWindowFullscreenForTabOrPending()); } +// Tests FullscreenController support for fullscreen capability delegation. +// https://wicg.github.io/capability-delegation/spec.html +// See related wpt/fullscreen/api/delegate-request.https.sub.tentative.html +// TODO(crbug.com/1326575): Test opener->popup etc. messaging; add WPT coverage. +class FullscreenCapabilityDelegationFullscreenControllerInteractiveTest + : public FullscreenControllerInteractiveTest, + public testing::WithParamInterface<bool> { + public: + FullscreenCapabilityDelegationFullscreenControllerInteractiveTest() = default; + + void SetUpCommandLine(base::CommandLine* command_line) override { + FullscreenControllerInteractiveTest::SetUpCommandLine(command_line); + command_line->AppendSwitchASCII(GetParam() + ? switches::kEnableBlinkFeatures + : switches::kDisableBlinkFeatures, + "CapabilityDelegationFullscreenRequest"); + } + + void SetUpOnMainThread() override { + host_resolver()->AddRule("*", "127.0.0.1"); + content::SetupCrossSiteRedirector(embedded_test_server()); + embedded_test_server()->ServeFilesFromSourceDirectory( + "chrome/test/data/capability_delegation"); + } + + // Returns a popup with `url`, opened via JS from `browser`'s active tab. + content::WebContents* OpenPopup(Browser* browser, const GURL& url) { + const std::string script = content::JsReplace( + "window.open($1, '', 'width=500,height=500');", url.spec()); + content::ExecuteScriptAsync( + browser->tab_strip_model()->GetActiveWebContents(), script); + Browser* popup = ui_test_utils::WaitForBrowserToOpen(); + EXPECT_NE(popup, browser); + content::WebContents* popup_contents = + popup->tab_strip_model()->GetActiveWebContents(); + EXPECT_TRUE(WaitForRenderFrameReady(popup_contents->GetMainFrame())); + EXPECT_TRUE(content::WaitForLoadStop(popup_contents)); + return popup_contents; + } + + // Run `script` on `initiator` with `options`, and compares `expected_result` + // with the script result and the `target` browser's fullscreen state. + void ExecScriptAndCheckFullscreen(content::WebContents* initiator, + Browser* target, + const std::string& script, + int options, + bool expected_result) { + FullscreenNotificationObserver fullscreen_observer(target); + EXPECT_EQ(expected_result, EvalJs(initiator, script, options)); + if (expected_result) + fullscreen_observer.Wait(); + EXPECT_EQ(expected_result, target->window()->IsFullscreen()); + } +}; + +IN_PROC_BROWSER_TEST_P( + FullscreenCapabilityDelegationFullscreenControllerInteractiveTest, + CapabilityDelegationSameOriginPopup) { + EXPECT_TRUE(embedded_test_server()->Start()); + + // Navigate to a page that requests fullscreen and replies on message receipt. + const GURL receiver_url = embedded_test_server()->GetURL( + "a.com", "/fullscreen_request_delegation_receiver.html"); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), receiver_url)); + + // Open a same-origin popup that delegates fullscreen and reports the result. + const GURL initiator_url = embedded_test_server()->GetURL( + "a.com", "/fullscreen_request_delegation_initiator.html"); + content::WebContents* popup = OpenPopup(browser(), initiator_url); + + const std::string targetOrigin = + embedded_test_server()->GetOrigin("a.com").Serialize(); + const std::string script_without_delegation = content::JsReplace( + "delegateCapability(window.opener, $1, '')", targetOrigin); + const std::string script_with_delegation = content::JsReplace( + "delegateCapability(window.opener, $1, 'fullscreen')", targetOrigin); + + // Fullscreen is only granted with user activation and explicit delegation. + ExecScriptAndCheckFullscreen(popup, browser(), script_without_delegation, + content::EXECUTE_SCRIPT_NO_USER_GESTURE, false); + ExecScriptAndCheckFullscreen(popup, browser(), script_with_delegation, + content::EXECUTE_SCRIPT_NO_USER_GESTURE, false); + ExecScriptAndCheckFullscreen(popup, browser(), script_without_delegation, + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, false); + ExecScriptAndCheckFullscreen(popup, browser(), script_with_delegation, + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + GetParam()); +} + +IN_PROC_BROWSER_TEST_P( + FullscreenCapabilityDelegationFullscreenControllerInteractiveTest, + CapabilityDelegationCrossOriginPopup) { + EXPECT_TRUE(embedded_test_server()->Start()); + + // Navigate to a page that requests fullscreen and replies on message receipt. + const GURL receiver_url = embedded_test_server()->GetURL( + "a.com", "/fullscreen_request_delegation_receiver.html"); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), receiver_url)); + + // Open a cross-origin popup that delegates fullscreen and reports the result. + const GURL initiator_url = embedded_test_server()->GetURL( + "b.com", "/fullscreen_request_delegation_initiator.html"); + content::WebContents* popup = OpenPopup(browser(), initiator_url); + + const std::string targetOrigin = + embedded_test_server()->GetOrigin("a.com").Serialize(); + const std::string script_without_delegation = content::JsReplace( + "delegateCapability(window.opener, $1, '')", targetOrigin); + const std::string script_with_delegation = content::JsReplace( + "delegateCapability(window.opener, $1, 'fullscreen')", targetOrigin); + + // Fullscreen is only granted with user activation and explicit delegation. + ExecScriptAndCheckFullscreen(popup, browser(), script_without_delegation, + content::EXECUTE_SCRIPT_NO_USER_GESTURE, false); + ExecScriptAndCheckFullscreen(popup, browser(), script_with_delegation, + content::EXECUTE_SCRIPT_NO_USER_GESTURE, false); + ExecScriptAndCheckFullscreen(popup, browser(), script_without_delegation, + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, false); + ExecScriptAndCheckFullscreen(popup, browser(), script_with_delegation, + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + GetParam()); +} + +INSTANTIATE_TEST_SUITE_P( + , + FullscreenCapabilityDelegationFullscreenControllerInteractiveTest, + ::testing::Bool()); + // Tests FullscreenController support of Multi-Screen Window Placement features. // Sites with the Window Placement permission can request fullscreen on a // specific screen, move fullscreen windows to different displays, and more. class MultiScreenFullscreenControllerInteractiveTest : public FullscreenControllerInteractiveTest { public: + void SetUp() override { +#if !BUILDFLAG(IS_CHROMEOS_ASH) + screen_.display_list().AddDisplay({1, gfx::Rect(100, 100, 801, 802)}, + display::DisplayList::Type::PRIMARY); + display::Screen::SetScreenInstance(&screen_); +#endif + FullscreenControllerInteractiveTest::SetUp(); + } + + void TearDown() override { + FullscreenControllerInteractiveTest::TearDown(); +#if !BUILDFLAG(IS_CHROMEOS_ASH) + display::Screen::SetScreenInstance(nullptr); +#endif + } + // Perform common setup operations for multi-screen fullscreen testing: // Mock a screen with two displays, move the browser onto the first display, // and auto-grant the Window Placement permission on its active tab. @@ -692,12 +837,8 @@ display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager()) .UpdateDisplay("0+0-800x800,800+0-800x800"); #else - original_screen_ = display::Screen::GetScreen(); - screen_.display_list().AddDisplay({1, gfx::Rect(0, 0, 800, 800)}, - display::DisplayList::Type::PRIMARY); screen_.display_list().AddDisplay({2, gfx::Rect(800, 0, 800, 800)}, display::DisplayList::Type::NOT_PRIMARY); - display::Screen::SetScreenInstance(&screen_); #endif // BUILDFLAG(IS_CHROMEOS_ASH) EXPECT_EQ(2, display::Screen::GetScreen()->GetNumDisplays()); @@ -720,14 +861,6 @@ return tab; } - void TearDown() override { -#if !BUILDFLAG(IS_CHROMEOS_ASH) - if (original_screen_) - display::Screen::SetScreenInstance(original_screen_); -#endif // !BUILDFLAG(IS_CHROMEOS_ASH) - FullscreenControllerInteractiveTest::TearDown(); - } - // Wait for a JS content fullscreen change with the given script and options. void RequestContentFullscreenFromScript( const std::string& eval_js_script, @@ -801,14 +934,12 @@ #if !BUILDFLAG(IS_CHROMEOS_ASH) display::DisplayList& display_list() { return screen_.display_list(); } #endif // !BUILDFLAG(IS_CHROMEOS_ASH) - private: base::test::ScopedFeatureList feature_list_{ blink::features::kWindowPlacement}; #if !BUILDFLAG(IS_CHROMEOS_ASH) - raw_ptr<display::Screen> original_screen_ = nullptr; display::ScreenBase screen_; -#endif // !BUILDFLAG(IS_CHROMEOS_ASH) +#endif }; // TODO(crbug.com/1034772): Disabled on Windows, where views::FullscreenHandler
diff --git a/chrome/browser/ui/views/DEPS b/chrome/browser/ui/views/DEPS index 273916b..0bd5884 100644 --- a/chrome/browser/ui/views/DEPS +++ b/chrome/browser/ui/views/DEPS
@@ -3,6 +3,7 @@ "+components/fullscreen_control", "+components/live_caption", "+components/services/app_service/public", + "+components/url_formatter", "+components/user_education/views", "+third_party/libaddressinput", "+services/tracing/public",
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc index e8413c7..90d0e06 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -1079,6 +1079,14 @@ } } +void BookmarkBarView::ChildPreferredSizeChanged(views::View* child) { + // only rerender + if (child != saved_tab_group_bar_) + return; + + InvalidateDrop(); +} + void BookmarkBarView::GetAccessibleNodeData(ui::AXNodeData* node_data) { node_data->role = ax::mojom::Role::kToolbar; node_data->SetName(l10n_util::GetStringUTF8(IDS_ACCNAME_BOOKMARKS));
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h index bfd86c5..58626c4 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
@@ -17,6 +17,7 @@ #include "chrome/browser/ui/bookmarks/bookmark_stats.h" #include "chrome/browser/ui/tabs/tab_group_theme.h" #include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_observer.h" +#include "chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.h" #include "components/bookmarks/browser/bookmark_model_observer.h" #include "components/bookmarks/browser/bookmark_node_data.h" #include "components/prefs/pref_change_registrar.h" @@ -171,7 +172,8 @@ views::View::DropCallback GetDropCallback( const ui::DropTargetEvent& event) override; void OnThemeChanged() override; - void VisibilityChanged(View* starting_from, bool is_visible) override; + void VisibilityChanged(views::View* starting_from, bool is_visible) override; + void ChildPreferredSizeChanged(views::View* child) override; // AccessiblePaneView: void GetAccessibleNodeData(ui::AXNodeData* node_data) override; @@ -319,7 +321,7 @@ // Returns the node corresponding to |sender|, which is one of the // |bookmark_buttons_|. - const bookmarks::BookmarkNode* GetNodeForSender(View* sender) const; + const bookmarks::BookmarkNode* GetNodeForSender(views::View* sender) const; // Writes a BookmarkNodeData for node to data. void WriteBookmarkDragData(const bookmarks::BookmarkNode* node,
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_unittest.cc index 1afacdb16..7e68b783 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_unittest.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_unittest.cc
@@ -22,6 +22,8 @@ #include "chrome/browser/ui/app_list/app_list_util.h" #include "chrome/browser/ui/bookmarks/bookmark_utils.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.h" +#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view_test_helper.h" #include "chrome/browser/ui/views/native_widget_factory.h" @@ -516,6 +518,38 @@ EXPECT_TRUE(test_helper_->saved_tab_group_bar()->page_navigator()); } +TEST_F(BookmarkBarViewTest, OnSavedTabGroupUpdateBookmarkBarCallsLayout) { + SavedTabGroupKeyedService* keyed_service = + SavedTabGroupServiceFactory::GetForProfile(browser()->profile()); + ASSERT_TRUE(keyed_service); + ASSERT_TRUE(keyed_service->model()); + + // Add 3 saved tab groups. + keyed_service->model()->Add(SavedTabGroup( + tab_groups::TabGroupId::GenerateNew(), std::u16string(u"tab group 1"), + tab_groups::TabGroupColorId::kGrey, {})); + + tab_groups::TabGroupId button_2_id = tab_groups::TabGroupId::GenerateNew(); + keyed_service->model()->Add( + SavedTabGroup(button_2_id, std::u16string(u"tab group 2"), + tab_groups::TabGroupColorId::kGrey, {})); + + keyed_service->model()->Add(SavedTabGroup( + tab_groups::TabGroupId::GenerateNew(), std::u16string(u"tab group 3"), + tab_groups::TabGroupColorId::kGrey, {})); + + // Save the position of the 3rd button. + ASSERT_EQ(3u, test_helper_->saved_tab_group_bar()->children().size()); + const auto* button_3 = test_helper_->saved_tab_group_bar()->children()[2]; + gfx::Rect bounds_in_screen = button_3->GetBoundsInScreen(); + + // Remove the middle tab group. + keyed_service->model()->Remove(button_2_id); + + // Make sure the positions of the buttons were updated. + EXPECT_EQ(bounds_in_screen, button_3->GetBoundsInScreen()); +} + TEST_F(BookmarkBarViewInWidgetTest, UpdateTooltipText) { widget()->Show();
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc index ae62eaa..c38304a 100644 --- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc +++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc
@@ -71,22 +71,26 @@ void SavedTabGroupBar::SavedTabGroupAdded(const SavedTabGroup& group, int index) { AddTabGroupButton(group, index); + PreferredSizeChanged(); } void SavedTabGroupBar::SavedTabGroupRemoved(int index) { RemoveTabGroupButton(index); + PreferredSizeChanged(); } void SavedTabGroupBar::SavedTabGroupUpdated(const SavedTabGroup& group, int index) { RemoveTabGroupButton(index); AddTabGroupButton(group, index); + PreferredSizeChanged(); } void SavedTabGroupBar::SavedTabGroupMoved(const SavedTabGroup& group, int old_index, int new_index) { ReorderChildView(children().at(old_index), new_index); + PreferredSizeChanged(); } // TODO dpenning: Support the state of the SavedTabGroup open in a tab strip
diff --git a/chrome/browser/ui/views/commerce/ntp_discount_consent_dialog_view.cc b/chrome/browser/ui/views/commerce/ntp_discount_consent_dialog_view.cc new file mode 100644 index 0000000..ff358af --- /dev/null +++ b/chrome/browser/ui/views/commerce/ntp_discount_consent_dialog_view.cc
@@ -0,0 +1,104 @@ +// Copyright 2022 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/ui/views/commerce/ntp_discount_consent_dialog_view.h" + +#include "base/callback_helpers.h" +#include "chrome/browser/cart/chrome_cart.mojom.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "components/constrained_window/constrained_window_views.h" +#include "ui/views/widget/widget.h" +#include "ui/views/window/dialog_delegate.h" + +#include "chrome/browser/ui/views/accessibility/theme_tracking_non_accessible_image_view.h" +#include "chrome/browser/ui/views/chrome_layout_provider.h" +#include "chrome/browser/ui/views/chrome_typography.h" +#include "chrome/grit/theme_resources.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/box_layout.h" + +namespace { +// Spacing between child of the Discount Consent Dialog View +constexpr int kChildSpacing = 24; +} // namespace + +// static +void NtpDiscountConsentDialogView::Show(Browser* browser, + ActionCallback callback) { + constrained_window::CreateBrowserModalDialogViews( + std::make_unique<NtpDiscountConsentDialogView>(std::move(callback)), + browser->window()->GetNativeWindow()) + ->Show(); +} + +NtpDiscountConsentDialogView::NtpDiscountConsentDialogView( + ActionCallback callback) + : callback_(std::move(callback)) { + // Set up dialog properties. + SetModalType(ui::MODAL_TYPE_WINDOW); + SetShowCloseButton(false); + SetOwnedByWidget(true); + // TODO(meiliang@): Set text for the button. + SetButtons(ui::DIALOG_BUTTON_CANCEL | ui::DIALOG_BUTTON_OK); + set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric( + DISTANCE_LARGE_MODAL_DIALOG_PREFERRED_WIDTH)); + + SetAcceptCallback(base::BindOnce(&NtpDiscountConsentDialogView::OnAccept, + base::Unretained(this))); + SetCancelCallback(base::BindOnce(&NtpDiscountConsentDialogView::OnReject, + base::Unretained(this))); + SetCloseCallback(base::BindOnce(&NtpDiscountConsentDialogView::OnDismiss, + base::Unretained(this))); + + // Set up dialog content view. + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical, + ChromeLayoutProvider::Get()->GetInsetsMetric(views::INSETS_DIALOG), + kChildSpacing)); + + ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); + + AddChildView(std::make_unique<ThemeTrackingNonAccessibleImageView>( + *bundle.GetImageSkiaNamed(IDR_NTP_CART_DISCOUNT_CONSENT_LIGHT), + *bundle.GetImageSkiaNamed(IDR_NTP_CART_DISCOUNT_CONSENT_DARK), + base::BindRepeating(&NtpDiscountConsentDialogView::GetBackgroundColor, + base::Unretained(this)))); + + auto title_label = std::make_unique<views::Label>( + l10n_util::GetStringUTF16(IDS_NATIVE_NTP_CART_DISCOUNT_CONSENT_TITLE), + CONTEXT_HEADLINE, views::style::STYLE_PRIMARY); + auto* title = AddChildView(std::move(title_label)); + title->SetMultiLine(true); + + auto consent_label = std::make_unique<views::Label>( + l10n_util::GetStringUTF16(IDS_NATIVE_NTP_CART_DISCOUNT_CONSENT_BODY), + views::style::CONTEXT_DIALOG_BODY_TEXT, views::style::STYLE_SECONDARY); + auto* consent = AddChildView(std::move(consent_label)); + consent->SetMultiLine(true); +} + +NtpDiscountConsentDialogView::~NtpDiscountConsentDialogView() = default; + +SkColor NtpDiscountConsentDialogView::GetBackgroundColor() { + return GetWidget()->GetColorProvider()->GetColor(ui::kColorDialogBackground); +} + +void NtpDiscountConsentDialogView::OnAccept() { + assert(callback_); + std::move(callback_).Run(chrome_cart::mojom::ConsentStatus::ACCEPTED); +} + +void NtpDiscountConsentDialogView::OnReject() { + assert(callback_); + std::move(callback_).Run(chrome_cart::mojom::ConsentStatus::REJECTED); +} + +void NtpDiscountConsentDialogView::OnDismiss() { + assert(callback_); + std::move(callback_).Run(chrome_cart::mojom::ConsentStatus::DISMISSED); +}
diff --git a/chrome/browser/ui/views/commerce/ntp_discount_consent_dialog_view.h b/chrome/browser/ui/views/commerce/ntp_discount_consent_dialog_view.h new file mode 100644 index 0000000..a8cdd63 --- /dev/null +++ b/chrome/browser/ui/views/commerce/ntp_discount_consent_dialog_view.h
@@ -0,0 +1,34 @@ +// Copyright 2022 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_UI_VIEWS_COMMERCE_NTP_DISCOUNT_CONSENT_DIALOG_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_COMMERCE_NTP_DISCOUNT_CONSENT_DIALOG_VIEW_H_ + +#include "base/callback_helpers.h" +#include "chrome/browser/cart/chrome_cart.mojom.h" +#include "ui/views/window/dialog_delegate.h" + +class Browser; + +class NtpDiscountConsentDialogView : public views::DialogDelegateView { + public: + using ActionCallback = + base::OnceCallback<void(chrome_cart::mojom::ConsentStatus)>; + static void Show(Browser* browser, ActionCallback callback); + explicit NtpDiscountConsentDialogView(ActionCallback callback); + ~NtpDiscountConsentDialogView() override; + + private: + ActionCallback callback_; + + SkColor GetBackgroundColor(); + // Called when the accept button is clicked. + void OnAccept(); + // Called when the reject button is clicked. + void OnReject(); + // Called when the Esc key is used. + void OnDismiss(); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_COMMERCE_NTP_DISCOUNT_CONSENT_DIALOG_VIEW_H_
diff --git a/chrome/browser/ui/views/commerce/ntp_discount_consent_dialog_view_browsertest.cc b/chrome/browser/ui/views/commerce/ntp_discount_consent_dialog_view_browsertest.cc new file mode 100644 index 0000000..aff3424c --- /dev/null +++ b/chrome/browser/ui/views/commerce/ntp_discount_consent_dialog_view_browsertest.cc
@@ -0,0 +1,33 @@ +// Copyright 2022 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/ui/views/commerce/ntp_discount_consent_dialog_view.h" + +#include "chrome/browser/ui/test/test_browser_dialog.h" +#include "content/public/test/browser_test.h" + +// Test harness for integration tests using NtpDiscountConsentView. +class NtpDiscountConsentDialogViewBrowserTest : public DialogBrowserTest { + public: + NtpDiscountConsentDialogViewBrowserTest() = default; + + NtpDiscountConsentDialogViewBrowserTest( + const NtpDiscountConsentDialogViewBrowserTest&) = delete; + NtpDiscountConsentDialogViewBrowserTest& operator=( + const NtpDiscountConsentDialogViewBrowserTest&) = delete; + + // DialogBrowserTest: + void ShowUi(const std::string& name) override { + NtpDiscountConsentDialogView::Show( + browser(), + base::BindOnce([](chrome_cart::mojom::ConsentStatus status) {})); + } +}; + +// Shows the dialog for bookmarking all tabs. This shows a BookmarkEditorView +// dialog, with a tree view, where a user can rename and select a parent folder. +IN_PROC_BROWSER_TEST_F(NtpDiscountConsentDialogViewBrowserTest, + InvokeUi_default) { + ShowAndVerifyUi(); +}
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view.cc b/chrome/browser/ui/views/intent_picker_bubble_view.cc index 9c53c60..d06b4aa3dcb 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view.cc +++ b/chrome/browser/ui/views/intent_picker_bubble_view.cc
@@ -60,8 +60,6 @@ key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_LEFT; } -} // namespace - // IntentPickerLabelButton // A button that represents a candidate intent handler. @@ -103,6 +101,131 @@ BEGIN_METADATA(IntentPickerLabelButton, views::LabelButton) END_METADATA +class IntentPickerAppListView + : public IntentPickerBubbleView::IntentPickerAppsView { + public: + METADATA_HEADER(IntentPickerAppListView); + + IntentPickerAppListView( + const std::vector<IntentPickerBubbleView::AppInfo>& apps, + base::RepeatingCallback<void(size_t, bool)> selected_callback) + : selected_callback_(selected_callback) { + auto scrollable_view = std::make_unique<views::View>(); + scrollable_view->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical)); + scrollable_view->SetID(IntentPickerBubbleView::ViewId::kItemContainer); + + for (size_t i = 0; i < apps.size(); i++) { + auto app_button = std::make_unique<IntentPickerLabelButton>( + base::BindRepeating(&IntentPickerAppListView::OnAppPressed, + base::Unretained(this), i), + apps[i].icon_model, apps[i].display_name); + scrollable_view->AddChildViewAt(std::move(app_button), i); + } + + SetBackgroundThemeColorId(ui::kColorBubbleBackground); + SetContents(std::move(scrollable_view)); + DCHECK(!contents()->children().empty()); + const int row_height = + contents()->children().front()->GetPreferredSize().height(); + // TODO(djacobo): Replace this limit to correctly reflect the UI mocks, + // which now instead of limiting the results to 3.5 will allow whatever fits + // in 256pt. Using |kMaxAppResults| as a measure of how many apps we want to + // show. + ClipHeightTo(row_height, (apps::kMaxAppResults + 0.5) * row_height); + } + + ~IntentPickerAppListView() override = default; + + void SetSelectedIndex(size_t index) override { + SetSelectedAppIndex(index, nullptr); + } + + size_t GetSelectedIndex() const override { return selected_app_index_; } + + void OnKeyEvent(ui::KeyEvent* event) override { + if (!IsKeyboardCodeArrow(event->key_code()) || + event->type() != ui::ET_KEY_RELEASED) + return; + + int delta = 0; + switch (event->key_code()) { + case ui::VKEY_UP: + delta = -1; + break; + case ui::VKEY_DOWN: + delta = 1; + break; + case ui::VKEY_LEFT: + delta = base::i18n::IsRTL() ? 1 : -1; + break; + case ui::VKEY_RIGHT: + delta = base::i18n::IsRTL() ? -1 : 1; + break; + default: + NOTREACHED(); + break; + } + + SetSelectedAppIndex(CalculateNextAppIndex(delta), nullptr); + AdjustScrollViewVisibleRegion(); + + ScrollView::OnKeyEvent(event); + } + + private: + void OnAppPressed(size_t index, const ui::Event& event) { + SetSelectedAppIndex(index, &event); + } + + void SetSelectedAppIndex(size_t index, const ui::Event* event) { + GetIntentPickerLabelButtonAt(selected_app_index_) + ->MarkAsUnselected(nullptr); + selected_app_index_ = index; + GetIntentPickerLabelButtonAt(selected_app_index_)->MarkAsSelected(event); + + bool accepted = false; + if (event && ((event->IsMouseEvent() && + event->AsMouseEvent()->GetClickCount() == 2) || + (event->IsGestureEvent() && + event->AsGestureEvent()->details().tap_count() == 2))) { + accepted = true; + } + + selected_callback_.Run(index, accepted); + } + + size_t CalculateNextAppIndex(int delta) { + size_t size = contents()->children().size(); + return static_cast<size_t>((selected_app_index_ + delta) % size); + } + + void AdjustScrollViewVisibleRegion() { + views::ScrollBar* bar = vertical_scroll_bar(); + if (bar) { + const int row_height = + contents()->children().front()->GetPreferredSize().height(); + ScrollToPosition(bar, (selected_app_index_ - 1) * row_height); + } + } + + IntentPickerLabelButton* GetIntentPickerLabelButtonAt(size_t index) { + const auto& children = contents()->children(); + DCHECK_LT(index, children.size()); + return static_cast<IntentPickerLabelButton*>(children[index]); + } + + base::RepeatingCallback<void(size_t, bool)> selected_callback_; + + size_t selected_app_index_ = 0; +}; + +BEGIN_METADATA(IntentPickerAppListView, views::ScrollView) +ADD_PROPERTY_METADATA(size_t, SelectedIndex) +END_METADATA + +} // namespace + // static IntentPickerBubbleView* IntentPickerBubbleView::intent_picker_bubble_ = nullptr; @@ -126,7 +249,6 @@ show_remember_selection, initiating_origin); if (highlighted_button) intent_picker_bubble_->SetHighlightedButton(highlighted_button); - intent_picker_bubble_->set_margins(gfx::Insets()); intent_picker_bubble_->Initialize(); views::Widget* widget = views::BubbleDialogDelegateView::CreateBubble(intent_picker_bubble_); @@ -138,8 +260,7 @@ DCHECK(intent_picker_bubble_->HasCandidates()); widget->Show(); - intent_picker_bubble_->GetIntentPickerLabelButtonAt(0)->MarkAsSelected( - nullptr); + intent_picker_bubble_->SetSelectedIndex(0); return widget; } @@ -157,10 +278,10 @@ void IntentPickerBubbleView::OnDialogAccepted() { bool should_persist = remember_selection_checkbox_ && remember_selection_checkbox_->GetChecked(); - RunCallbackAndCloseBubble(app_info_[selected_app_tag_].launch_name, - app_info_[selected_app_tag_].type, - apps::IntentPickerCloseReason::OPEN_APP, - should_persist); + auto selected_index = GetSelectedIndex(); + RunCallbackAndCloseBubble( + app_info_[selected_index].launch_name, app_info_[selected_index].type, + apps::IntentPickerCloseReason::OPEN_APP, should_persist); } void IntentPickerBubbleView::OnDialogCancelled() { @@ -184,6 +305,15 @@ return true; } +void IntentPickerBubbleView::SetSelectedIndex(size_t index) { + DCHECK_LT(index, app_info_.size()); + apps_view_->SetSelectedIndex(index); +} + +size_t IntentPickerBubbleView::GetSelectedIndex() const { + return apps_view_->GetSelectedIndex(); +} + std::u16string IntentPickerBubbleView::GetWindowTitle() const { if (bubble_type_ == BubbleType::kClickToCall) { return l10n_util::GetStringUTF16( @@ -237,6 +367,8 @@ // intent_picker_helpers, they will get closed on each navigation start and // should stay open until after navigation finishes. SetCloseOnMainFrameOriginNavigation(bubble_type == BubbleType::kClickToCall); + // Margins are manually added in Initialize(). + set_margins(gfx::Insets()); } IntentPickerBubbleView::~IntentPickerBubbleView() { @@ -251,77 +383,15 @@ false); } -void IntentPickerBubbleView::AppButtonPressed(size_t index, - const ui::Event& event) { - SetSelectedAppIndex(index, &event); - if ((event.IsMouseEvent() && event.AsMouseEvent()->GetClickCount() == 2) || - (event.IsGestureEvent() && - event.AsGestureEvent()->details().tap_count() == 2)) { +void IntentPickerBubbleView::OnAppSelected(size_t index, bool accepted) { + UpdateCheckboxState(index); + + if (accepted) { AcceptDialog(); } } -void IntentPickerBubbleView::ArrowButtonPressed(size_t index) { - SetSelectedAppIndex(index, nullptr); - AdjustScrollViewVisibleRegion(); -} - -void IntentPickerBubbleView::OnKeyEvent(ui::KeyEvent* event) { - if (!IsKeyboardCodeArrow(event->key_code()) || - event->type() != ui::ET_KEY_RELEASED) - return; - - int delta = 0; - switch (event->key_code()) { - case ui::VKEY_UP: - delta = -1; - break; - case ui::VKEY_DOWN: - delta = 1; - break; - case ui::VKEY_LEFT: - delta = base::i18n::IsRTL() ? 1 : -1; - break; - case ui::VKEY_RIGHT: - delta = base::i18n::IsRTL() ? -1 : 1; - break; - default: - NOTREACHED(); - break; - } - ArrowButtonPressed(CalculateNextAppIndex(delta)); - - View::OnKeyEvent(event); -} - void IntentPickerBubbleView::Initialize() { - // Creates a view to hold the views for each app. - auto scrollable_view = std::make_unique<views::View>(); - scrollable_view->SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical)); - scrollable_view->SetID(ViewId::kItemContainer); - - for (size_t i = 0; i < app_info_.size(); i++) { - auto app_button = std::make_unique<IntentPickerLabelButton>( - base::BindRepeating(&IntentPickerBubbleView::AppButtonPressed, - base::Unretained(this), i), - app_info_[i].icon_model, app_info_[i].display_name); - scrollable_view->AddChildViewAt(std::move(app_button), i); - } - - auto scroll_view = std::make_unique<views::ScrollView>(); - scroll_view->SetBackgroundThemeColorId(ui::kColorBubbleBackground); - scroll_view->SetContents(std::move(scrollable_view)); - DCHECK(!scroll_view->contents()->children().empty()); - const int row_height = - scroll_view->contents()->children().front()->GetPreferredSize().height(); - // TODO(djacobo): Replace this limit to correctly reflect the UI mocks, which - // now instead of limiting the results to 3.5 will allow whatever fits in - // 256pt. Using |kMaxAppResults| as a measure of how many apps we want to - // show. - scroll_view->ClipHeightTo(row_height, - (apps::kMaxAppResults + 0.5) * row_height); - const bool show_origin = initiating_origin_ && !initiating_origin_->IsSameOriginWith( @@ -363,7 +433,11 @@ subtitle->SetMaximumWidth(kMaxDialogWidth - insets.width()); } - scroll_view_ = AddChildView(std::move(scroll_view)); + // Create a container for all of the individual app views. + auto list_view = std::make_unique<IntentPickerAppListView>( + app_info_, base::BindRepeating(&IntentPickerBubbleView::OnAppSelected, + base::Unretained(this))); + apps_view_ = AddChildView(std::move(list_view)); if (show_origin) { std::u16string origin_text = l10n_util::GetStringFUTF16( @@ -391,16 +465,9 @@ IDS_INTENT_PICKER_BUBBLE_VIEW_REMEMBER_SELECTION))); remember_selection_checkbox_->SetID(ViewId::kRememberCheckbox); remember_selection_checkbox_->SetProperty(views::kMarginsKey, insets); - UpdateCheckboxState(); } } -IntentPickerLabelButton* IntentPickerBubbleView::GetIntentPickerLabelButtonAt( - size_t index) { - const auto& children = scroll_view_->contents()->children(); - return static_cast<IntentPickerLabelButton*>(children[index]); -} - bool IntentPickerBubbleView::HasCandidates() const { return !app_info_.empty(); } @@ -423,39 +490,10 @@ } } -void IntentPickerBubbleView::AdjustScrollViewVisibleRegion() { - const views::ScrollBar* bar = scroll_view_->vertical_scroll_bar(); - if (bar) { - const int row_height = scroll_view_->contents() - ->children() - .front() - ->GetPreferredSize() - .height(); - scroll_view_->ScrollToPosition(const_cast<views::ScrollBar*>(bar), - (selected_app_tag_ - 1) * row_height); - } -} - -void IntentPickerBubbleView::SetSelectedAppIndex(size_t index, - const ui::Event* event) { - DCHECK(HasCandidates()); - DCHECK_LT(index, app_info_.size()); - - GetIntentPickerLabelButtonAt(selected_app_tag_)->MarkAsUnselected(nullptr); - selected_app_tag_ = index; - GetIntentPickerLabelButtonAt(selected_app_tag_)->MarkAsSelected(event); - UpdateCheckboxState(); -} - -size_t IntentPickerBubbleView::CalculateNextAppIndex(int delta) { - size_t size = scroll_view_->contents()->children().size(); - return static_cast<size_t>((selected_app_tag_ + size + delta) % size); -} - -void IntentPickerBubbleView::UpdateCheckboxState() { +void IntentPickerBubbleView::UpdateCheckboxState(size_t index) { if (!remember_selection_checkbox_) return; - auto selected_app_type = app_info_[selected_app_tag_].type; + auto selected_app_type = app_info_[index].type; bool should_enable = true; if (selected_app_type == apps::PickerEntryType::kDevice) { // TODO(crbug.com/1000037): Allow persisting remote devices.
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view.h b/chrome/browser/ui/views/intent_picker_bubble_view.h index 6c16f44..10f590f 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view.h +++ b/chrome/browser/ui/views/intent_picker_bubble_view.h
@@ -19,6 +19,7 @@ #include "ui/base/accelerators/accelerator.h" #include "ui/gfx/image/image.h" #include "ui/views/animation/ink_drop_state.h" +#include "ui/views/controls/scroll_view.h" #include "url/origin.h" namespace content { @@ -31,12 +32,6 @@ class Widget; } // namespace views -namespace ui { -class Event; -} // namespace ui - -class IntentPickerLabelButton; - // A bubble that displays a list of applications (icons and names), after the // list the UI displays a checkbox to allow the user remember the selection and // after that a couple of buttons for either using the selected app or just @@ -108,6 +103,17 @@ BubbleType bubble_type() const { return bubble_type_; } + void SetSelectedIndex(size_t index); + size_t GetSelectedIndex() const; + + // A ScrollView which contains a list of apps. This view manages the selection + // state for the dialog. + class IntentPickerAppsView : public views::ScrollView { + public: + virtual void SetSelectedIndex(size_t index) = 0; + virtual size_t GetSelectedIndex() const = 0; + }; + const std::vector<AppInfo>& app_info_for_testing() const { return app_info_; } protected: @@ -121,14 +127,9 @@ // views::BubbleDialogDelegateView overrides: void OnWidgetDestroying(views::Widget* widget) override; - void AppButtonPressed(size_t index, const ui::Event& event); - - // Similar to AppButtonPressed, except this controls the up/down/right/left - // input while focusing on the |scroll_view_|. - void ArrowButtonPressed(size_t index); - - // ui::EventHandler overrides: - void OnKeyEvent(ui::KeyEvent* event) override; + // Called when the app at |index| is selected in the app list. If |accepted| + // is true, the dialog should be immediately accepted with that app selected. + void OnAppSelected(size_t index, bool accepted); void Initialize(); @@ -136,10 +137,6 @@ void OnDialogCancelled(); void OnDialogClosed(); - // Retrieves the IntentPickerLabelButton* contained at position |index| from - // the internal ScrollView. - IntentPickerLabelButton* GetIntentPickerLabelButtonAt(size_t index); - // Runs |intent_picker_cb_| and closes the current bubble view. void RunCallbackAndCloseBubble(const std::string& launch_name, apps::PickerEntryType entry_type, @@ -152,18 +149,8 @@ // return false. bool HasCandidates() const; - // Ensure the selected app is within the visible region of the ScrollView. - void AdjustScrollViewVisibleRegion(); - - // Set the new app selection, use the |event| (if provided) to show a more - // accurate ripple effect w.r.t. the user's input. - void SetSelectedAppIndex(size_t index, const ui::Event* event); - - // Calculate the next app to select given the current selection and |delta|. - size_t CalculateNextAppIndex(int delta); - // Updates whether the persistence checkbox is enabled or not. - void UpdateCheckboxState(); + void UpdateCheckboxState(size_t index); // Clears this bubble from being considered the currently open bubble. void ClearIntentPickerBubbleView(); @@ -173,13 +160,10 @@ // Callback used to respond to AppsNavigationThrottle. IntentPickerResponse intent_picker_cb_; - // Pre-select the first app on the list. - size_t selected_app_tag_ = 0; - - raw_ptr<views::ScrollView> scroll_view_ = nullptr; - std::vector<AppInfo> app_info_; + raw_ptr<IntentPickerAppsView> apps_view_ = nullptr; + raw_ptr<views::Checkbox> remember_selection_checkbox_ = nullptr; // When true, enables an alternate layout which presents apps as a grid
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc index dce1fa36..aaf0346 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc
@@ -269,33 +269,6 @@ EXPECT_FALSE(intent_picker_view->GetVisible()); } -IN_PROC_BROWSER_TEST_F(IntentPickerBubbleViewBrowserTest, DoubleClickOpensApp) { - auto app_id = InstallTestWebApp(GetAppUrlHost(), GetAppScopePath()); - - const GURL in_scope_url = - https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), in_scope_url)); - - views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{}, - "IntentPickerBubbleView"); - GetIntentPickerIcon()->ExecuteForTesting(); - waiter.WaitIfNeededAndGet(); - ASSERT_TRUE(intent_picker_bubble()); - EXPECT_TRUE(intent_picker_bubble()->GetVisible()); - - auto event_generator = ui::test::EventGenerator( - views::GetRootWindow(intent_picker_bubble()->GetWidget())); - auto* container = intent_picker_bubble()->GetViewByID( - IntentPickerBubbleView::ViewId::kItemContainer); - ASSERT_GT(container->children().size(), 0ul); - event_generator.MoveMouseTo( - container->children()[0]->GetBoundsInScreen().CenterPoint()); - event_generator.DoubleClickLeftButton(); - - Browser* app_browser = BrowserList::GetInstance()->GetLastActive(); - EXPECT_TRUE(web_app::AppBrowserController::IsForWebApp(app_browser, app_id)); -} - INSTANTIATE_TEST_SUITE_P( All, IntentPickerBubbleViewBrowserTest,
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc b/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc index e25059d..117a6b7 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc +++ b/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc
@@ -20,11 +20,13 @@ #include "chrome/common/chrome_features.h" #include "chrome/grit/generated_resources.h" #include "chrome/test/views/chrome_views_test_base.h" +#include "components/services/app_service/public/cpp/intent_util.h" #include "content/public/browser/web_contents.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/image_model.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/events/test/event_generator.h" #include "ui/gfx/image/image.h" #include "ui/strings/grit/ui_strings.h" @@ -154,16 +156,23 @@ .size(); } - // Dummy method to be called upon bubble closing. - void OnBubbleClosed(const std::string& selected_app_package, + void OnBubbleClosed(const std::string& selected_app_launch_name, apps::PickerEntryType entry_type, apps::IntentPickerCloseReason close_reason, - bool should_persist) {} + bool should_persist) { + last_selected_launch_name_ = selected_app_launch_name; + last_close_reason_ = close_reason; + last_selection_should_persist_ = should_persist; + } raw_ptr<IntentPickerBubbleView> bubble_; raw_ptr<views::View> anchor_view_; std::vector<AppInfo> app_info_; std::unique_ptr<ui::test::EventGenerator> event_generator_; + + std::string last_selected_launch_name_; + apps::IntentPickerCloseReason last_close_reason_; + bool last_selection_should_persist_; }; // Verifies that we didn't set up an image for any LabelButton. @@ -340,3 +349,98 @@ ClickApp(2); ASSERT_TRUE(checkbox->GetEnabled()); } + +TEST_F(IntentPickerBubbleViewTest, AcceptDialog) { + AddApp(apps::PickerEntryType::kWeb, "web_app_id_1", "Web App"); + AddApp(apps::PickerEntryType::kWeb, "web_app_id_2", "Web App"); + CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/false, + BubbleType::kLinkCapturing, + /*initiating_origin=*/absl::nullopt); + + ClickApp(1); + bubble_->AcceptDialog(); + + EXPECT_EQ(last_selected_launch_name_, "web_app_id_2"); + EXPECT_FALSE(last_selection_should_persist_); + EXPECT_EQ(last_close_reason_, apps::IntentPickerCloseReason::OPEN_APP); +} + +TEST_F(IntentPickerBubbleViewTest, AcceptDialogWithRememberSelection) { + AddApp(apps::PickerEntryType::kArc, "arc_app_id", "ARC App"); + CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/true, + BubbleType::kLinkCapturing, + /*initiating_origin=*/absl::nullopt); + + views::Checkbox* checkbox = static_cast<views::Checkbox*>( + bubble_->GetViewByID(IntentPickerBubbleView::ViewId::kRememberCheckbox)); + checkbox->SetChecked(true); + + bubble_->AcceptDialog(); + + EXPECT_EQ(last_selected_launch_name_, "arc_app_id"); + EXPECT_TRUE(last_selection_should_persist_); + EXPECT_EQ(last_close_reason_, apps::IntentPickerCloseReason::OPEN_APP); +} + +TEST_F(IntentPickerBubbleViewTest, CancelDialog) { + AddApp(apps::PickerEntryType::kWeb, "web_app_id_1", "Web App"); + AddApp(apps::PickerEntryType::kWeb, "web_app_id_2", "Web App"); + CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/true, + BubbleType::kLinkCapturing, + /*initiating_origin=*/absl::nullopt); + + ClickApp(1); + bubble_->CancelDialog(); + + EXPECT_EQ(last_selected_launch_name_, apps_util::kUseBrowserForLink); + EXPECT_FALSE(last_selection_should_persist_); + EXPECT_EQ(last_close_reason_, apps::IntentPickerCloseReason::STAY_IN_CHROME); +} + +TEST_F(IntentPickerBubbleViewTest, CloseDialog) { + AddApp(apps::PickerEntryType::kWeb, "web_app_id_1", "Web App"); + CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/false, + BubbleType::kLinkCapturing, + /*initiating_origin=*/absl::nullopt); + + bubble_->GetWidget()->CloseWithReason( + views::Widget::ClosedReason::kLostFocus); + + ASSERT_EQ(last_close_reason_, + apps::IntentPickerCloseReason::DIALOG_DEACTIVATED); +} + +TEST_F(IntentPickerBubbleViewTest, KeyboardNavigation) { + CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/false, + BubbleType::kLinkCapturing, + /*initiating_origin=*/absl::nullopt); + + GetButtonAtIndex(0)->RequestFocus(); + + event_generator_->PressAndReleaseKey(ui::VKEY_DOWN); + EXPECT_EQ(bubble_->GetSelectedIndex(), 1u); + event_generator_->PressAndReleaseKey(ui::VKEY_LEFT); + EXPECT_EQ(bubble_->GetSelectedIndex(), 0u); + // Pressing up/left from the first item should wrap around to the last item. + event_generator_->PressAndReleaseKey(ui::VKEY_UP); + EXPECT_EQ(bubble_->GetSelectedIndex(), + bubble_->app_info_for_testing().size() - 1); + // Pressing down/right from the last item should wrap around to the first + // item. + event_generator_->PressAndReleaseKey(ui::VKEY_RIGHT); + EXPECT_EQ(bubble_->GetSelectedIndex(), 0u); +} + +TEST_F(IntentPickerBubbleViewTest, DoubleClickToAccept) { + AddApp(apps::PickerEntryType::kWeb, "web_app_id", "Web App"); + CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/false, + BubbleType::kLinkCapturing, + /*initiating_origin=*/absl::nullopt); + + event_generator_->MoveMouseTo( + GetButtonAtIndex(0)->GetBoundsInScreen().CenterPoint()); + event_generator_->DoubleClickLeftButton(); + + EXPECT_EQ(last_selected_launch_name_, "web_app_id"); + EXPECT_EQ(last_close_reason_, apps::IntentPickerCloseReason::OPEN_APP); +}
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc index 2ab3e82..4f6c28fc 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
@@ -25,6 +25,10 @@ #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/widget/widget.h" +#if defined(USE_AURA) +#include "ui/aura/env.h" +#endif + namespace { // An arbitrary index for the result view under test. Used to test the selection @@ -59,18 +63,16 @@ class OmniboxResultViewTest : public ChromeViewsTestBase { public: void SetUp() override { - ChromeViewsTestBase::SetUp(); - - // Create a widget and assign bounds to support calls to HitTestPoint. - widget_ = CreateTestWidget(); - - // Install |test_screen_| after superclass setup and widget creation; on Ash - // both these require the Screen to work well with the underlying Shell, and - // TestScreen has no knowledge of that. +#if !defined(USE_AURA) test_screen_ = std::make_unique<display::test::TestScreen>(); scoped_screen_override_ = std::make_unique<display::test::ScopedScreenOverride>( test_screen_.get()); +#endif + ChromeViewsTestBase::SetUp(); + + // Create a widget and assign bounds to support calls to HitTestPoint. + widget_ = CreateTestWidget(); edit_model_ = std::make_unique<OmniboxEditModel>( nullptr, nullptr, std::make_unique<TestOmniboxClient>()); @@ -89,10 +91,10 @@ } void TearDown() override { - scoped_screen_override_.reset(); - test_screen_.reset(); widget_.reset(); ChromeViewsTestBase::TearDown(); + scoped_screen_override_.reset(); + test_screen_.reset(); } // Also sets the fake screen's mouse cursor to 0, 0. @@ -105,7 +107,11 @@ int flags, float x, float y) { +#if !defined(USE_AURA) test_screen_->set_cursor_screen_point(gfx::Point(x, y)); +#else + aura::Env::GetInstance()->SetLastMouseLocation(gfx::Point(x, y)); +#endif return ui::MouseEvent(type, gfx::Point(x, y), gfx::Point(), ui::EventTimeForNow(), flags, 0); }
diff --git a/chrome/browser/ui/views/sharing_hub/preview_view.cc b/chrome/browser/ui/views/sharing_hub/preview_view.cc index 4137f98..eb10a318 100644 --- a/chrome/browser/ui/views/sharing_hub/preview_view.cc +++ b/chrome/browser/ui/views/sharing_hub/preview_view.cc
@@ -7,6 +7,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/share/share_features.h" #include "chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.h" +#include "components/url_formatter/elide_url.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/layout/flex_layout.h" @@ -50,6 +51,36 @@ } } +class UrlLabel : public views::Label { + public: + UrlLabel(GURL url, int context, int style) + : views::Label(base::UTF8ToUTF16(url.spec()), context, style), url_(url) { + // Never use the elided URL for the accessible name or tooltip - both of + // these are allowed to be of arbitrary length (since they aren't + // constrained by the visual layout) and should give the user the full URL. + SetAccessibleName(GetText()); + SetTooltipText(GetText()); + } + ~UrlLabel() override = default; + + void OnBoundsChanged(const gfx::Rect& previous) override { + // Danger! Do not repurpose this behavior for your own use! + // + // It is safe to change the text in response to a layout like this *only* + // because the UrlLabel is included in a fixed-width bubble. If the bubble + // instead had variable width, or this view's width could otherwise change, + // then it would be very easy to get into an infinite loop between setting + // the text (thus prompting a relayout) and the layout setting the width + // (thus causing the text to be set again). Since the bubble containing the + // UrlLabel has a fixed width, this infinite recurrence can't happen. + views::Label::OnBoundsChanged(previous); + SetText(url_formatter::ElideUrl(url_, font_list(), width())); + } + + private: + GURL url_; +}; + } // namespace // This view uses two nested FlexLayouts, a horizontal outer one and a vertical @@ -93,9 +124,12 @@ // here. title_ = labels_container->AddChildView(std::make_unique<views::Label>( attempt.title, views::style::CONTEXT_DIALOG_TITLE)); - url_ = labels_container->AddChildView(std::make_unique<views::Label>( - base::UTF8ToUTF16(attempt.url.spec()), views::style::CONTEXT_DIALOG_TITLE, + title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + + url_ = labels_container->AddChildView(std::make_unique<UrlLabel>( + attempt.url, views::style::CONTEXT_DIALOG_TITLE, views::style::STYLE_HINT)); + url_->SetHorizontalAlignment(gfx::ALIGN_LEFT); } PreviewView::~PreviewView() = default;
diff --git a/chrome/browser/ui/views/test/view_event_test_base.cc b/chrome/browser/ui/views/test/view_event_test_base.cc index 54c917a..fed341ee 100644 --- a/chrome/browser/ui/views/test/view_event_test_base.cc +++ b/chrome/browser/ui/views/test/view_event_test_base.cc
@@ -14,13 +14,13 @@ #include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/testing_browser_process.h" #include "mojo/core/embedder/embedder.h" +#include "ui/display/screen.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" #if defined(USE_AURA) && !BUILDFLAG(IS_CHROMEOS_ASH) -#include "ui/display/screen.h" #include "ui/views/widget/desktop_aura/desktop_screen.h" #if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && defined(USE_OZONE) @@ -98,13 +98,12 @@ // TODO(pkasting): Determine why the TestScreen in AuraTestHelper is // insufficient for these tests, then either bolster/replace it or fix the // tests. - DCHECK(!display::Screen::GetScreen()); + DCHECK(!display::Screen::HasScreen()); #if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && defined(USE_OZONE) - if (!display::Screen::GetScreen()) - display::Screen::SetScreenInstance( - views::test::TestDesktopScreenOzone::GetInstance()); + if (!display::Screen::HasScreen()) + screen_ = views::test::TestDesktopScreenOzone::Create(); #endif - if (!display::Screen::GetScreen()) + if (!display::Screen::HasScreen()) screen_ = views::CreateDesktopScreen(); #endif }
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc index 21e546e..813eb81 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view.cc +++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -416,7 +416,6 @@ if (GetBubbleFrameView()->GetWidget()->closed_reason() == views::Widget::ClosedReason::kCloseButtonClicked) { model_->DeclineTranslation(); - translate::ReportUiAction(translate::CLOSE_BUTTON_CLICKED); model_->ReportUIInteraction(translate::UIInteraction::kCloseUIExplicitly); } else { model_->ReportUIInteraction(translate::UIInteraction::kCloseUILostFocus);
diff --git a/chrome/browser/ui/views/user_education/browser_user_education_service.cc b/chrome/browser/ui/views/user_education/browser_user_education_service.cc index 35c8486e..cd24f0f 100644 --- a/chrome/browser/ui/views/user_education/browser_user_education_service.cc +++ b/chrome/browser/ui/views/user_education/browser_user_education_service.cc
@@ -31,6 +31,7 @@ #include "ui/base/interaction/element_identifier.h" #include "ui/base/interaction/element_tracker.h" #include "ui/base/interaction/interaction_sequence.h" +#include "ui/color/color_id.h" #include "ui/views/interaction/element_tracker_views.h" #include "ui/views/view.h" #include "ui/views/view_utils.h" @@ -89,29 +90,24 @@ // These methods return color codes that will be handled by the app's theming // system. - int GetHelpBubbleBackgroundColor() const override { - return ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_BACKGROUND; - } - int GetHelpBubbleForegroundColor() const override { - return ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_FOREGROUND; - } - int GetHelpBubbleDefaultButtonBackgroundColor() const override { - return ThemeProperties:: - COLOR_FEATURE_PROMO_BUBBLE_DEFAULT_BUTTON_BACKGROUND; - } - int GetHelpBubbleDefaultButtonForegroundColor() const override { - return ThemeProperties:: - COLOR_FEATURE_PROMO_BUBBLE_DEFAULT_BUTTON_FOREGROUND; - } - int GetHelpBubbleButtonBorderColor() const override { - return ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_BUTTON_BORDER; - } - int GetHelpBubbleCloseButtonInkDropColor() const override { - return ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_CLOSE_BUTTON_INK_DROP; - } ui::ColorId GetHelpBubbleBackgroundColorId() const override { return kColorFeaturePromoBubbleBackground; } + ui::ColorId GetHelpBubbleForegroundColorId() const override { + return kColorFeaturePromoBubbleForeground; + } + ui::ColorId GetHelpBubbleDefaultButtonBackgroundColorId() const override { + return kColorFeaturePromoBubbleDefaultButtonBackground; + } + ui::ColorId GetHelpBubbleDefaultButtonForegroundColorId() const override { + return kColorFeaturePromoBubbleDefaultButtonForeground; + } + ui::ColorId GetHelpBubbleButtonBorderColorId() const override { + return kColorFeaturePromoBubbleButtonBorder; + } + ui::ColorId GetHelpBubbleCloseButtonInkDropColorId() const override { + return kColorFeaturePromoBubbleCloseButtonInkDrop; + } }; } // namespace
diff --git a/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.cc b/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.cc new file mode 100644 index 0000000..17096021 --- /dev/null +++ b/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.cc
@@ -0,0 +1,141 @@ +// Copyright 2022 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 <memory> + +#include "chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.h" + +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/feature_engagement/tracker_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/page_action/page_action_icon_type.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/frame/toolbar_button_provider.h" +#include "chrome/browser/ui/views/page_action/page_action_icon_view.h" +#include "chrome/browser/ui/views/web_apps/web_app_info_image_source.h" +#include "chrome/browser/web_applications/web_app_helpers.h" +#include "chrome/browser/web_applications/web_app_prefs_utils.h" +#include "components/constrained_window/constrained_window_views.h" +#include "components/feature_engagement/public/event_constants.h" +#include "components/feature_engagement/public/tracker.h" +#include "components/prefs/pref_service.h" +#include "components/strings/grit/components_strings.h" +#include "content/public/browser/web_contents.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/base/models/dialog_model_field.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/views/bubble/bubble_dialog_model_host.h" +#include "ui/views/window/dialog_delegate.h" + +namespace chrome { + +void ShowWebAppDetailedInstallDialog( + content::WebContents* web_contents, + std::unique_ptr<WebAppInstallInfo> install_info, + chrome::AppInstallationAcceptanceCallback callback, + chrome::PwaInProductHelpState iph_state) { + content::BrowserContext* browser_context = web_contents->GetBrowserContext(); + PrefService* const prefs = + Profile::FromBrowserContext(browser_context)->GetPrefs(); + + feature_engagement::Tracker* const tracker = + feature_engagement::TrackerFactory::GetForBrowserContext(browser_context); + + constexpr int kIconSize = 32; + + gfx::ImageSkia image(std::make_unique<WebAppInfoImageSource>( + kIconSize, install_info->icon_bitmaps.any), + gfx::Size(kIconSize, kIconSize)); + + auto title = install_info->title; + auto description = install_info->description; + + auto delegate = + std::make_unique<web_app::WebAppDetailedInstallDialogDelegate>( + web_contents, std::move(install_info), std::move(callback), + std::move(iph_state), prefs, tracker); + + auto* delegate_ptr = delegate.get(); + + auto dialog_model = + ui::DialogModel::Builder(std::move(delegate)) + .SetIcon(ui::ImageModel::FromImageSkia(image)) + .SetTitle(title) // TODO(pbos): Add secondary-title support for + // base::UTF8ToUTF16(install_info->start_url.host()) + .AddBodyText(ui::DialogModelLabel(description)) + .AddOkButton( + base::BindOnce( + &web_app::WebAppDetailedInstallDialogDelegate::OnAccept, + base::Unretained(delegate_ptr)), + l10n_util::GetStringUTF16(IDS_INSTALL)) + .AddCancelButton(base::BindOnce( + &web_app::WebAppDetailedInstallDialogDelegate::OnCancel, + base::Unretained(delegate_ptr))) + .OverrideShowCloseButton(false) + .Build(); + + auto dialog = views::BubbleDialogModelHost::CreateModal( + std::move(dialog_model), ui::MODAL_TYPE_CHILD); + + constrained_window::ShowWebModalDialogViews(dialog.release(), web_contents); +} + +} // namespace chrome + +namespace web_app { + +WebAppDetailedInstallDialogDelegate::WebAppDetailedInstallDialogDelegate( + content::WebContents* web_contents, + std::unique_ptr<WebAppInstallInfo> web_app_info, + chrome::AppInstallationAcceptanceCallback callback, + chrome::PwaInProductHelpState iph_state, + PrefService* prefs, + feature_engagement::Tracker* tracker) + : web_contents_(web_contents), + install_info_(std::move(web_app_info)), + callback_(std::move(callback)), + iph_state_(std::move(iph_state)), + prefs_(prefs), + tracker_(tracker) { + DCHECK(install_info_); + DCHECK(prefs_); +} + +WebAppDetailedInstallDialogDelegate::~WebAppDetailedInstallDialogDelegate() { + // TODO(crbug.com/1327363): move this to dialog->SetHighlightedButton. + Browser* browser = chrome::FindBrowserWithWebContents(web_contents_); + if (!browser) + return; + + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); + // Dehighlight the install icon when this dialog is closed. + browser_view->toolbar_button_provider() + ->GetPageActionIconView(PageActionIconType::kPwaInstall) + ->SetHighlighted(false); +} + +void WebAppDetailedInstallDialogDelegate::OnAccept() { + if (iph_state_ == chrome::PwaInProductHelpState::kShown) { + web_app::AppId app_id = web_app::GenerateAppId(install_info_->manifest_id, + install_info_->start_url); + web_app::RecordInstallIphInstalled(prefs_, app_id); + tracker_->NotifyEvent(feature_engagement::events::kDesktopPwaInstalled); + } + + std::move(callback_).Run(true, std::move(install_info_)); +} + +void WebAppDetailedInstallDialogDelegate::OnCancel() { + if (iph_state_ == chrome::PwaInProductHelpState::kShown && install_info_) { + web_app::AppId app_id = web_app::GenerateAppId(install_info_->manifest_id, + install_info_->start_url); + web_app::RecordInstallIphIgnored(prefs_, app_id, base::Time::Now()); + } + + std::move(callback_).Run(false, std::move(install_info_)); +} + +} // namespace web_app
diff --git a/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.h b/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.h new file mode 100644 index 0000000..69f1d6b --- /dev/null +++ b/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.h
@@ -0,0 +1,54 @@ +// Copyright 2022 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_UI_VIEWS_WEB_APPS_WEB_APP_DETAILED_INSTALL_DIALOG_H_ +#define CHROME_BROWSER_UI_VIEWS_WEB_APPS_WEB_APP_DETAILED_INSTALL_DIALOG_H_ + +#include <memory> + +#include "base/memory/raw_ptr.h" +#include "chrome/browser/ui/browser_dialogs.h" +#include "chrome/browser/web_applications/web_app_install_info.h" +#include "ui/base/models/dialog_model.h" +#include "ui/views/view.h" + +class PrefService; + +namespace content { +class WebContents; +} + +namespace feature_engagement { +class Tracker; +} + +namespace web_app { + +class WebAppDetailedInstallDialogDelegate : public ui::DialogModelDelegate { + public: + WebAppDetailedInstallDialogDelegate( + content::WebContents* web_contents, + std::unique_ptr<WebAppInstallInfo> install_info, + chrome::AppInstallationAcceptanceCallback callback, + chrome::PwaInProductHelpState iph_state, + PrefService* prefs, + feature_engagement::Tracker* tracker); + + ~WebAppDetailedInstallDialogDelegate() override; + + void OnAccept(); + void OnCancel(); + + private: + raw_ptr<content::WebContents> web_contents_; + std::unique_ptr<WebAppInstallInfo> install_info_; + chrome::AppInstallationAcceptanceCallback callback_; + chrome::PwaInProductHelpState iph_state_; + raw_ptr<PrefService> prefs_; + raw_ptr<feature_engagement::Tracker> tracker_; +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_UI_VIEWS_WEB_APPS_WEB_APP_DETAILED_INSTALL_DIALOG_H_
diff --git a/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog_browsertest.cc new file mode 100644 index 0000000..fe417187 --- /dev/null +++ b/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog_browsertest.cc
@@ -0,0 +1,43 @@ +// Copyright 2022 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/ui/browser.h" +#include "chrome/browser/ui/browser_dialogs.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/test/test_browser_dialog.h" +#include "chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.h" +#include "chrome/browser/web_applications/test/web_app_icon_test_utils.h" +#include "chrome/browser/web_applications/web_app_install_info.h" +#include "content/public/test/browser_test.h" +#include "third_party/skia/include/core/SkColor.h" + +namespace web_app { + +class WebAppDetailedInstallDialogBrowserTest : public DialogBrowserTest { + public: + // DialogBrowserTest: + void ShowUi(const std::string& name) override { + auto install_info = std::make_unique<WebAppInstallInfo>(); + install_info->title = u"test"; + install_info->description = u"This is a test app"; + + AddGeneratedIcon(&install_info->icon_bitmaps.any, kIconSize, kIconColor); + + chrome::ShowWebAppDetailedInstallDialog( + browser()->tab_strip_model()->GetWebContentsAt(0), + std::move(install_info), base::DoNothing(), + chrome::PwaInProductHelpState::kNotShown); + } + + private: + static constexpr int kIconSize = 40; + static constexpr SkColor kIconColor = SK_ColorGREEN; +}; + +IN_PROC_BROWSER_TEST_F(WebAppDetailedInstallDialogBrowserTest, + InvokeUi_Default) { + ShowAndVerifyUi(); +} + +} // namespace web_app
diff --git a/chrome/browser/ui/web_applications/web_app_dialog_utils.cc b/chrome/browser/ui/web_applications/web_app_dialog_utils.cc index 9cdc5010..93742dc2 100644 --- a/chrome/browser/ui/web_applications/web_app_dialog_utils.cc +++ b/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/web_applications/web_app_install_utils.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_utils.h" +#include "chrome/common/chrome_features.h" #include "components/webapps/browser/banners/app_banner_manager.h" #include "components/webapps/browser/installable/installable_metrics.h" #include "content/public/browser/navigation_entry.h" @@ -47,10 +48,18 @@ switch (flow) { case WebAppInstallFlow::kInstallSite: web_app_info->user_display_mode = UserDisplayMode::kStandalone; - chrome::ShowPWAInstallBubble( - initiator_web_contents, std::move(web_app_info), - std::move(web_app_acceptance_callback), iph_state); - return; + if (base::FeatureList::IsEnabled( + features::kDesktopPWAsDetailedInstallDialog)) { + chrome::ShowWebAppDetailedInstallDialog( + initiator_web_contents, std::move(web_app_info), + std::move(web_app_acceptance_callback), iph_state); + return; + } else { + chrome::ShowPWAInstallBubble( + initiator_web_contents, std::move(web_app_info), + std::move(web_app_acceptance_callback), iph_state); + return; + } case WebAppInstallFlow::kCreateShortcut: chrome::ShowWebAppInstallDialog(initiator_web_contents, std::move(web_app_info),
diff --git a/chrome/browser/ui/webui/settings/chromeos/crostini_section.cc b/chrome/browser/ui/webui/settings/chromeos/crostini_section.cc index 432117a..9bf8232 100644 --- a/chrome/browser/ui/webui/settings/chromeos/crostini_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/crostini_section.cc
@@ -419,6 +419,12 @@ IDS_SETTINGS_CROSTINI_SUBTEXT, ui::GetChromeOSDeviceName(), GetHelpUrlWithBoard(chrome::kLinuxAppsLearnMoreURL))); html_source->AddString( + "crostiniSubtextNotSupported", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_CROSTINI_SUBTEXT_NOT_SUPPORTED, + ui::GetChromeOSDeviceName(), + GetHelpUrlWithBoard(chrome::kLinuxAppsLearnMoreURL))); + html_source->AddString( "crostiniArcAdbPowerwashRequiredSublabel", l10n_util::GetStringFUTF16( IDS_SETTINGS_CROSTINI_ARC_ADB_POWERWASH_REQUIRED_SUBLABEL,
diff --git a/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc b/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc index 4fe4c389..816a2df2 100644 --- a/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc
@@ -43,9 +43,9 @@ ASSERT_EQ(local_state(), g_browser_process->local_state()); EXPECT_TRUE(test_web_ui()->call_data().empty()); - base::ListValue args; - args.Append(std::make_unique<base::Value>(1)); - handler()->HandleGetMetricsReporting(args.GetList()); + base::Value::List args; + args.Append(1); + handler()->HandleGetMetricsReporting(args); EXPECT_TRUE(handler()->IsJavascriptAllowed()); EXPECT_EQ(1u, test_web_ui()->call_data().size());
diff --git a/chrome/browser/ui/window_sizer/DEPS b/chrome/browser/ui/window_sizer/DEPS index 046d8fd0..ea16c4459 100644 --- a/chrome/browser/ui/window_sizer/DEPS +++ b/chrome/browser/ui/window_sizer/DEPS
@@ -1,6 +1,5 @@ specific_include_rules = { - ".*test.*": [ - "!ash", - "+ash/public", + ".*chromeos.*test.*": [ + "+ash", ], }
diff --git a/chrome/browser/ui/window_sizer/window_sizer_chromeos_unittest.cc b/chrome/browser/ui/window_sizer/window_sizer_chromeos_unittest.cc index a29e51a..90696be 100644 --- a/chrome/browser/ui/window_sizer/window_sizer_chromeos_unittest.cc +++ b/chrome/browser/ui/window_sizer/window_sizer_chromeos_unittest.cc
@@ -5,6 +5,8 @@ #include "chrome/browser/ui/window_sizer/window_sizer_chromeos.h" #include "ash/public/cpp/window_properties.h" +#include "ash/root_window_controller.h" +#include "ash/shelf/shelf.h" #include "ash/shell.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" @@ -45,16 +47,30 @@ void GetWindowBounds(const Browser* browser, const gfx::Rect& passed_in, int64_t display_id, + const gfx::Rect& bounds, + const gfx::Rect& work_area, + Source source, gfx::Rect* out_bounds) { auto state_provider = std::make_unique<TestStateProvider>(); - state_provider->SetPersistentState(gfx::Rect(), gfx::Rect(), - ui::SHOW_STATE_DEFAULT); + if (source == PERSISTED) { + state_provider->SetPersistentState(bounds, work_area, + ui::SHOW_STATE_DEFAULT); + } else { + DCHECK_EQ(source, DEFAULT); + } display::Screen::GetScreen()->SetDisplayForNewWindows(display_id); ui::WindowShowState ignored; WindowSizer::GetBrowserWindowBoundsAndShowState( std::move(state_provider), passed_in, browser, out_bounds, &ignored); } + void GetWindowBounds(const Browser* browser, + const gfx::Rect& passed_in, + int64_t display_id, + gfx::Rect* out_bounds = nullptr) { + GetWindowBounds(browser, passed_in, display_id, gfx::Rect(), gfx::Rect(), + PERSISTED, out_bounds); + } // Returns browser window |out_bounds| and |out_show_state| for simulated // persisted and last-active window bounds, work area, show state, etc. @@ -124,9 +140,13 @@ } // namespace +// WindowSizerChromeOSNoAshTest are the tests that does not require ash +// environment, thus it can use WindowSizerTestUtil that create a TestScreen +// inside. + // Test that the window is sized appropriately for the first run experience // where the default window bounds calculation is invoked. -TEST_F(WindowSizerChromeOSTest, DefaultSizeCase) { +TEST(WindowSizerChromeOSNoAshTest, DefaultSizeCase) { { // 4:3 monitor case, 1024x768, no taskbar. gfx::Rect window_bounds; @@ -237,7 +257,7 @@ // Test that the next opened window is positioned appropriately given the // bounds of an existing window of the same type. -TEST_F(WindowSizerChromeOSTest, LastWindowBoundsCase) { +TEST(WindowSizerChromeOS2NoAshTest, LastWindowBoundsCase) { { // Normal, in the middle of the screen somewhere. gfx::Rect window_bounds; @@ -294,8 +314,8 @@ } } -TEST_F(WindowSizerChromeOSTest, - LastWindowOffscreenWithNonAggressiveRepositioning) { +TEST(WindowSizerChromeOSNoAshTest, + LastWindowOffscreenWithNonAggressiveRepositioning) { { // Taskbar on left. gfx::Rect window_bounds; @@ -370,6 +390,12 @@ // Test the placement of newly created windows. TEST_F(WindowSizerChromeOSTest, PlaceNewWindows) { + UpdateDisplay("1600x1200"); + auto* shelf = ash::Shell::GetPrimaryRootWindowController()->shelf(); + shelf->SetAutoHideBehavior(ash::ShelfAutoHideBehavior::kAlways); + + int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + // Create a browser to pass into the WindowSizerTestUtil::GetWindowBounds // function. Browser::CreateParams native_params(&profile_, true); @@ -395,10 +421,9 @@ Browser::CreateParams params_popup(Browser::TYPE_POPUP, &profile_, true); auto new_popup = CreateWindowlessBrowser(params_popup); gfx::Rect window_bounds; - WindowSizerTestUtil::GetWindowBounds( - p1600x1200, p1600x1200, gfx::Rect(), gfx::Rect(50, 100, 300, 150), - bottom_s1600x1200, PERSISTED, new_popup.get(), gfx::Rect(), - &window_bounds); + GetWindowBounds(new_popup.get(), gfx::Rect(), display_id, + gfx::Rect(50, 100, 300, 150), bottom_s1600x1200, PERSISTED, + &window_bounds); EXPECT_EQ("50,100 300x150", window_bounds.ToString()); } @@ -406,19 +431,17 @@ { // If a window is there but not shown the persisted default should be used. gfx::Rect window_bounds; - WindowSizerTestUtil::GetWindowBounds( - p1600x1200, p1600x1200, gfx::Rect(), gfx::Rect(50, 100, 300, 150), - bottom_s1600x1200, PERSISTED, browser.get(), gfx::Rect(), - &window_bounds); + GetWindowBounds(browser.get(), gfx::Rect(), display_id, + gfx::Rect(50, 100, 300, 150), bottom_s1600x1200, PERSISTED, + &window_bounds); EXPECT_EQ("50,100 300x150", window_bounds.ToString()); } { // If a window is there but not shown the default should be returned. gfx::Rect window_bounds; - WindowSizerTestUtil::GetWindowBounds( - p1600x1200, p1600x1200, gfx::Rect(), gfx::Rect(), bottom_s1600x1200, - DEFAULT, browser.get(), gfx::Rect(), &window_bounds); + GetWindowBounds(browser.get(), gfx::Rect(), display_id, gfx::Rect(), + bottom_s1600x1200, DEFAULT, &window_bounds); // Note: We need to also take the defaults maximum width into account here // since that might get used if the resolution is too big. EXPECT_EQ(
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index 58fd3d52..c749ca0 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -97,6 +97,8 @@ "policy/web_app_settings_policy_handler.h", "preinstalled_app_install_features.cc", "preinstalled_app_install_features.h", + "preinstalled_web_app_config_utils.cc", + "preinstalled_web_app_config_utils.h", "preinstalled_web_app_manager.cc", "preinstalled_web_app_manager.h", "preinstalled_web_app_utils.cc",
diff --git a/chrome/browser/web_applications/preinstalled_web_app_config_utils.cc b/chrome/browser/web_applications/preinstalled_web_app_config_utils.cc new file mode 100644 index 0000000..93c220a --- /dev/null +++ b/chrome/browser/web_applications/preinstalled_web_app_config_utils.cc
@@ -0,0 +1,139 @@ +// Copyright 2022 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/web_applications/preinstalled_web_app_config_utils.h" + +#include "base/command_line.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" + +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/constants/ash_switches.h" +#include "chrome/browser/ash/profiles/profile_helper.h" +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chrome/common/chrome_paths_lacros.h" +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + +namespace web_app { + +namespace { + +const base::FilePath* g_config_dir_for_testing = nullptr; + +#if BUILDFLAG(IS_CHROMEOS_ASH) +// The sub-directory of the extensions directory in which to scan for external +// web apps (as opposed to external extensions or external ARC apps). +const base::FilePath::CharType kWebAppsSubDirectory[] = + FILE_PATH_LITERAL("web_apps"); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + +#if BUILDFLAG(IS_CHROMEOS_LACROS) +base::FilePath GetPreinstalledWebAppConfigDirFromDefaultPaths( + Profile* profile) { + if (g_config_dir_for_testing) { + return *g_config_dir_for_testing; + } + + base::FilePath web_apps_dir; + if (chrome::GetPreinstalledWebAppConfigPath(&web_apps_dir)) + return web_apps_dir; + return base::FilePath(); +} + +base::FilePath GetPreinstalledWebAppExtraConfigDirFromDefaultPaths( + Profile* profile) { + base::FilePath extra_web_apps_dir; + if (chrome::GetPreinstalledWebAppExtraConfigPath(&extra_web_apps_dir)) + return extra_web_apps_dir; + return base::FilePath(); +} +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + +} // namespace + +const base::FilePath* GetPreinstalledWebAppConfigDirForTesting() { + return g_config_dir_for_testing; +} + +void SetPreinstalledWebAppConfigDirForTesting( + const base::FilePath* config_dir) { + g_config_dir_for_testing = config_dir; +} + +#if !BUILDFLAG(IS_CHROMEOS_LACROS) +base::FilePath GetPreinstalledWebAppConfigDirFromCommandLine(Profile* profile) { + std::string command_line_directory = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kPreinstalledWebAppsDir); + if (!command_line_directory.empty()) + return base::FilePath::FromUTF8Unsafe(command_line_directory); + +#if BUILDFLAG(IS_CHROMEOS_ASH) + // As of mid 2018, only Chrome OS has default/external web apps, and + // chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS is only defined for OS_LINUX, + // which includes OS_CHROMEOS. + + // Exclude sign-in and lock screen profiles. + if (!ash::ProfileHelper::IsRegularProfile(profile)) { + return {}; + } + + if (g_config_dir_for_testing) { + return *g_config_dir_for_testing; + } + + // For manual testing, you can change s/STANDALONE/USER/, as writing to + // "$HOME/.config/chromium/test-user/.config/chromium/External + // Extensions/web_apps" does not require root ACLs, unlike + // "/usr/share/chromium/extensions/web_apps". + base::FilePath dir; + if (base::PathService::Get(chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, + &dir)) { + return dir.Append(kWebAppsSubDirectory); + } + + LOG(ERROR) << "base::PathService::Get failed"; +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + + return {}; +} + +base::FilePath GetPreinstalledWebAppExtraConfigDirFromCommandLine( + Profile* profile) { +#if BUILDFLAG(IS_CHROMEOS_ASH) + base::FilePath config_dir = + GetPreinstalledWebAppConfigDirFromCommandLine(profile); + std::string extra_config_subdir = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + ash::switches::kExtraWebAppsDir); + if (config_dir.empty() || extra_config_subdir.empty()) + return base::FilePath(); + return config_dir.AppendASCII(extra_config_subdir); +#else + return base::FilePath(); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) +} +#endif // !BUILDFLAG(IS_CHROMEOS_LACROS) + +base::FilePath GetPreinstalledWebAppConfigDir(Profile* profile) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + return GetPreinstalledWebAppConfigDirFromDefaultPaths(profile); +#else + return GetPreinstalledWebAppConfigDirFromCommandLine(profile); +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) +} + +base::FilePath GetPreinstalledWebAppExtraConfigDir(Profile* profile) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + return GetPreinstalledWebAppExtraConfigDirFromDefaultPaths(profile); +#else + return GetPreinstalledWebAppExtraConfigDirFromCommandLine(profile); +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/preinstalled_web_app_config_utils.h b/chrome/browser/web_applications/preinstalled_web_app_config_utils.h new file mode 100644 index 0000000..0bd79414 --- /dev/null +++ b/chrome/browser/web_applications/preinstalled_web_app_config_utils.h
@@ -0,0 +1,41 @@ +// Copyright 2022 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_WEB_APPLICATIONS_PREINSTALLED_WEB_APP_CONFIG_UTILS_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_PREINSTALLED_WEB_APP_CONFIG_UTILS_H_ + +#include "base/files/file_path.h" +#include "build/chromeos_buildflags.h" + +class Profile; + +namespace web_app { + +const base::FilePath* GetPreinstalledWebAppConfigDirForTesting(); +void SetPreinstalledWebAppConfigDirForTesting(const base::FilePath* config_dir); + +#if !BUILDFLAG(IS_CHROMEOS_LACROS) +// The directory where default web app configs are stored. +// Empty if not applicable. +base::FilePath GetPreinstalledWebAppConfigDirFromCommandLine(Profile* profile); + +// The directory where additional web app configs are stored. This allows a +// single Chrome OS system image to have device-specific apps for multiple +// devices. Empty if not applicable. +base::FilePath GetPreinstalledWebAppExtraConfigDirFromCommandLine( + Profile* profile); +#endif // !BUILDFLAG(IS_CHROMEOS_LACROS) + +// The directory where default web app configs are stored. +// Empty if not applicable. +// As of mid 2018, only Chrome OS has default/external web apps. +base::FilePath GetPreinstalledWebAppConfigDir(Profile* profile); + +// The directory where additional web app configs are stored. +// Empty if not applicable. +base::FilePath GetPreinstalledWebAppExtraConfigDir(Profile* profile); + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_PREINSTALLED_WEB_APP_CONFIG_UTILS_H_
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager.cc b/chrome/browser/web_applications/preinstalled_web_app_manager.cc index 57bfbdc..d073054 100644 --- a/chrome/browser/web_applications/preinstalled_web_app_manager.cc +++ b/chrome/browser/web_applications/preinstalled_web_app_manager.cc
@@ -12,7 +12,6 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/command_line.h" #include "base/containers/contains.h" #include "base/containers/cxx20_erase.h" #include "base/feature_list.h" @@ -24,7 +23,6 @@ #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_functions.h" #include "base/observer_list.h" -#include "base/path_service.h" #include "base/strings/strcat.h" #include "base/task/thread_pool.h" #include "base/threading/scoped_blocking_call.h" @@ -39,6 +37,7 @@ #include "chrome/browser/web_applications/externally_managed_app_manager.h" #include "chrome/browser/web_applications/file_utils_wrapper.h" #include "chrome/browser/web_applications/preinstalled_app_install_features.h" +#include "chrome/browser/web_applications/preinstalled_web_app_config_utils.h" #include "chrome/browser/web_applications/preinstalled_web_app_utils.h" #include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h" #include "chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.h" @@ -48,8 +47,6 @@ #include "chrome/browser/web_applications/web_app_ui_manager.h" #include "chrome/browser/web_applications/web_app_utils.h" #include "chrome/common/chrome_features.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "components/ntp_tiles/most_visited_sites.h" #include "components/pref_registry/pref_registry_syncable.h" @@ -72,6 +69,7 @@ #endif // BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "chromeos/lacros/lacros_service.h" #endif // BUILDFLAG(IS_CHROMEOS_LACROS) @@ -79,17 +77,9 @@ namespace { -#if BUILDFLAG(IS_CHROMEOS) -// The sub-directory of the extensions directory in which to scan for external -// web apps (as opposed to external extensions or external ARC apps). -const base::FilePath::CharType kWebAppsSubDirectory[] = - FILE_PATH_LITERAL("web_apps"); -#endif // BUILDFLAG(IS_CHROMEOS) - bool g_skip_startup_for_testing_ = false; bool g_bypass_offline_manifest_requirement_for_testing_ = false; bool g_override_previous_user_uninstall_for_testing_ = false; -const base::FilePath* g_config_dir_for_testing = nullptr; const std::vector<base::Value>* g_configs_for_testing = nullptr; FileUtilsWrapper* g_file_utils_for_testing = nullptr; @@ -436,20 +426,6 @@ return absl::nullopt; } -std::string GetConfigDirectoryFromCommandLine() { - return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kPreinstalledWebAppsDir); -} - -std::string GetExtraConfigSubdirectory() { -#if BUILDFLAG(IS_CHROMEOS_ASH) - return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - ash::switches::kExtraWebAppsDir); -#else - return std::string(); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) -} - } // namespace const char* PreinstalledWebAppManager::kHistogramEnabledCount = @@ -494,11 +470,6 @@ g_override_previous_user_uninstall_for_testing_ = true; } -void PreinstalledWebAppManager::SetConfigDirForTesting( - const base::FilePath* config_dir) { - g_config_dir_for_testing = config_dir; -} - void PreinstalledWebAppManager::SetConfigsForTesting( const std::vector<base::Value>* configs) { g_configs_for_testing = configs; @@ -596,8 +567,8 @@ LoadedConfigs loaded_configs; for (const base::Value& config : *g_configs_for_testing) { auto file = base::FilePath(FILE_PATH_LITERAL("test.json")); - if (g_config_dir_for_testing) { - file = g_config_dir_for_testing->Append(file); + if (GetPreinstalledWebAppConfigDirForTesting()) { + file = GetPreinstalledWebAppConfigDirForTesting()->Append(file); } loaded_configs.configs.push_back( @@ -612,16 +583,17 @@ return; } - base::FilePath config_dir = GetConfigDir(); + base::FilePath config_dir = GetPreinstalledWebAppConfigDir(profile_); if (config_dir.empty()) { std::move(callback).Run({}); return; } std::vector<base::FilePath> config_dirs = {config_dir}; - std::string extra_config_subdir = GetExtraConfigSubdirectory(); - if (!extra_config_subdir.empty()) { - config_dirs.push_back(config_dir.AppendASCII(extra_config_subdir)); + base::FilePath extra_config_dir = + GetPreinstalledWebAppExtraConfigDir(profile_); + if (!extra_config_dir.empty()) { + config_dirs.push_back(extra_config_dir); } base::ThreadPool::PostTaskAndReplyWithResult( @@ -860,43 +832,6 @@ } } -base::FilePath PreinstalledWebAppManager::GetConfigDir() { - std::string command_line_directory = GetConfigDirectoryFromCommandLine(); - if (!command_line_directory.empty()) - return base::FilePath::FromUTF8Unsafe(command_line_directory); - -#if BUILDFLAG(IS_CHROMEOS) - // As of mid 2018, only Chrome OS has default/external web apps, and - // chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS is only defined for OS_LINUX, - // which includes OS_CHROMEOS. - -#if BUILDFLAG(IS_CHROMEOS_ASH) - // Exclude sign-in and lock screen profiles. - if (!ash::ProfileHelper::IsRegularProfile(profile_)) { - return {}; - } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - - if (g_config_dir_for_testing) { - return *g_config_dir_for_testing; - } - - // For manual testing, you can change s/STANDALONE/USER/, as writing to - // "$HOME/.config/chromium/test-user/.config/chromium/External - // Extensions/web_apps" does not require root ACLs, unlike - // "/usr/share/chromium/extensions/web_apps". - base::FilePath dir; - if (base::PathService::Get(chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, - &dir)) { - return dir.Append(kWebAppsSubDirectory); - } - - LOG(ERROR) << "base::PathService::Get failed"; -#endif // BUILDFLAG(IS_CHROMEOS) - - return {}; -} - bool PreinstalledWebAppManager::IsNewUser() { PrefService* prefs = profile_->GetPrefs(); return prefs->GetString(prefs::kWebAppsLastPreinstallSynchronizeVersion)
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager.h b/chrome/browser/web_applications/preinstalled_web_app_manager.h index 2c0a7482d..cfd5a5f 100644 --- a/chrome/browser/web_applications/preinstalled_web_app_manager.h +++ b/chrome/browser/web_applications/preinstalled_web_app_manager.h
@@ -20,10 +20,6 @@ #include "chrome/browser/web_applications/file_utils_wrapper.h" #include "url/gurl.h" -namespace base { -class FilePath; -} - namespace user_prefs { class PrefRegistrySyncable; } @@ -79,8 +75,10 @@ static void SkipStartupForTesting(); static void BypassOfflineManifestRequirementForTesting(); + static void OverridePreviousUserUninstallConfigForTesting(); static void SetConfigDirForTesting(const base::FilePath* config_dir); + static void SetConfigsForTesting(const std::vector<base::Value>* configs); static void SetFileUtilsForTesting(FileUtilsWrapper* file_utils); @@ -147,10 +145,6 @@ install_results, std::map<InstallUrl, bool> uninstall_results); - // The directory where default web app configs are stored. - // Empty if not applicable. - base::FilePath GetConfigDir(); - // Returns whether this is the first time we've deployed default apps on this // profile. bool IsNewUser();
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc index b5e2240..1a2640f4 100644 --- a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc +++ b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" #include "chrome/browser/web_applications/policy/web_app_policy_manager.h" #include "chrome/browser/web_applications/preinstalled_app_install_features.h" +#include "chrome/browser/web_applications/preinstalled_web_app_config_utils.h" #include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h" #include "chrome/browser/web_applications/test/fake_os_integration_manager.h" #include "chrome/browser/web_applications/test/test_file_utils.h" @@ -218,7 +219,7 @@ const GURL& install_url, base::StringPiece app_config_string) { base::FilePath test_config_dir(FILE_PATH_LITERAL("test_dir")); - PreinstalledWebAppManager::SetConfigDirForTesting(&test_config_dir); + SetPreinstalledWebAppConfigDirForTesting(&test_config_dir); base::FilePath source_root_dir; CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir)); @@ -255,7 +256,7 @@ })); sync_run_loop.Run(); - PreinstalledWebAppManager::SetConfigDirForTesting(nullptr); + SetPreinstalledWebAppConfigDirForTesting(nullptr); PreinstalledWebAppManager::SetFileUtilsForTesting(nullptr); PreinstalledWebAppManager::SetConfigsForTesting(nullptr);
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc b/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc index 681502f..5018b41 100644 --- a/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc +++ b/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc
@@ -24,6 +24,7 @@ #include "build/chromeos_buildflags.h" #include "chrome/browser/extensions/extension_management_test_util.h" #include "chrome/browser/web_applications/preinstalled_app_install_features.h" +#include "chrome/browser/web_applications/preinstalled_web_app_config_utils.h" #include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h" #include "chrome/browser/web_applications/user_display_mode.h" #include "chrome/browser/web_applications/web_app_constants.h" @@ -49,6 +50,13 @@ #include "components/user_manager/scoped_user_manager.h" #endif +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "base/path_service.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_paths_lacros.h" +#include "chromeos/crosapi/mojom/crosapi.mojom.h" +#endif + namespace web_app { namespace { @@ -97,7 +105,7 @@ } protected: - std::vector<ExternalInstallOptions> LoadApps(const char* test_dir, + std::vector<ExternalInstallOptions> LoadApps(base::StringPiece test_dir, Profile* profile = nullptr) { std::unique_ptr<TestingProfile> testing_profile; if (!profile) { @@ -109,17 +117,8 @@ #endif } - // Uses the chrome/test/data/web_app_default_apps/test_dir directory - // that holds the *.json data files from which tests should parse as app - // configs. - base::FilePath config_dir; - if (!base::PathService::Get(chrome::DIR_TEST_DATA, &config_dir)) { - ADD_FAILURE() - << "base::PathService::Get could not resolve chrome::DIR_TEST_DATA"; - } - config_dir = - config_dir.AppendASCII("web_app_default_apps").AppendASCII(test_dir); - PreinstalledWebAppManager::SetConfigDirForTesting(&config_dir); + base::FilePath config_dir = GetConfigDir(test_dir); + SetPreinstalledWebAppConfigDirForTesting(&config_dir); auto preinstalled_web_app_manager = std::make_unique<PreinstalledWebAppManager>(profile); @@ -139,7 +138,7 @@ })); run_loop.Run(); - PreinstalledWebAppManager::SetConfigDirForTesting(nullptr); + SetPreinstalledWebAppConfigDirForTesting(nullptr); return result; } @@ -187,6 +186,26 @@ return profile; } + void SetExtraWebAppsDir(base::StringPiece test_dir, + base::StringPiece extra_web_apps_dir) { +#if BUILDFLAG(IS_CHROMEOS_ASH) + command_line_.GetProcessCommandLine()->AppendSwitchASCII( + ash::switches::kExtraWebAppsDir, extra_web_apps_dir); +#else + base::FilePath config_dir = GetConfigDir(test_dir); + auto params = crosapi::mojom::BrowserInitParams::New(); + params->default_paths = crosapi::mojom::DefaultPaths::New(); + params->default_paths->documents = + base::PathService::CheckedGet(chrome::DIR_USER_DOCUMENTS); + params->default_paths->downloads = + base::PathService::CheckedGet(chrome::DIR_DEFAULT_DOWNLOADS); + params->default_paths->preinstalled_web_app_config = config_dir; + params->default_paths->preinstalled_web_app_extra_config = + config_dir.AppendASCII(extra_web_apps_dir); + chrome::SetLacrosDefaultPathsFromInitParams(params.get()); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + } + void VerifySetOfApps(Profile* profile, const std::set<GURL>& expectations) { const auto install_options_list = LoadApps(kUserTypesTestDir, profile); ASSERT_EQ(expectations.size(), install_options_list.size()); @@ -209,6 +228,18 @@ ScopedTestingPreinstalledAppData preinstalled_web_app_override_; private: + base::FilePath GetConfigDir(base::StringPiece test_dir) { + // Uses the chrome/test/data/web_app_default_apps/test_dir directory + // that holds the *.json data files from which tests should parse as app + // configs. + base::FilePath config_dir; + if (!base::PathService::Get(chrome::DIR_TEST_DATA, &config_dir)) { + ADD_FAILURE() + << "base::PathService::Get could not resolve chrome::DIR_TEST_DATA"; + } + return config_dir.AppendASCII("web_app_default_apps").AppendASCII(test_dir); + } + #if BUILDFLAG(IS_CHROMEOS_ASH) ash::FakeChromeUserManager* user_manager() { return static_cast<ash::FakeChromeUserManager*>( @@ -219,6 +250,8 @@ // To support primary/non-primary users. std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_; + + base::test::ScopedCommandLine command_line_; #endif // To support context of browser threads. @@ -501,27 +534,19 @@ EXPECT_TRUE(profile->IsChild()); VerifySetOfApps(profile.get(), {GURL(kAppAllUrl), GURL(kAppChildUrl)}); } -#else -// No app is expected for non-ChromeOS builds. -TEST_F(PreinstalledWebAppManagerTest, NoApp) { - EXPECT_TRUE(LoadApps(kUserTypesTestDir, CreateProfile().get()).empty()); -} -#endif // BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_CHROMEOS_ASH) TEST_F(PreinstalledWebAppManagerTest, NonPrimaryProfile) { VerifySetOfApps(CreateProfile().get(), {GURL(kAppAllUrl), GURL(kAppUnmanagedUrl)}); } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) -// TODO(crbug.com/1252272): Enable extra web apps tests for Lacros. TEST_F(PreinstalledWebAppManagerTest, ExtraWebApps) { // The extra_web_apps directory contains two JSON files in different named // subdirectories. The --extra-web-apps-dir switch should control which // directory apps are loaded from. - base::test::ScopedCommandLine command_line; - command_line.GetProcessCommandLine()->AppendSwitchASCII( - ash::switches::kExtraWebAppsDir, "model1"); + SetExtraWebAppsDir("extra_web_apps", "model1"); const auto app_infos = LoadApps("extra_web_apps"); EXPECT_EQ(1u, app_infos.size()); @@ -529,15 +554,18 @@ } TEST_F(PreinstalledWebAppManagerTest, ExtraWebAppsNoMatchingDirectory) { - base::test::ScopedCommandLine command_line; - command_line.GetProcessCommandLine()->AppendSwitchASCII( - ash::switches::kExtraWebAppsDir, "model3"); + SetExtraWebAppsDir("extra_web_apps", "model3"); const auto app_infos = LoadApps("extra_web_apps"); EXPECT_EQ(0u, app_infos.size()); ExpectHistograms(/*enabled=*/0, /*disabled=*/0, /*errors=*/0); } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#else +// No app is expected for non-ChromeOS builds. +TEST_F(PreinstalledWebAppManagerTest, NoApp) { + EXPECT_TRUE(LoadApps(kUserTypesTestDir, CreateProfile().get()).empty()); +} +#endif // BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_CHROMEOS) class DisabledPreinstalledWebAppManagerTest
diff --git a/chrome/browser/web_applications/preinstalled_web_apps_browsertest.cc b/chrome/browser/web_applications/preinstalled_web_apps_browsertest.cc index 61e3183d..3bf70bb 100644 --- a/chrome/browser/web_applications/preinstalled_web_apps_browsertest.cc +++ b/chrome/browser/web_applications/preinstalled_web_apps_browsertest.cc
@@ -10,6 +10,7 @@ #include "build/chromeos_buildflags.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/web_applications/preinstalled_app_install_features.h" +#include "chrome/browser/web_applications/preinstalled_web_app_config_utils.h" #include "chrome/browser/web_applications/preinstalled_web_app_manager.h" #include "chrome/browser/web_applications/test/fake_os_integration_manager.h" #include "chrome/browser/web_applications/test/with_crosapi_param.h" @@ -30,7 +31,7 @@ PreinstalledWebAppsBrowserTest() { PreinstalledWebAppManager::SkipStartupForTesting(); // Ignore any default app configs on disk. - PreinstalledWebAppManager::SetConfigDirForTesting(&empty_path_); + SetPreinstalledWebAppConfigDirForTesting(&empty_path_); WebAppProvider::SetOsIntegrationManagerFactoryForTesting( [](Profile* profile) -> std::unique_ptr<OsIntegrationManager> { return std::make_unique<FakeOsIntegrationManager>( @@ -38,6 +39,10 @@ }); } + ~PreinstalledWebAppsBrowserTest() override { + SetPreinstalledWebAppConfigDirForTesting(nullptr); + } + void SetUpDefaultCommandLine(base::CommandLine* command_line) override { InProcessBrowserTest::SetUpDefaultCommandLine(command_line);
diff --git a/chrome/browser/window_placement/window_placement_printing_interactive_uitest.cc b/chrome/browser/window_placement/window_placement_printing_interactive_uitest.cc index 8efceba..b10fccc 100644 --- a/chrome/browser/window_placement/window_placement_printing_interactive_uitest.cc +++ b/chrome/browser/window_placement/window_placement_printing_interactive_uitest.cc
@@ -25,6 +25,15 @@ class WindowPlacementTest : public InProcessBrowserTest { public: + void SetUp() override { +#if !BUILDFLAG(IS_CHROMEOS_ASH) + display::Screen::SetScreenInstance(&screen_); + screen_.display_list().AddDisplay({1, gfx::Rect(0, 0, 803, 600)}, + display::DisplayList::Type::PRIMARY); +#endif + InProcessBrowserTest::SetUp(); + } + void SetUpOnMainThread() override { // Window placement features are only available on secure contexts. https_test_server_ = std::make_unique<net::EmbeddedTestServer>( @@ -33,10 +42,20 @@ ASSERT_TRUE(https_test_server_->Start()); } + void TearDown() override { + InProcessBrowserTest::TearDown(); +#if !BUILDFLAG(IS_CHROMEOS_ASH) + display::Screen::SetScreenInstance(nullptr); +#endif + } + protected: std::unique_ptr<net::EmbeddedTestServer> https_test_server_; base::test::ScopedFeatureList scoped_feature_list_{ blink::features::kWindowPlacement}; +#if !BUILDFLAG(IS_CHROMEOS_ASH) + display::ScreenBase screen_; +#endif }; // TODO(crbug.com/1042990): Windows crashes static casting to ScreenWin. @@ -56,11 +75,6 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager()) .UpdateDisplay("0+0-803x600"); -#else - display::ScreenBase screen; - screen.display_list().AddDisplay({1, gfx::Rect(0, 0, 803, 600)}, - display::DisplayList::Type::PRIMARY); - display::test::ScopedScreenOverride screen_override(&screen); #endif // BUILDFLAG(IS_CHROMEOS_ASH) ASSERT_EQ(1, display::Screen::GetScreen()->GetNumDisplays()); @@ -99,9 +113,9 @@ display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager()) .UpdateDisplay("0+0-807x600"); #else - screen.display_list().UpdateDisplay({1, gfx::Rect(0, 0, 807, 600)}, - display::DisplayList::Type::PRIMARY); - EXPECT_EQ(screen.display_list().displays().size(), 1u); + screen_.display_list().UpdateDisplay({1, gfx::Rect(0, 0, 807, 600)}, + display::DisplayList::Type::PRIMARY); + EXPECT_EQ(screen_.display_list().displays().size(), 1u); #endif // BUILDFLAG(IS_CHROMEOS_ASH) ASSERT_EQ(1, display::Screen::GetScreen()->GetNumDisplays()); @@ -116,9 +130,9 @@ display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager()) .UpdateDisplay("0+0-807x600,1000+0-804x600"); #else - screen.display_list().AddDisplay({2, gfx::Rect(1000, 0, 804, 600)}, - display::DisplayList::Type::NOT_PRIMARY); - EXPECT_EQ(screen.display_list().displays().size(), 2u); + screen_.display_list().AddDisplay({2, gfx::Rect(1000, 0, 804, 600)}, + display::DisplayList::Type::NOT_PRIMARY); + EXPECT_EQ(screen_.display_list().displays().size(), 2u); #endif // BUILDFLAG(IS_CHROMEOS_ASH) ASSERT_EQ(2, display::Screen::GetScreen()->GetNumDisplays());
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 9868acf1..2ca5cd8 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1652982811-2fdf2c43be67d816ba181468f29ead94c38a3207.profdata +chrome-linux-main-1653004718-550f92d458d9543873af601aef4d70240f640880.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index fe98ded..c99bdfb1 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1652982811-ad1c4ef9176e8eedd9baead64a3dbdc7f3a1f038.profdata +chrome-mac-arm-main-1653004718-e355640cf3224109cd9cf7dc418dc3bc876c4f5b.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index ba9c95f..f48da14e 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1652982811-7012145e83da8501e81be3da58aaba6d62c9623c.profdata +chrome-mac-main-1653004718-c2ca067c3647bbce4d00287f02758d82633f0fa9.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index f4ba7db..aee8e8a 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1652982811-78a4c035bd06b470693241830b4b763a3d090d32.profdata +chrome-win32-main-1653004718-c2433064b36fa3564a7f8b552448083cded1b1fc.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 7ce8c56..b40073c67 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1652982811-a29cc5640d9014852937387704bfc56637e8411a.profdata +chrome-win64-main-1653004718-61b6082e36edd8b9bd57650fde09bf7ab12acb8e.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index dd21e7f4..ff727a14 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -284,6 +284,10 @@ const base::Feature kDesktopPWAsEnforceWebAppSettingsPolicy{ "DesktopPWAsEnforceWebAppSettingsPolicy", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enables showing a detailed install dialog for user installs. +const base::Feature kDesktopPWAsDetailedInstallDialog{ + "DesktopPWAsDetailedInstallDialog", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables or disables Desktop PWAs to be auto-started on OS login. const base::Feature kDesktopPWAsRunOnOsLogin { "DesktopPWAsRunOnOsLogin", @@ -307,6 +311,7 @@ // Serves web app settings at chrome://app-settings/<app-id>. const base::Feature kDesktopPWAsWebAppSettingsPage{ "DesktopPWAsWebAppSettingsPage", base::FEATURE_ENABLED_BY_DEFAULT}; + // Controls whether Chrome Apps are supported. See https://crbug.com/1221251. // If the feature is disabled, Chrome Apps continue to work. If enabled, Chrome // Apps will not launch and will be marked in the UI as deprecated.
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index d73c00f..3ab6dea 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -208,6 +208,9 @@ extern const base::Feature kDesktopPWAsFlashAppNameInsteadOfOrigin; COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::Feature kDesktopPWAsDetailedInstallDialog; + +COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kDesktopPWAsRunOnOsLogin; COMPONENT_EXPORT(CHROME_FEATURES)
diff --git a/chrome/common/chrome_paths_lacros.cc b/chrome/common/chrome_paths_lacros.cc index 85d1ba68..3f26f06e 100644 --- a/chrome/common/chrome_paths_lacros.cc +++ b/chrome/common/chrome_paths_lacros.cc
@@ -26,6 +26,8 @@ base::FilePath android_files_dir; base::FilePath linux_files_dir; base::FilePath share_cache_dir; + base::FilePath preinstalled_web_app_config_dir; + base::FilePath preinstalled_web_app_extra_config_dir; }; DefaultPaths& GetDefaultPaths() { @@ -35,14 +37,17 @@ } // namespace -void SetLacrosDefaultPaths(const base::FilePath& documents_dir, - const base::FilePath& downloads_dir, - const base::FilePath& drivefs, - const base::FilePath& removable_media_dir, - const base::FilePath& android_files_dir, - const base::FilePath& linux_files_dir, - const base::FilePath& ash_resources_dir, - const base::FilePath& share_cache_dir) { +void SetLacrosDefaultPaths( + const base::FilePath& documents_dir, + const base::FilePath& downloads_dir, + const base::FilePath& drivefs, + const base::FilePath& removable_media_dir, + const base::FilePath& android_files_dir, + const base::FilePath& linux_files_dir, + const base::FilePath& ash_resources_dir, + const base::FilePath& share_cache_dir, + const base::FilePath& preinstalled_web_app_config_dir, + const base::FilePath& preinstalled_web_app_extra_config_dir) { DCHECK(!documents_dir.empty()); DCHECK(documents_dir.IsAbsolute()); GetDefaultPaths().documents_dir = documents_dir; @@ -60,6 +65,10 @@ chromeos::lacros_paths::SetAshResourcesPath(ash_resources_dir); GetDefaultPaths().share_cache_dir = share_cache_dir; + GetDefaultPaths().preinstalled_web_app_config_dir = + preinstalled_web_app_config_dir; + GetDefaultPaths().preinstalled_web_app_extra_config_dir = + preinstalled_web_app_extra_config_dir; } void SetLacrosDefaultPathsFromInitParams( @@ -86,11 +95,23 @@ base::FilePath share_cache_dir; if (init_params->default_paths->share_cache.has_value()) share_cache_dir = init_params->default_paths->share_cache.value(); + base::FilePath preinstalled_web_app_config_dir; + if (init_params->default_paths->preinstalled_web_app_config.has_value()) { + preinstalled_web_app_config_dir = + init_params->default_paths->preinstalled_web_app_config.value(); + } + base::FilePath preinstalled_web_app_extra_config_dir; + if (init_params->default_paths->preinstalled_web_app_extra_config + .has_value()) { + preinstalled_web_app_extra_config_dir = + init_params->default_paths->preinstalled_web_app_extra_config.value(); + } chrome::SetLacrosDefaultPaths( init_params->default_paths->documents, init_params->default_paths->downloads, drivefs_dir, removable_media_dir, - android_files_dir, linux_files_dir, ash_resources_dir, share_cache_dir); + android_files_dir, linux_files_dir, ash_resources_dir, share_cache_dir, + preinstalled_web_app_config_dir, preinstalled_web_app_extra_config_dir); } } @@ -193,4 +214,18 @@ return true; } +bool GetPreinstalledWebAppConfigPath(base::FilePath* result) { + if (GetDefaultPaths().preinstalled_web_app_config_dir.empty()) + return false; + *result = GetDefaultPaths().preinstalled_web_app_config_dir; + return true; +} + +bool GetPreinstalledWebAppExtraConfigPath(base::FilePath* result) { + if (GetDefaultPaths().preinstalled_web_app_extra_config_dir.empty()) + return false; + *result = GetDefaultPaths().preinstalled_web_app_extra_config_dir; + return true; +} + } // namespace chrome
diff --git a/chrome/common/chrome_paths_lacros.h b/chrome/common/chrome_paths_lacros.h index bf52e76..95ea2b53 100644 --- a/chrome/common/chrome_paths_lacros.h +++ b/chrome/common/chrome_paths_lacros.h
@@ -17,14 +17,17 @@ // including documents, downloads, DriveFS, removable media, ARC storage // and Crostini's home directory. The paths are sent by ash-chrome and // are set early in lacros-chrome startup. -void SetLacrosDefaultPaths(const base::FilePath& documents_dir, - const base::FilePath& downloads_dir, - const base::FilePath& drivefs, - const base::FilePath& removable_media_dir, - const base::FilePath& android_files_dir, - const base::FilePath& linux_files_dir, - const base::FilePath& ash_resources_dir, - const base::FilePath& share_cache_dir); +void SetLacrosDefaultPaths( + const base::FilePath& documents_dir, + const base::FilePath& downloads_dir, + const base::FilePath& drivefs, + const base::FilePath& removable_media_dir, + const base::FilePath& android_files_dir, + const base::FilePath& linux_files_dir, + const base::FilePath& ash_resources_dir, + const base::FilePath& share_cache_dir, + const base::FilePath& preinstalled_web_app_config_dir, + const base::FilePath& preinstalled_web_app_extra_config_dir); // Sets the default paths from BrowserInitParams received from ash on startup. void SetLacrosDefaultPathsFromInitParams( @@ -43,6 +46,8 @@ bool GetAndroidFilesPath(base::FilePath* result); bool GetLinuxFilesPath(base::FilePath* result); bool GetShareCachePath(base::FilePath* result); +bool GetPreinstalledWebAppConfigPath(base::FilePath* result); +bool GetPreinstalledWebAppExtraConfigPath(base::FilePath* result); } // namespace chrome #endif // CHROME_COMMON_CHROME_PATHS_LACROS_H_
diff --git a/chrome/common/profiler/thread_profiler_platform_configuration.cc b/chrome/common/profiler/thread_profiler_platform_configuration.cc index ae63ed7..704b9bd8 100644 --- a/chrome/common/profiler/thread_profiler_platform_configuration.cc +++ b/chrome/common/profiler/thread_profiler_platform_configuration.cc
@@ -201,38 +201,29 @@ double AndroidPlatformConfiguration::GetChildProcessEnableFraction( metrics::CallStackProfileParams::Process process) const { - DCHECK_NE(metrics::CallStackProfileParams::Process::kBrowser, process); + // Profile all processes in browser test mode since they're disabled + // otherwise. + if (browser_test_mode_enabled()) + return DefaultPlatformConfiguration::GetChildProcessEnableFraction(process); - // Profile all supported processes in browser test mode. - if (browser_test_mode_enabled()) { - return 1.0; - } + if (process == metrics::CallStackProfileParams::Process::kRenderer) + return 0.4; - // TODO(https://crbug.com/1326430): Enable for all the default processes. - switch (process) { - case metrics::CallStackProfileParams::Process::kRenderer: - // There are empirically, on average, 1.3 renderer processes per browser - // process. This samples the renderer process at roughly the same - // frequency overall as the browser process. - // http://uma/p/chrome/timeline_v2?sid=39bc30a43a01d045204d0add05ad120a - return 0.75; - - default: - return 0.0; - } + // TODO(https://crbug.com/1004855): Enable for all the default processes. + return 0.0; } bool AndroidPlatformConfiguration::IsEnabledForThread( metrics::CallStackProfileParams::Process process, metrics::CallStackProfileParams::Thread thread) const { - // TODO(https://crbug.com/1326430): Enable for all the default processes. - switch (process) { - case metrics::CallStackProfileParams::Process::kRenderer: - return thread == metrics::CallStackProfileParams::Thread::kMain; - - default: - return false; + // Enable on renderer process main thread in production, for now. + if (process == metrics::CallStackProfileParams::Process::kRenderer && + thread == metrics::CallStackProfileParams::Thread::kMain) { + return true; } + + // Otherwise enable in dedicated ThreadProfiler browser tests. + return browser_test_mode_enabled(); } bool AndroidPlatformConfiguration::IsSupportedForChannel(
diff --git a/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc b/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc index b7d2d44..1520e8d 100644 --- a/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc +++ b/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc
@@ -151,8 +151,8 @@ #if BUILDFLAG(IS_ANDROID) EXPECT_EQ(0.0, config()->GetChildProcessEnableFraction( metrics::CallStackProfileParams::Process::kGpu)); - EXPECT_EQ(0.75, config()->GetChildProcessEnableFraction( - metrics::CallStackProfileParams::Process::kRenderer)); + EXPECT_EQ(0.4, config()->GetChildProcessEnableFraction( + metrics::CallStackProfileParams::Process::kRenderer)); EXPECT_EQ(0.0, config()->GetChildProcessEnableFraction( metrics::CallStackProfileParams::Process::kNetworkService));
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index f51a46b..39523f2 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2165,6 +2165,7 @@ "../browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc", "../browser/ui/views/web_apps/frame_toolbar/web_app_minimal_ui_test.cc", "../browser/ui/views/web_apps/protocol_handler_launch_dialog_browsertest.cc", + "../browser/ui/views/web_apps/web_app_detailed_install_dialog_browsertest.cc", "../browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc", "../browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc", "../browser/ui/views/webid/fake_delegate.cc", @@ -3180,6 +3181,7 @@ "../browser/ui/views/bubble/webui_bubble_manager_browsertest.cc", "../browser/ui/views/certificate_selector_dialog_browsertest.cc", "../browser/ui/views/collected_cookies_views_browsertest.cc", + "../browser/ui/views/commerce/ntp_discount_consent_dialog_view_browsertest.cc", "../browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc", "../browser/ui/views/extensions/blocked_action_dialog_view_browsertest.cc", "../browser/ui/views/extensions/extension_install_blocked_dialog_view_browsertest.cc",
diff --git a/chrome/test/base/chrome_test_suite.cc b/chrome/test/base/chrome_test_suite.cc index b4e8b5e..588c96f 100644 --- a/chrome/test/base/chrome_test_suite.cc +++ b/chrome/test/base/chrome_test_suite.cc
@@ -117,14 +117,17 @@ // specific path doesn't matter as long as it exists. CHECK(scoped_temp_dir_.CreateUniqueTempDir()); base::FilePath temp_path = scoped_temp_dir_.GetPath(); - chrome::SetLacrosDefaultPaths(/*documents_dir=*/temp_path, - /*downloads_dir=*/temp_path, - /*drivefs=*/base::FilePath(), - /*removable_media_dir=*/base::FilePath(), - /*android_files_dir=*/base::FilePath(), - /*linux_files_dir=*/base::FilePath(), - /*ash_resources_dir=*/base::FilePath(), - /*share_cache_dir=*/temp_path); + chrome::SetLacrosDefaultPaths( + /*documents_dir=*/temp_path, + /*downloads_dir=*/temp_path, + /*drivefs=*/base::FilePath(), + /*removable_media_dir=*/base::FilePath(), + /*android_files_dir=*/base::FilePath(), + /*linux_files_dir=*/base::FilePath(), + /*ash_resources_dir=*/base::FilePath(), + /*share_cache_dir=*/temp_path, + /*preinstalled_web_app_config_dir=*/base::FilePath(), + /*preinstalled_web_app_extra_config_dir=*/base::FilePath()); #endif // BUILDFLAG(IS_CHROMEOS_LACROS) }
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc index 5c5e1d4..ec659c51 100644 --- a/chrome/test/base/in_process_browser_test.cc +++ b/chrome/test/base/in_process_browser_test.cc
@@ -119,6 +119,10 @@ #include "ui/events/test/event_generator.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) +#if defined(USE_OZONE) +#include "ui/views/test/test_desktop_screen_ozone.h" +#endif + #if defined(TOOLKIT_VIEWS) #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/tabs/tab.h" @@ -595,6 +599,22 @@ return true; } +void InProcessBrowserTest::SetScreenInstance() { + // TODO(crbug.com/1317416): On wayland platform, we need to check if the + // wayland-ozone platform is initialized at this point due to the async + // initialization of the display. Investigate if we can eliminate + // IsOzoneInitialized. +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) + if (!display::Screen::HasScreen() && + views::test::TestDesktopScreenOzone::IsOzoneInitialized()) { + // This is necessary for interactive UI tests. + // It is enabled in interactive_ui_tests_main.cc + // (or through GPUMain) + screen_ = views::test::TestDesktopScreenOzone::Create(); + } +#endif +} + #if !BUILDFLAG(IS_MAC) void InProcessBrowserTest::OpenDevToolsWindow( content::WebContents* web_contents) {
diff --git a/chrome/test/base/in_process_browser_test.h b/chrome/test/base/in_process_browser_test.h index b9ac30b..e154efc 100644 --- a/chrome/test/base/in_process_browser_test.h +++ b/chrome/test/base/in_process_browser_test.h
@@ -52,6 +52,10 @@ } #endif // defined(TOOLKIT_VIEWS) +namespace display { +class Screen; +} + class Browser; #if BUILDFLAG(IS_CHROMEOS_LACROS) class FakeAccountManagerUI; @@ -225,7 +229,7 @@ [[nodiscard]] virtual bool SetUpUserDataDirectory(); // Initializes the display::Screen instance. - virtual void SetScreenInstance() {} + virtual void SetScreenInstance(); // BrowserTestBase: void PreRunTestOnMainThread() override; @@ -314,6 +318,10 @@ FakeAccountManagerUI* GetFakeAccountManagerUI() const; #endif // BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) + std::unique_ptr<display::Screen> screen_; +#endif + private: void Initialize();
diff --git a/chrome/test/data/capability_delegation/fullscreen_request_delegation_initiator.html b/chrome/test/data/capability_delegation/fullscreen_request_delegation_initiator.html new file mode 100644 index 0000000..ebe7a3f --- /dev/null +++ b/chrome/test/data/capability_delegation/fullscreen_request_delegation_initiator.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<!-- +Copyright 2022 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. +--> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>Fullscreen request delegation initiator</title> +</head> +<script> + // https://wicg.github.io/capability-delegation/spec.html + async function delegateCapability(target, origin, capability) { + const promise = new Promise(resolve => { + window.addEventListener("message", e => resolve(e.data), /*once=*/true); + }); + target.postMessage("", { targetOrigin: origin, delegate: capability }); + return promise; + } +</script> +</html>
diff --git a/chrome/test/data/capability_delegation/fullscreen_request_delegation_receiver.html b/chrome/test/data/capability_delegation/fullscreen_request_delegation_receiver.html new file mode 100644 index 0000000..7998d5c7 --- /dev/null +++ b/chrome/test/data/capability_delegation/fullscreen_request_delegation_receiver.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<!-- +Copyright 2022 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. +--> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>Fullscreen request delegation receiver</title> +</head> +<script> + // https://wicg.github.io/capability-delegation/spec.html + async function requestFullscreenAndReport(event) { + document.documentElement.requestFullscreen().finally(() => { + event.source.postMessage(!!document.fullscreenElement, "*"); + }); + } + + window.addEventListener("message", requestFullscreenAndReport); +</script> +</html>
diff --git a/chrome/test/data/extensions/api_test/favicon/extension/test.js b/chrome/test/data/extensions/api_test/favicon/extension/test.js index 04bf6db..7eec4aba 100644 --- a/chrome/test/data/extensions/api_test/favicon/extension/test.js +++ b/chrome/test/data/extensions/api_test/favicon/extension/test.js
@@ -84,6 +84,46 @@ })); }); Promise.all(promises).then(() => chrome.test.succeed()); - } + }, + + // Verify that the requested icon size is returned. + async function cachedResolutions() { + const port = (await chrome.test.getConfig()).testServer.port; + const pixelsArr = [16, 32, 64, 48]; + const promises = pixelsArr.map(pixels => { + return new Promise((resolve, reject) => { + const favicon = new Favicon({ + pageUrl: `http://www.example.com:${ + port}/extensions/favicon/test_file.html`, + size: pixels + }); + const image = new Image(); + image.src = favicon.getUrl(); + image.onload = () => { + chrome.test.assertEq(pixels, image.height); + chrome.test.assertEq(pixels, image.width); + resolve(); + } + }); + }); + Promise.all(promises).then(() => chrome.test.succeed()); + }, + + // The default favicon size is 16. + async function defaultSize() { + const port = (await chrome.test.getConfig()).testServer.port; + const expected = 16; + const favicon = new Favicon({ + pageUrl: + `http://www.example.com:${port}/extensions/favicon/test_file.html` + }); + const image = new Image(); + image.src = favicon.getUrl(); + image.onload = () => { + chrome.test.assertEq(expected, image.height); + chrome.test.assertEq(expected, image.width); + chrome.test.succeed(); + } + }, ]); }
diff --git a/chrome/test/data/system_extensions/window_manager_extension/manifest.json b/chrome/test/data/system_extensions/window_manager_extension/manifest.json new file mode 100644 index 0000000..8b889983 --- /dev/null +++ b/chrome/test/data/system_extensions/window_manager_extension/manifest.json
@@ -0,0 +1,7 @@ +{ + "name": "Window Manager Extension", + "short_name": "WM Extension", + "service_worker_url": "/sw.js", + "id": "01020304", + "type": "echo" +}
diff --git a/chrome/test/data/system_extensions/window_manager_extension/sw.js b/chrome/test/data/system_extensions/window_manager_extension/sw.js new file mode 100644 index 0000000..bf96b55 --- /dev/null +++ b/chrome/test/data/system_extensions/window_manager_extension/sw.js
@@ -0,0 +1,8 @@ +// Copyright 2022 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. +'use strict'; + +chromeos.windowManagement.addEventListener('start', e => { + console.log('start event fired'); +});
diff --git a/chrome/test/data/webui/chromeos/personalization_app/avatar_camera_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/avatar_camera_element_test.ts index d46942d6..4c21969 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/avatar_camera_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/avatar_camera_element_test.ts
@@ -170,6 +170,30 @@ assertEquals(2, numFrames, '2 frames requested for video'); }); + test('displays a loading spinner button while capturing frames', async () => { + avatarCameraElement = + initElement(AvatarCamera, {mode: AvatarCameraMode.VIDEO}); + await waitAfterNextRender(avatarCameraElement); + + assertEquals( + null, avatarCameraElement.shadowRoot?.getElementById('loadingButton'), + 'no loading button shown yet'); + + avatarCameraElement?.shadowRoot?.getElementById('takePhoto')?.click(); + await mockWebcamUtils.whenCalled('captureFrames'); + + const loadingButton = avatarCameraElement.shadowRoot?.getElementById( + 'loadingButton') as HTMLButtonElement; + assertTrue(!!loadingButton, 'loading button is shown'); + assertTrue(loadingButton.disabled, 'loading button is disabled'); + + await waitAfterNextRender(avatarCameraElement); + + assertEquals( + null, avatarCameraElement.shadowRoot?.getElementById('loadingButton'), + 'loading button hidden again'); + }); + test('calls saveCameraImage with data on confirmPhoto click', async () => { avatarCameraElement = initElement(AvatarCamera, {mode: AvatarCameraMode.CAMERA});
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js b/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js index 2833ca4..1b4ac5f 100644 --- a/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js +++ b/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
@@ -682,6 +682,16 @@ }); }); + test('SaveLog', () => { + const states = [{state: State.kRepairComplete, error: RmadErrorCode.kOk}]; + service.setStates(states); + const expectedSavePath = {'path': 'fake/save/path'}; + service.setSaveLogResult(expectedSavePath); + return service.saveLog().then((res) => { + assertEquals(expectedSavePath, res.savePath); + }); + }); + test('SetGetPowerwashRequiredResultTrueUpdatesResult', () => { service.setGetPowerwashRequiredResult(true);
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js index 4401254..ace671dd 100644 --- a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js +++ b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js
@@ -327,6 +327,22 @@ assertTrue(logsDialog.open); }); + test('SaveLogButtonSavesTheLog', async () => { + const resolver = new PromiseResolver(); + await initializeRepairCompletePage(); + + let callCount = 0; + service.saveLog = () => { + callCount++; + return resolver.promise; + }; + + await clickButton('#saveLogDialogButton'); + await flushTasks(); + + assertEquals(1, callCount); + }); + test('BatteryCutButtonDisabledByDefault', async () => { await initializeRepairCompletePage(); const button = component.shadowRoot.querySelector('#batteryCutButton');
diff --git a/chrome/test/data/webui/history/history_metrics_test.ts b/chrome/test/data/webui/history/history_metrics_test.ts index fc7fa50..0244ad2 100644 --- a/chrome/test/data/webui/history/history_metrics_test.ts +++ b/chrome/test/data/webui/history/history_metrics_test.ts
@@ -235,4 +235,17 @@ .querySelector<HTMLElement>('#menuDeleteButton')!.click(); assertEquals(1, histogram[SyncedTabsHistogram.HIDE_FOR_NOW]); }); + + test('history-clusters-duration', async () => { + await finishSetup([]); + + navigateTo('/journeys', app); + await flushTasks(); + + navigateTo('/history', app); + await flushTasks(); + + const args = await testService.whenCalled('recordLongTime'); + assertEquals(args[0], 'History.Clusters.WebUISessionDuration'); + }); });
diff --git a/chrome/test/data/webui/history/test_browser_service.ts b/chrome/test/data/webui/history/test_browser_service.ts index ad7890d..fb03426 100644 --- a/chrome/test/data/webui/history/test_browser_service.ts +++ b/chrome/test/data/webui/history/test_browser_service.ts
@@ -30,6 +30,7 @@ 'queryHistory', 'queryHistoryContinuation', 'recordHistogram', + 'recordLongTime', 'removeVisits', 'startSignInFlow', ]); @@ -159,6 +160,11 @@ } recordTime() {} + + recordLongTime(histogram: string, value: number) { + this.methodCalled('recordLongTime', histogram, value); + } + removeBookmark() {} startSignInFlow() {} }
diff --git a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js index ce36b53..c3ce1e4 100644 --- a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
@@ -64,6 +64,8 @@ GuestOsBrowserProxyImpl.instance_ = guestOsBrowserProxy; PolymerTest.clearBody(); crostiniPage = document.createElement('settings-crostini-page'); + crostiniPage.showCrostini = true; + crostiniPage.allowCrostini = true; document.body.appendChild(crostiniPage); testing.Test.disableAnimationsAndTransitions(); }); @@ -127,6 +129,22 @@ setCrostiniPrefs(false); }); + test('NotSupported', function() { + crostiniPage.showCrostini = false; + crostiniPage.allowCrostini = false; + flush(); + assertTrue(!!crostiniPage.$$('#enable')); + assertFalse(!!crostiniPage.$$('cr-policy-indicator')); + }); + + test('NotAllowed', function() { + crostiniPage.showCrostini = true; + crostiniPage.allowCrostini = false; + flush(); + assertTrue(!!crostiniPage.$$('#enable')); + assertTrue(!!crostiniPage.$$('cr-policy-indicator')); + }); + test('Enable', function() { const button = crostiniPage.$$('#enable'); assertTrue(!!button);
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_page_test.js b/chrome/test/data/webui/settings/chromeos/os_settings_page_test.js index d2ebffb..5daf360c 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_page_test.js
@@ -240,7 +240,6 @@ test('Check settings-crostini-page exists', async () => { init(); - settingsPage.showCrostini = true; const idleRender = settingsPage.shadowRoot.querySelector('settings-idle-load'); await idleRender.get();
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index 38d6e50d..a9351bb 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -2202,6 +2202,9 @@ <message name="IDS_PERSONALIZATION_APP_AVATAR_CONFIRM_VIDEO" desc="Label for the button to confirm webcam video"> Use this video </message> + <message name="IDS_PERSONALIZATION_APP_AVATAR_CAPTURE_IN_PROGRESS" desc="Label to indicate a webcam video capture is in progress"> + Taking video + </message> <message name="IDS_PERSONALIZATION_APP_AVATAR_REJECT_PHOTO" desc="Label for the button to reject webcam photo or video"> Retake </message>
diff --git a/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_AVATAR_CAPTURE_IN_PROGRESS.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_AVATAR_CAPTURE_IN_PROGRESS.png.sha1 new file mode 100644 index 0000000..ece96d0 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_AVATAR_CAPTURE_IN_PROGRESS.png.sha1
@@ -0,0 +1 @@ +0b0ed010b0f9c44dccc6941129ef8c96df797d60 \ No newline at end of file
diff --git a/chromeos/crosapi/cpp/crosapi_constants.cc b/chromeos/crosapi/cpp/crosapi_constants.cc index b6260ef7..97d0666 100644 --- a/chromeos/crosapi/cpp/crosapi_constants.cc +++ b/chromeos/crosapi/cpp/crosapi_constants.cc
@@ -18,6 +18,10 @@ // The file name of shared resource file. const char kSharedResourcesPackName[] = "resources_for_sharing.rspak"; +const char kSharedChrome100PercentPackName[] = + "chrome_100_percent_for_sharing.rspak"; +const char kSharedChrome200PercentPackName[] = + "chrome_200_percent_for_sharing.rspak"; // Release channel key in /etc/lsb-release. const char kChromeOSReleaseTrack[] = "CHROMEOS_RELEASE_TRACK";
diff --git a/chromeos/crosapi/cpp/crosapi_constants.h b/chromeos/crosapi/cpp/crosapi_constants.h index 68186bd..a7bc33a 100644 --- a/chromeos/crosapi/cpp/crosapi_constants.h +++ b/chromeos/crosapi/cpp/crosapi_constants.h
@@ -14,6 +14,8 @@ COMPONENT_EXPORT(CROSAPI) extern const char kLacrosUserDataPath[]; COMPONENT_EXPORT(CROSAPI) extern const char kSharedResourcesPackName[]; +COMPONENT_EXPORT(CROSAPI) extern const char kSharedChrome100PercentPackName[]; +COMPONENT_EXPORT(CROSAPI) extern const char kSharedChrome200PercentPackName[]; COMPONENT_EXPORT(CROSAPI) extern const char kChromeOSReleaseTrack[];
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom index e553179..0551899 100644 --- a/chromeos/crosapi/mojom/crosapi.mojom +++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -567,8 +567,8 @@ // future compatibility, to avoid assumptions about where on disk the directory // is located. // -// Next version: 34 -// Next id: 9 +// Next version: 35 +// Next id: 11 [Stable] struct DefaultPaths { // The default (non-configurable) directory for documents. For example, @@ -606,6 +606,13 @@ // The default (non-configurable) directory for shared files. For example, // /home/chronos/u-<hash>/ShareCache. [MinVersion=33] mojo_base.mojom.FilePath? share_cache@8; + + // The directory where default web app configs are stored. + [MinVersion=34] mojo_base.mojom.FilePath? preinstalled_web_app_config@9; + + // The directory where additional web app configs are stored. + [MinVersion=34] mojo_base.mojom.FilePath? + preinstalled_web_app_extra_config@10; }; // The device specific data needed in Lacros.
diff --git a/chromeos/dbus/cros_disks/fake_cros_disks_client.cc b/chromeos/dbus/cros_disks/fake_cros_disks_client.cc index 0cd632cd..263eb394 100644 --- a/chromeos/dbus/cros_disks/fake_cros_disks_client.cc +++ b/chromeos/dbus/cros_disks/fake_cros_disks_client.cc
@@ -146,13 +146,14 @@ // Remove the dummy mounted directory if it exists. if (mounted_paths_.erase(base::FilePath::FromUTF8Unsafe(device_path))) { - base::ThreadPool::PostTaskAndReply( + base::ThreadPool::PostTask( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::GetDeletePathRecursivelyCallback( - base::FilePath::FromUTF8Unsafe(device_path)), - base::BindOnce(std::move(callback), unmount_error_)); + base::FilePath::FromUTF8Unsafe(device_path), + base::OnceCallback<void(bool)>(base::DoNothing()) + .Then(base::BindOnce(std::move(callback), unmount_error_)))); } else { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), unmount_error_));
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt index e9339d6..ee2a645 100644 --- a/chromeos/profiles/atom.afdo.newest.txt +++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-atom-104-5045.0-1652697047-benchmark-104.0.5070.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-atom-104-5045.0-1652697047-benchmark-104.0.5071.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt index 997c70a..23d4fe3 100644 --- a/chromeos/profiles/bigcore.afdo.newest.txt +++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-bigcore-104-5045.0-1652694334-benchmark-104.0.5070.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-bigcore-104-5045.0-1652694334-benchmark-104.0.5071.0-r1-redacted.afdo.xz
diff --git a/chromeos/services/cros_healthd/private/cpp/BUILD.gn b/chromeos/services/cros_healthd/private/cpp/BUILD.gn index 8d213ca..3714d2e 100644 --- a/chromeos/services/cros_healthd/private/cpp/BUILD.gn +++ b/chromeos/services/cros_healthd/private/cpp/BUILD.gn
@@ -11,14 +11,9 @@ sources = [ "data_collector.cc", "data_collector.h", - "internal_service_factory.cc", - "internal_service_factory.h", - "internal_service_factory_impl.cc", - "internal_service_factory_impl.h", ] deps = [ "//base", - "//chromeos/services/network_health/public/mojom", "//content/public/browser:browser", "//ui/events/devices", "//ui/events/ozone/evdev:event_device_info", @@ -35,17 +30,12 @@ source_set("unit_tests") { testonly = true - sources = [ - "data_collector_unittest.cc", - "internal_service_factory_impl_unittest.cc", - ] + sources = [ "data_collector_unittest.cc" ] deps = [ ":cpp", "//base/test:test_support", "//content/test:test_support", - "//mojo/core/embedder", "//mojo/public/cpp/bindings", - "//testing/gmock", "//testing/gtest", "//ui/events/devices", "//ui/events/devices:test_support",
diff --git a/chromeos/services/cros_healthd/private/cpp/internal_service_factory.cc b/chromeos/services/cros_healthd/private/cpp/internal_service_factory.cc deleted file mode 100644 index b2a1ff5..0000000 --- a/chromeos/services/cros_healthd/private/cpp/internal_service_factory.cc +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2021 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 "chromeos/services/cros_healthd/private/cpp/internal_service_factory.h" - -#include "base/no_destructor.h" -#include "chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl.h" - -namespace chromeos { -namespace cros_healthd { -namespace internal { - -InternalServiceFactory* InternalServiceFactory::GetInstance() { - static base::NoDestructor<InternalServiceFactoryImpl> service_factory; - return service_factory.get(); -} - -} // namespace internal -} // namespace cros_healthd -} // namespace chromeos
diff --git a/chromeos/services/cros_healthd/private/cpp/internal_service_factory.h b/chromeos/services/cros_healthd/private/cpp/internal_service_factory.h deleted file mode 100644 index aceb24b..0000000 --- a/chromeos/services/cros_healthd/private/cpp/internal_service_factory.h +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2021 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 CHROMEOS_SERVICES_CROS_HEALTHD_PRIVATE_CPP_INTERNAL_SERVICE_FACTORY_H_ -#define CHROMEOS_SERVICES_CROS_HEALTHD_PRIVATE_CPP_INTERNAL_SERVICE_FACTORY_H_ - -#include <mojo/public/cpp/bindings/pending_receiver.h> - -#include "chromeos/services/cros_healthd/private/mojom/cros_healthd_internal.mojom-forward.h" -#include "chromeos/services/network_health/public/mojom/network_diagnostics.mojom.h" -#include "chromeos/services/network_health/public/mojom/network_health.mojom.h" - -namespace chromeos { -namespace cros_healthd { -namespace internal { - -class InternalServiceFactory { - public: - static InternalServiceFactory* GetInstance(); - - using NetworkHealthServiceReceiver = mojo::PendingReceiver< - chromeos::network_health::mojom::NetworkHealthService>; - using BindNetworkHealthServiceCallback = - base::RepeatingCallback<void(NetworkHealthServiceReceiver)>; - - using NetworkDiagnosticsRoutinesReceiver = mojo::PendingReceiver< - chromeos::network_diagnostics::mojom::NetworkDiagnosticsRoutines>; - using BindNetworkDiagnosticsRoutinesCallback = - base::RepeatingCallback<void(NetworkDiagnosticsRoutinesReceiver)>; - - // Sets a callback to request binding a PendingReceiver to the - // NetworkHealthService. This callback is invoked when cros_healthd connects. - virtual void SetBindNetworkHealthServiceCallback( - BindNetworkHealthServiceCallback callback) = 0; - // Sets a callback to request binding a PendingReceiver to the - // NetworkDiagnosticsRoutines interface. This callback is invoked when - // cros_healthd connects. - virtual void SetBindNetworkDiagnosticsRoutinesCallback( - BindNetworkDiagnosticsRoutinesCallback callback) = 0; - // Binds a mojo pending receiver to this service. - virtual void BindReceiver( - mojo::PendingReceiver<mojom::CrosHealthdInternalServiceFactory> - receiver) = 0; - - protected: - InternalServiceFactory() = default; - InternalServiceFactory(const InternalServiceFactory&) = delete; - InternalServiceFactory& operator=(const InternalServiceFactory&) = delete; - virtual ~InternalServiceFactory() = default; -}; - -} // namespace internal -} // namespace cros_healthd -} // namespace chromeos - -// TODO(https://crbug.com/1164001): remove when moved to ash. -namespace ash { -namespace cros_healthd { -namespace internal { -using ::chromeos::cros_healthd::internal::InternalServiceFactory; -} -} // namespace cros_healthd -} // namespace ash - -#endif // CHROMEOS_SERVICES_CROS_HEALTHD_PRIVATE_CPP_INTERNAL_SERVICE_FACTORY_H_
diff --git a/chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl.cc b/chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl.cc deleted file mode 100644 index 74374b5..0000000 --- a/chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl.cc +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2021 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 "chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl.h" - -namespace chromeos { -namespace cros_healthd { -namespace internal { - -InternalServiceFactoryImpl::InternalServiceFactoryImpl() = default; - -InternalServiceFactoryImpl::~InternalServiceFactoryImpl() = default; - -void InternalServiceFactoryImpl::SetBindNetworkHealthServiceCallback( - BindNetworkHealthServiceCallback callback) { - DCHECK(!callback.is_null()); - base::AutoLock lock(lock_); - bind_network_health_callback_ = std::move(callback); - for (auto& receiver : pending_network_health_receivers_) { - bind_network_health_callback_.Run(std::move(receiver)); - } - pending_network_health_receivers_.clear(); -} - -void InternalServiceFactoryImpl::SetBindNetworkDiagnosticsRoutinesCallback( - BindNetworkDiagnosticsRoutinesCallback callback) { - DCHECK(!callback.is_null()); - base::AutoLock lock(lock_); - bind_network_diag_callback_ = std::move(callback); - for (auto& receiver : pending_network_diag_receivers_) { - bind_network_diag_callback_.Run(std::move(receiver)); - } - pending_network_diag_receivers_.clear(); -} - -void InternalServiceFactoryImpl::BindReceiver( - mojo::PendingReceiver<mojom::CrosHealthdInternalServiceFactory> receiver) { - receiver_set_.Add(/*impl=*/this, std::move(receiver)); -} - -void InternalServiceFactoryImpl::GetNetworkHealthService( - NetworkHealthServiceReceiver receiver) { - base::AutoLock lock(lock_); - if (bind_network_health_callback_.is_null()) { - pending_network_health_receivers_.push_back(std::move(receiver)); - return; - } - bind_network_health_callback_.Run(std::move(receiver)); -} - -void InternalServiceFactoryImpl::GetNetworkDiagnosticsRoutines( - NetworkDiagnosticsRoutinesReceiver receiver) { - base::AutoLock lock(lock_); - if (bind_network_diag_callback_.is_null()) { - pending_network_diag_receivers_.push_back(std::move(receiver)); - return; - } - bind_network_diag_callback_.Run(std::move(receiver)); -} - -} // namespace internal -} // namespace cros_healthd -} // namespace chromeos
diff --git a/chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl.h b/chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl.h deleted file mode 100644 index c0a1e242..0000000 --- a/chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl.h +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2021 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 CHROMEOS_SERVICES_CROS_HEALTHD_PRIVATE_CPP_INTERNAL_SERVICE_FACTORY_IMPL_H_ -#define CHROMEOS_SERVICES_CROS_HEALTHD_PRIVATE_CPP_INTERNAL_SERVICE_FACTORY_IMPL_H_ - -#include "base/synchronization/lock.h" -#include "chromeos/services/cros_healthd/private/cpp/internal_service_factory.h" -#include "chromeos/services/cros_healthd/private/mojom/cros_healthd_internal.mojom.h" -#include "mojo/public/cpp/bindings/receiver_set.h" - -namespace chromeos { -namespace cros_healthd { -namespace internal { - -class InternalServiceFactoryImpl - : public InternalServiceFactory, - public mojom::CrosHealthdInternalServiceFactory { - public: - InternalServiceFactoryImpl(); - InternalServiceFactoryImpl(const InternalServiceFactoryImpl&) = delete; - InternalServiceFactoryImpl& operator=(const InternalServiceFactoryImpl&) = - delete; - - public: - // InternalServiceFactory overrides. - void SetBindNetworkHealthServiceCallback( - BindNetworkHealthServiceCallback callback) override; - void SetBindNetworkDiagnosticsRoutinesCallback( - BindNetworkDiagnosticsRoutinesCallback callback) override; - void BindReceiver( - mojo::PendingReceiver<mojom::CrosHealthdInternalServiceFactory> receiver) - override; - // mojom::CrosHealthdInternalServiceFactory overrides. - void GetNetworkHealthService(NetworkHealthServiceReceiver receiver) override; - void GetNetworkDiagnosticsRoutines( - NetworkDiagnosticsRoutinesReceiver receiver) override; - - protected: - ~InternalServiceFactoryImpl() override; - - private: - // The receiver set to handle connections. - mojo::ReceiverSet<mojom::CrosHealthdInternalServiceFactory> receiver_set_; - // Lock for access from main thread and mojo thread. - base::Lock lock_; - // Repeating callbacks that binds a mojo::PendingRemote and returns it. - BindNetworkHealthServiceCallback bind_network_health_callback_; - BindNetworkDiagnosticsRoutinesCallback bind_network_diag_callback_; - // Vectors to keep the pending receivers before the callbacks are ready. - std::vector<NetworkHealthServiceReceiver> pending_network_health_receivers_; - std::vector<NetworkDiagnosticsRoutinesReceiver> - pending_network_diag_receivers_; -}; - -} // namespace internal -} // namespace cros_healthd -} // namespace chromeos - -#endif // CHROMEOS_SERVICES_CROS_HEALTHD_PRIVATE_CPP_INTERNAL_SERVICE_FACTORY_IMPL_H_
diff --git a/chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl_unittest.cc b/chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl_unittest.cc deleted file mode 100644 index fa8df8d7..0000000 --- a/chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl_unittest.cc +++ /dev/null
@@ -1,116 +0,0 @@ -// Copyright 2021 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 "chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl.h" - -#include "base/test/bind.h" -#include "base/test/task_environment.h" -#include "chromeos/services/cros_healthd/private/cpp/internal_service_factory_impl.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace chromeos { -namespace cros_healthd { -namespace internal { -namespace { - -namespace network_health_mojom = ::chromeos::network_health::mojom; -namespace network_diag_mojom = ::chromeos::network_diagnostics::mojom; - -class CrosHealthdInternalServiceFactoryImplTest; - -class MockInternalServiceFactoryImpl : public InternalServiceFactoryImpl { - using InternalServiceFactoryImpl::InternalServiceFactoryImpl; -}; - -class CrosHealthdInternalServiceFactoryImplTest : public testing::Test { - public: - CrosHealthdInternalServiceFactoryImplTest() = default; - CrosHealthdInternalServiceFactoryImplTest( - const CrosHealthdInternalServiceFactoryImplTest&) = delete; - CrosHealthdInternalServiceFactoryImplTest& operator=( - const CrosHealthdInternalServiceFactoryImplTest&) = delete; - - void SetUp() override { - mock_internal_service_factory_.BindReceiver( - internal_service_factory_remote_.BindNewPipeAndPassReceiver()); - EXPECT_TRUE(internal_service_factory_remote_.is_connected()); - } - - void Flush() { internal_service_factory_remote_.FlushForTesting(); } - - InternalServiceFactoryImpl* mock_internal_service_factory() { - return &mock_internal_service_factory_; - } - - mojom::CrosHealthdInternalServiceFactory* internal_service_factory_remote() { - return internal_service_factory_remote_.get(); - } - - private: - base::test::TaskEnvironment task_environment_; - - MockInternalServiceFactoryImpl mock_internal_service_factory_; - mojo::Remote<mojom::CrosHealthdInternalServiceFactory> - internal_service_factory_remote_; -}; - -TEST_F(CrosHealthdInternalServiceFactoryImplTest, GetNetworkHealthService) { - mojo::Remote<network_health_mojom::NetworkHealthService> remote; - internal_service_factory_remote()->GetNetworkHealthService( - remote.BindNewPipeAndPassReceiver()); - remote.reset(); - internal_service_factory_remote()->GetNetworkHealthService( - remote.BindNewPipeAndPassReceiver()); - - int count = 0; - auto callback = base::BindLambdaForTesting( - [&](mojo::PendingReceiver<network_health_mojom::NetworkHealthService> - receiver) { ++count; }); - mock_internal_service_factory()->SetBindNetworkHealthServiceCallback( - callback); - Flush(); - ASSERT_EQ(count, 2); - - remote.reset(); - internal_service_factory_remote()->GetNetworkHealthService( - remote.BindNewPipeAndPassReceiver()); - remote.reset(); - internal_service_factory_remote()->GetNetworkHealthService( - remote.BindNewPipeAndPassReceiver()); - Flush(); - ASSERT_EQ(count, 4); -} - -TEST_F(CrosHealthdInternalServiceFactoryImplTest, GetNetworkDiagService) { - mojo::Remote<network_diag_mojom::NetworkDiagnosticsRoutines> remote; - internal_service_factory_remote()->GetNetworkDiagnosticsRoutines( - remote.BindNewPipeAndPassReceiver()); - remote.reset(); - internal_service_factory_remote()->GetNetworkDiagnosticsRoutines( - remote.BindNewPipeAndPassReceiver()); - - int count = 0; - auto callback = base::BindLambdaForTesting( - [&](mojo::PendingReceiver<network_diag_mojom::NetworkDiagnosticsRoutines> - receiver) { ++count; }); - mock_internal_service_factory()->SetBindNetworkDiagnosticsRoutinesCallback( - callback); - Flush(); - ASSERT_EQ(count, 2); - - remote.reset(); - internal_service_factory_remote()->GetNetworkDiagnosticsRoutines( - remote.BindNewPipeAndPassReceiver()); - remote.reset(); - internal_service_factory_remote()->GetNetworkDiagnosticsRoutines( - remote.BindNewPipeAndPassReceiver()); - Flush(); - ASSERT_EQ(count, 4); -} - -} // namespace -} // namespace internal -} // namespace cros_healthd -} // namespace chromeos
diff --git a/chromeos/services/cros_healthd/private/mojom/BUILD.gn b/chromeos/services/cros_healthd/private/mojom/BUILD.gn index 675fca46..ce983ef 100644 --- a/chromeos/services/cros_healthd/private/mojom/BUILD.gn +++ b/chromeos/services/cros_healthd/private/mojom/BUILD.gn
@@ -6,9 +6,5 @@ mojom("mojom") { sources = [ "cros_healthd_internal.mojom" ] - public_deps = [ - "//chromeos/services/cros_healthd/public/mojom", - "//chromeos/services/network_health/public/mojom", - "//mojo/public/mojom/base", - ] + public_deps = [ "//mojo/public/mojom/base" ] }
diff --git a/chromeos/services/cros_healthd/private/mojom/cros_healthd_internal.mojom b/chromeos/services/cros_healthd/private/mojom/cros_healthd_internal.mojom index d41b04f..333a6ad 100644 --- a/chromeos/services/cros_healthd/private/mojom/cros_healthd_internal.mojom +++ b/chromeos/services/cros_healthd/private/mojom/cros_healthd_internal.mojom
@@ -11,44 +11,6 @@ module chromeos.cros_healthd.internal.mojom; -import "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom"; -import "chromeos/services/network_health/public/mojom/network_diagnostics.mojom"; -import "chromeos/services/network_health/public/mojom/network_health.mojom"; - -// Interface for Chrome to bootstrap the connection between cros_healthd and -// Chrome. Chrome uses this interface to obtain cros_healthd services and -// to provide Chrome services. -// -// NextMinVersion: 1, NextIndex: 2 -interface ServiceBootstrap { - // Pass a receiver of service factory to cros_healthd to bind the services. - GetCrosHealthdServiceFactory@0(pending_receiver< - chromeos.cros_healthd.mojom.CrosHealthdServiceFactory> receiver); - // Pass a remote of internal service factory to cros_healthd for it to - // obtain the services in Chrome. This should be the only interface which - // the connection is passed from the provider side. All the services in - // Chrome should use internal service factory interface to provide services - // to cros_healthd. - // Should be called only once per connection. - SetCrosHealthdInternalServiceFactory@1(pending_remote< - CrosHealthdInternalServiceFactory> remote); -}; - -// Factory interface which allows remote ends (cros_healthd) to request -// implementations of several services in Chrome. -// -// NextMinVersion: 1, NextIndex: 2 -interface CrosHealthdInternalServiceFactory { - // NetworkHealthService provides network health information from chrome - // network stack. - GetNetworkHealthService@0(pending_receiver< - chromeos.network_health.mojom.NetworkHealthService> receiver); - // NetworkDiagnosticsRoutines provides network diagnostics routines to test - // network. - GetNetworkDiagnosticsRoutines@1(pending_receiver< - chromeos.network_diagnostics.mojom.NetworkDiagnosticsRoutines> receiver); -}; - // Collects data from chromium to Healthd. // // NextMinVersion: 1, NextIndex: 2
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc index ce8a8fc4..476fcad 100644 --- a/components/autofill/core/common/autofill_payments_features.cc +++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -80,7 +80,7 @@ // preflight call. const base::Feature kAutofillEnableSendingBcnInGetUploadDetails{ "AutofillEnableSendingBcnInGetUploadDetails", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // When enabled, if the user interacts with the manual fallback bottom sheet // on Android, it'll remain sticky until the user dismisses it.
diff --git a/components/certificate_transparency/chrome_ct_policy_enforcer.cc b/components/certificate_transparency/chrome_ct_policy_enforcer.cc index 884f44d..25b260f8 100644 --- a/components/certificate_transparency/chrome_ct_policy_enforcer.cc +++ b/components/certificate_transparency/chrome_ct_policy_enforcer.cc
@@ -21,7 +21,6 @@ #include "base/time/time.h" #include "base/values.h" #include "base/version.h" -#include "components/certificate_transparency/ct_features.h" #include "components/certificate_transparency/ct_known_logs.h" #include "crypto/sha2.h" #include "net/cert/ct_policy_status.h" @@ -246,14 +245,12 @@ // months. // Increases the SCT requirements for certificates with a lifetime between // 180 days and 15 months, from 2 to 3. + // This conditional, and the pre-2022 policy logic can be removed after June + // 1, 2023, since all publicly trusted certificates issued prior to the + // policy change date will have expired by then. const base::Time kPolicyUpdateDate = base::Time::UnixEpoch() + base::Seconds(1649980800); - bool use_2022_policy = - base::FeatureList::IsEnabled( - features::kCertificateTransparency2022PolicyAllCerts) || - (base::FeatureList::IsEnabled( - features::kCertificateTransparency2022Policy) && - issuance_date >= kPolicyUpdateDate); + bool use_2022_policy = issuance_date >= kPolicyUpdateDate; bool has_valid_google_sct = false; bool has_valid_nongoogle_sct = false; @@ -374,18 +371,7 @@ // AND there is at least one embedded SCT from a non-Google Log once or // currently qualified; // ... - // - // Note: This policy language is only enforced after the below issuance - // date, as that's when the diversity policy first came into effect for - // SCTs embedded in certificates. - // The date when diverse SCTs requirement is effective from. - // 2015-07-01 00:00:00 UTC. - // TODO(carlosil): There are no more valid certificates from before this - // date, so this date and the associated logic should be cleaned up. - const base::Time kDiverseSCTRequirementStartDate = - base::Time::UnixEpoch() + base::Seconds(1435708800); - if (issuance_date >= kDiverseSCTRequirementStartDate && - !(has_embedded_google_sct && has_embedded_nongoogle_sct)) { + if (!(has_embedded_google_sct && has_embedded_nongoogle_sct)) { // Note: This also covers the case for non-embedded SCTs, as it's only // possible to reach here if both sets are not diverse enough. return CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS;
diff --git a/components/certificate_transparency/chrome_ct_policy_enforcer_unittest.cc b/components/certificate_transparency/chrome_ct_policy_enforcer_unittest.cc index eded3675..056ceee 100644 --- a/components/certificate_transparency/chrome_ct_policy_enforcer_unittest.cc +++ b/components/certificate_transparency/chrome_ct_policy_enforcer_unittest.cc
@@ -14,7 +14,6 @@ #include "base/test/simple_test_clock.h" #include "base/time/time.h" #include "base/version.h" -#include "components/certificate_transparency/ct_features.h" #include "components/certificate_transparency/ct_known_logs.h" #include "crypto/rsa_private_key.h" #include "crypto/sha2.h" @@ -70,7 +69,7 @@ SignedCertificateTimestamp::Origin desired_origin, size_t num_scts, const std::vector<std::string>& desired_log_keys, - bool timestamp_past_enforcement_date, + bool timestamp_past_2022_policy_date, SCTList* verified_scts) { for (size_t i = 0; i < num_scts; ++i) { scoped_refptr<SignedCertificateTimestamp> sct( @@ -81,11 +80,11 @@ else sct->log_id = std::string(crypto::kSHA256Length, static_cast<char>(i)); - if (timestamp_past_enforcement_date) { - EXPECT_TRUE(base::Time::FromUTCExploded({2015, 8, 0, 15, 0, 0, 0, 0}, + if (timestamp_past_2022_policy_date) { + EXPECT_TRUE(base::Time::FromUTCExploded({2022, 4, 0, 15, 0, 0, 0, 0}, &sct->timestamp)); } else { - EXPECT_TRUE(base::Time::FromUTCExploded({2015, 6, 0, 15, 0, 0, 0, 0}, + EXPECT_TRUE(base::Time::FromUTCExploded({2022, 4, 0, 14, 0, 0, 0, 0}, &sct->timestamp)); } @@ -95,6 +94,7 @@ void AddDisqualifiedLogSCT(SignedCertificateTimestamp::Origin desired_origin, bool timestamp_after_disqualification_date, + bool timestamp_past_2022_policy_date, SCTList* verified_scts) { static const char kTestRetiredLogID[] = "\xcd\xb5\x17\x9b\x7f\xc1\xc0\x46\xfe\xea\x31\x13\x6a\x3f\x8f\x00\x2e" @@ -102,8 +102,14 @@ static_assert(std::size(kTestRetiredLogID) - 1 == crypto::kSHA256Length, "Incorrect log ID length."); base::Time retirement_time; - ASSERT_TRUE(base::Time::FromUTCExploded({2016, 4, 0, 15, 0, 0, 0, 0}, - &retirement_time)); + if (timestamp_past_2022_policy_date) { + ASSERT_TRUE(base::Time::FromUTCExploded({2022, 4, 0, 16, 0, 0, 0, 0}, + &retirement_time)); + } else { + ASSERT_TRUE(base::Time::FromUTCExploded({2022, 4, 0, 14, 12, 0, 0, 0}, + &retirement_time)); + } + policy_enforcer_->SetDisqualifiedLogForTesting( std::make_pair(std::string(kTestRetiredLogID, 32), retirement_time)); @@ -112,11 +118,9 @@ sct->origin = desired_origin; sct->log_id = std::string(kTestRetiredLogID, crypto::kSHA256Length); if (timestamp_after_disqualification_date) { - EXPECT_TRUE(base::Time::FromUTCExploded({2016, 4, 0, 16, 0, 0, 0, 0}, - &sct->timestamp)); + sct->timestamp = retirement_time + base::Hours(1); } else { - EXPECT_TRUE(base::Time::FromUTCExploded({2016, 4, 0, 1, 0, 0, 0, 0}, - &sct->timestamp)); + sct->timestamp = retirement_time - base::Hours(1); } verified_scts->push_back(sct); @@ -125,11 +129,12 @@ void FillListWithSCTsOfOrigin( SignedCertificateTimestamp::Origin desired_origin, size_t num_scts, + bool timestamp_past_2022_policy_date, SCTList* verified_scts) { std::vector<std::string> desired_log_ids; desired_log_ids.push_back(google_log_id_); - FillListWithSCTsOfOrigin(desired_origin, num_scts, desired_log_ids, true, - verified_scts); + FillListWithSCTsOfOrigin(desired_origin, num_scts, desired_log_ids, + timestamp_past_2022_policy_date, verified_scts); } base::Time CreateTime(const base::Time::Exploded& exploded) { @@ -159,28 +164,13 @@ base::test::ScopedFeatureList scoped_feature_list_; }; -// Subclass of ChromeCTPolicyEnforcerTest that tests using only the pre-2022 -// policy. -class ChromeCTPolicyEnforcerTestPre2022Policy - : public ChromeCTPolicyEnforcerTest { - public: - void SetUp() override { - scoped_feature_list_.InitWithFeatures( - /*enabled_features*/ {}, - /*disabled_features*/ { - features::kCertificateTransparency2022Policy, - features::kCertificateTransparency2022PolicyAllCerts}); - ChromeCTPolicyEnforcerTest::SetUp(); - } -}; - -TEST_F(ChromeCTPolicyEnforcerTestPre2022Policy, +TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllGoogle) { SCTList scts; std::vector<std::string> desired_log_ids(2, google_log_id_); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - desired_log_ids.size(), desired_log_ids, true, + desired_log_ids.size(), desired_log_ids, false, &scts); EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, @@ -188,13 +178,13 @@ NetLogWithSource())); } -TEST_F(ChromeCTPolicyEnforcerTestPre2022Policy, +TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllNonGoogle) { SCTList scts; std::vector<std::string> desired_log_ids(2, non_google_log_id_); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - desired_log_ids.size(), desired_log_ids, true, + desired_log_ids.size(), desired_log_ids, false, &scts); EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, @@ -202,20 +192,7 @@ NetLogWithSource())); } -TEST_F(ChromeCTPolicyEnforcerTestPre2022Policy, - ConformsToCTPolicyIfSCTBeforeEnforcementDate) { - SCTList scts; - // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. - // All 5 SCTs will be from non-Google logs. - FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5, - std::vector<std::string>(), false, &scts); - - EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, - policy_enforcer_->CheckCompliance(chain_.get(), scts, - NetLogWithSource())); -} - -TEST_F(ChromeCTPolicyEnforcerTestPre2022Policy, +TEST_F(ChromeCTPolicyEnforcerTest, ConformsToPolicyExactNumberOfSCTsForValidityPeriod) { std::unique_ptr<crypto::RSAPrivateKey> private_key( crypto::RSAPrivateKey::Create(1024)); @@ -284,18 +261,31 @@ for (size_t j = 0; j < required_scts - 1; ++j) { SCTList scts; - FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, j, - std::vector<std::string>(), false, &scts); - EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - policy_enforcer_->CheckCompliance(cert.get(), scts, - NetLogWithSource())) + std::vector<std::string> desired_logs; + desired_logs.push_back(google_log_id_); + if (j > 0) { + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 1, + desired_logs, false, &scts); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, + j - 1, std::vector<std::string>(), false, + &scts); + } + CTPolicyCompliance expected_failure = + j == 1 ? CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS + : CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS; + EXPECT_EQ(expected_failure, policy_enforcer_->CheckCompliance( + cert.get(), scts, NetLogWithSource())) << " for: " << (end - start).InDays() << " and " << required_scts << " scts=" << scts.size() << " j=" << j; } SCTList scts; + std::vector<std::string> desired_logs; + desired_logs.push_back(google_log_id_); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 1, + desired_logs, false, &scts); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, - required_scts, std::vector<std::string>(), false, - &scts); + required_scts - 1, std::vector<std::string>(), + false, &scts); EXPECT_EQ( CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, policy_enforcer_->CheckCompliance(cert.get(), scts, NetLogWithSource())) @@ -304,7 +294,7 @@ } } -TEST_F(ChromeCTPolicyEnforcerTestPre2022Policy, +TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughUniqueEmbeddedLogs) { SCTList scts; std::vector<std::string> desired_logs; @@ -313,21 +303,21 @@ desired_logs.clear(); desired_logs.push_back(google_log_id_); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, - desired_logs.size(), desired_logs, true, &scts); + desired_logs.size(), desired_logs, false, &scts); // Two distinct non-Google logs. desired_logs.clear(); desired_logs.emplace_back(crypto::kSHA256Length, 'A'); desired_logs.emplace_back(crypto::kSHA256Length, 'B'); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, - desired_logs.size(), desired_logs, true, &scts); + desired_logs.size(), desired_logs, false, &scts); // Two unique SCTs from the same non-Google log. desired_logs.clear(); desired_logs.emplace_back(crypto::kSHA256Length, 'C'); desired_logs.emplace_back(crypto::kSHA256Length, 'C'); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, - desired_logs.size(), desired_logs, true, &scts); + desired_logs.size(), desired_logs, false, &scts); // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. // However, there are only 4 SCTs are from distinct logs. @@ -336,8 +326,7 @@ NetLogWithSource())); } -TEST_F(ChromeCTPolicyEnforcerTestPre2022Policy, - DoesNotConformToCTPolicyNotEnoughFreshSCTs) { +TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughFreshSCTs) { SCTList scts; // The results should be the same before and after disqualification, @@ -346,9 +335,9 @@ // SCT from before disqualification. scts.clear(); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - 1, &scts); + 1, false, &scts); AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - false, &scts); + false, false, &scts); EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); @@ -356,9 +345,9 @@ // SCT from after disqualification. scts.clear(); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - 1, &scts); + 1, false, &scts); AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - true, &scts); + true, false, &scts); EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); @@ -366,8 +355,9 @@ // Embedded SCT from before disqualification. scts.clear(); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - 1, &scts); - AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, false, &scts); + 1, false, &scts); + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, false, false, + &scts); EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); @@ -375,8 +365,9 @@ // Embedded SCT from after disqualification. scts.clear(); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - 1, &scts); - AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true, &scts); + 1, false, &scts); + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true, false, + &scts); EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); @@ -386,28 +377,13 @@ // policy and the 2022 policy. class ChromeCTPolicyEnforcerTestBothPolicies : public ChromeCTPolicyEnforcerTest, - public ::testing::WithParamInterface<bool> { - public: - void SetUp() override { - if (GetParam()) { - scoped_feature_list_.InitAndEnableFeature( - features::kCertificateTransparency2022PolicyAllCerts); - } else { - scoped_feature_list_.InitWithFeatures( - /*enabled_features*/ {}, - /*disabled_features*/ { - features::kCertificateTransparency2022Policy, - features::kCertificateTransparency2022PolicyAllCerts}); - } - ChromeCTPolicyEnforcerTest::SetUp(); - } -}; + public ::testing::WithParamInterface<bool> {}; TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, ConformsToCTPolicyWithNonEmbeddedSCTs) { SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - 2, &scts); + 2, GetParam(), &scts); if (GetParam()) { std::map<std::string, OperatorHistoryEntry> operator_history; FillOperatorHistoryWithDiverseOperators(scts, &operator_history); @@ -422,7 +398,7 @@ TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, EnforcementDisabledByBinaryAge) { SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - 2, &scts); + 2, GetParam(), &scts); if (GetParam()) { std::map<std::string, OperatorHistoryEntry> operator_history; FillOperatorHistoryWithDiverseOperators(scts, &operator_history); @@ -444,7 +420,8 @@ ConformsToCTPolicyWithEmbeddedSCTs) { // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. SCTList scts; - FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5, &scts); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5, + GetParam(), &scts); if (GetParam()) { std::map<std::string, OperatorHistoryEntry> operator_history; FillOperatorHistoryWithDiverseOperators(scts, &operator_history); @@ -465,13 +442,15 @@ desired_logs.clear(); desired_logs.push_back(google_log_id_); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, - desired_logs.size(), desired_logs, true, &scts); + desired_logs.size(), desired_logs, GetParam(), + &scts); // One non-Google log, delivered via TLS. desired_logs.clear(); desired_logs.push_back(non_google_log_id_); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - desired_logs.size(), desired_logs, true, &scts); + desired_logs.size(), desired_logs, GetParam(), + &scts); if (GetParam()) { std::map<std::string, OperatorHistoryEntry> operator_history; FillOperatorHistoryWithDiverseOperators(scts, &operator_history); @@ -492,13 +471,15 @@ desired_logs.clear(); desired_logs.push_back(google_log_id_); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, - desired_logs.size(), desired_logs, true, &scts); + desired_logs.size(), desired_logs, GetParam(), + &scts); // One non-Google log, delivered via OCSP. desired_logs.clear(); desired_logs.push_back(non_google_log_id_); FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, - desired_logs.size(), desired_logs, true, &scts); + desired_logs.size(), desired_logs, GetParam(), + &scts); if (GetParam()) { std::map<std::string, OperatorHistoryEntry> operator_history; @@ -515,7 +496,8 @@ DoesNotConformToCTPolicyNotEnoughSCTs) { // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. SCTList scts; - FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 2, &scts); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 2, + GetParam(), &scts); if (GetParam()) { std::map<std::string, OperatorHistoryEntry> operator_history; FillOperatorHistoryWithDiverseOperators(scts, &operator_history); @@ -530,8 +512,15 @@ TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, ConformsWithDisqualifiedLogBeforeDisqualificationDate) { SCTList scts; - FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 4, &scts); - AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, false, &scts); + std::vector<std::string> desired_log_ids; + desired_log_ids.push_back(google_log_id_); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 1, + desired_log_ids, GetParam(), &scts); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, + GetParam() ? 1 : 3, std::vector<std::string>(), + GetParam(), &scts); + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, false, + GetParam(), &scts); if (GetParam()) { std::map<std::string, OperatorHistoryEntry> operator_history; FillOperatorHistoryWithDiverseOperators(scts, &operator_history); @@ -550,8 +539,9 @@ // Add required - 1 valid SCTs (with the old policy 5 are required, with the // new policy 3). FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, - GetParam() ? 2 : 4, &scts); - AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true, &scts); + GetParam() ? 2 : 4, GetParam(), &scts); + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true, + GetParam(), &scts); if (GetParam()) { std::map<std::string, OperatorHistoryEntry> operator_history; FillOperatorHistoryWithDiverseOperators(scts, &operator_history); @@ -567,11 +557,12 @@ TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, DoesNotConformWithIssuanceDateAfterDisqualificationDate) { SCTList scts; - AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true, &scts); + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true, + GetParam(), &scts); // Add required - 1 valid SCTs (with the old policy 5 are required, with the // new policy 3). FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, - GetParam() ? 2 : 4, &scts); + GetParam() ? 2 : 4, GetParam(), &scts); // Make sure all SCTs are after the disqualification date. for (size_t i = 1; i < scts.size(); ++i) scts[i]->timestamp = scts[0]->timestamp; @@ -591,7 +582,7 @@ TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, UpdateCTLogList) { SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - 2, &scts); + 2, GetParam(), &scts); std::vector<std::pair<std::string, base::Time>> disqualified_logs; std::vector<std::string> operated_by_google_logs; @@ -631,7 +622,7 @@ TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, TimestampUpdates) { SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - 1, &scts); + 1, GetParam(), &scts); // Clear the log list and set the last updated time to more than 10 weeks ago. std::vector<std::pair<std::string, base::Time>> disqualified_logs; @@ -715,7 +706,8 @@ TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, ConformsWithCTPolicyFutureRetirementDateLogs) { SCTList scts; - FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5, &scts); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5, + GetParam(), &scts); std::vector<std::pair<std::string, base::Time>> disqualified_logs; std::vector<std::string> operated_by_google_logs = {google_log_id_}; @@ -747,7 +739,8 @@ TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, DoesNotConformWithCTPolicyPastRetirementDateLogs) { SCTList scts; - FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5, &scts); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5, + GetParam(), &scts); std::vector<std::pair<std::string, base::Time>> disqualified_logs; std::vector<std::string> operated_by_google_logs = {google_log_id_}; @@ -781,17 +774,7 @@ ChromeCTPolicyEnforcerTestBothPolicies, testing::Bool()); -class ChromeCTPolicyEnforcerTest2022Policy : public ChromeCTPolicyEnforcerTest { - public: - void SetUp() override { - scoped_feature_list_.InitAndEnableFeature( - features::kCertificateTransparency2022Policy); - ChromeCTPolicyEnforcerTest::SetUp(); - } -}; - -TEST_F(ChromeCTPolicyEnforcerTest2022Policy, - 2022PolicyNotInEffectBeforeTargetDate) { +TEST_F(ChromeCTPolicyEnforcerTest, 2022PolicyNotInEffectBeforeTargetDate) { // Old policy should enforce one Google log requirement. SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, @@ -810,8 +793,7 @@ NetLogWithSource())); } -TEST_F(ChromeCTPolicyEnforcerTest2022Policy, - 2022PolicyInEffectAfterTargetDate) { +TEST_F(ChromeCTPolicyEnforcerTest, 2022PolicyInEffectAfterTargetDate) { // New policy should allow SCTs from all non-Google operators to comply as // long as diversity requirement is fulfilled. SCTList scts; @@ -831,17 +813,7 @@ NetLogWithSource())); } -class ChromeCTPolicyEnforcerTest2022PolicyAllCerts - : public ChromeCTPolicyEnforcerTest { - public: - void SetUp() override { - scoped_feature_list_.InitAndEnableFeature( - features::kCertificateTransparency2022PolicyAllCerts); - ChromeCTPolicyEnforcerTest::SetUp(); - } -}; - -TEST_F(ChromeCTPolicyEnforcerTest2022PolicyAllCerts, UpdatedSCTRequirements) { +TEST_F(ChromeCTPolicyEnforcerTest, UpdatedSCTRequirements) { std::unique_ptr<crypto::RSAPrivateKey> private_key( crypto::RSAPrivateKey::Create(1024)); ASSERT_TRUE(private_key); @@ -896,7 +868,7 @@ for (size_t j = 0; j <= scts_required; ++j) { SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, j, - std::vector<std::string>(), false, &scts); + std::vector<std::string>(), true, &scts); // Add different operators to the logs so the SCTs comply with operator // diversity. FillOperatorHistoryWithDiverseOperators(scts, &operator_history); @@ -921,7 +893,7 @@ } } -TEST_F(ChromeCTPolicyEnforcerTest2022PolicyAllCerts, +TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformToCTPolicyAllLogsSameOperator) { SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, @@ -939,8 +911,7 @@ NetLogWithSource())); } -TEST_F(ChromeCTPolicyEnforcerTest2022PolicyAllCerts, - ConformsToCTPolicyDifferentOperators) { +TEST_F(ChromeCTPolicyEnforcerTest, ConformsToCTPolicyDifferentOperators) { SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 2, std::vector<std::string>(), true, &scts); @@ -953,8 +924,7 @@ NetLogWithSource())); } -TEST_F(ChromeCTPolicyEnforcerTest2022PolicyAllCerts, - ConformsToPolicyDueToOperatorSwitch) { +TEST_F(ChromeCTPolicyEnforcerTest, ConformsToPolicyDueToOperatorSwitch) { SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 2, std::vector<std::string>(), true, &scts); @@ -976,8 +946,7 @@ NetLogWithSource())); } -TEST_F(ChromeCTPolicyEnforcerTest2022PolicyAllCerts, - DoesNotConformToPolicyDueToOperatorSwitch) { +TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformToPolicyDueToOperatorSwitch) { SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 2, std::vector<std::string>(), true, &scts); @@ -996,7 +965,7 @@ NetLogWithSource())); } -TEST_F(ChromeCTPolicyEnforcerTest2022PolicyAllCerts, MultipleOperatorSwitches) { +TEST_F(ChromeCTPolicyEnforcerTest, MultipleOperatorSwitches) { SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 2, std::vector<std::string>(), true, &scts); @@ -1016,8 +985,7 @@ NetLogWithSource())); } -TEST_F(ChromeCTPolicyEnforcerTest2022PolicyAllCerts, - MultipleOperatorSwitchesBeforeSCTTimestamp) { +TEST_F(ChromeCTPolicyEnforcerTest, MultipleOperatorSwitchesBeforeSCTTimestamp) { SCTList scts; FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 2, std::vector<std::string>(), true, &scts);
diff --git a/components/certificate_transparency/ct_features.cc b/components/certificate_transparency/ct_features.cc index fea5eea..bb5133d7 100644 --- a/components/certificate_transparency/ct_features.cc +++ b/components/certificate_transparency/ct_features.cc
@@ -13,12 +13,5 @@ "CertificateTransparencyComponentUpdater", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kCertificateTransparency2022Policy{ - "CertificateTransparency2022Policy", base::FEATURE_ENABLED_BY_DEFAULT}; - -const base::Feature kCertificateTransparency2022PolicyAllCerts{ - "CertificateTransparency2022PolicyAllCerts", - base::FEATURE_DISABLED_BY_DEFAULT}; - } // namespace features } // namespace certificate_transparency
diff --git a/components/certificate_transparency/ct_features.h b/components/certificate_transparency/ct_features.h index 1738fcd..5b20965 100644 --- a/components/certificate_transparency/ct_features.h +++ b/components/certificate_transparency/ct_features.h
@@ -14,21 +14,6 @@ COMPONENT_EXPORT(CERTIFICATE_TRANSPARENCY) extern const base::Feature kCertificateTransparencyComponentUpdater; -// If enabled, the 2022 CT policy which removes the one Google log -// requirement, introduces log operator diversity requirements, and increases -// the number of embedded SCTs required for certificates with a lifetime over -// 180 days (from 2 to 3) will be used for any certificate issued after February -// 1, 2022. -COMPONENT_EXPORT(CERTIFICATE_TRANSPARENCY) -extern const base::Feature kCertificateTransparency2022Policy; - -// If enabled, the 2022 CT policy which removes the one Google log -// requirement, introduces log operator diversity requirements, and increases -// the number of embedded SCTs required for certificates with a lifetime over -// 180 days (from 2 to 3) will be used for all certificates. -COMPONENT_EXPORT(CERTIFICATE_TRANSPARENCY) -extern const base::Feature kCertificateTransparency2022PolicyAllCerts; - } // namespace features } // namespace certificate_transparency
diff --git a/components/commerce_strings.grdp b/components/commerce_strings.grdp index 2528c78..0c9847f 100644 --- a/components/commerce_strings.grdp +++ b/components/commerce_strings.grdp
@@ -23,7 +23,11 @@ <message name="IDS_DISCOUNT_CONTEXTUAL_CONSENT_ACCEPTED_CONFIRMATION_DONE" desc="The text shown on the consent confirmation bubble bubble. User can click this button to close the bubble."> Done </message> - <message name="IDS_NATIVE_NTP_CART_DISCOUNT_CONSENT_TITLE" translateable="false" desc="The title shown on the native consent dialog for getting discount. Note: This is intentionally left blank. No translation is required."></message> - <message name="IDS_NATIVE_NTP_CART_DISCOUNT_CONSENT_BODY" translateable="false" desc="The actual consent descrition that shows in the native consent dialog. Note: This is intentionally left blank. No translation is required."></message> + <message name="IDS_NATIVE_NTP_CART_DISCOUNT_CONSENT_TITLE" translateable="false" desc="The title shown on the native consent dialog for getting discount. Note: This is intentionally left blank. No translation is required."> + Get discounts on your carts & when you shop online + </message> + <message name="IDS_NATIVE_NTP_CART_DISCOUNT_CONSENT_BODY" translateable="false" desc="The actual consent descrition that shows in the native consent dialog. Note: This is intentionally left blank. No translation is required."> + Let Google find personalized discounts on your carts and on online stores you visit. When available, discounts will automatically show up on your carts and on sites. + </message> </if> </grit-part> \ No newline at end of file
diff --git a/components/drive/OWNERS b/components/drive/OWNERS index 51c60c1..4ad89d4 100644 --- a/components/drive/OWNERS +++ b/components/drive/OWNERS
@@ -1,7 +1,5 @@ -hashimoto@chromium.org -hidehiko@chromium.org -hirono@chromium.org -kinaba@chromium.org -slangley@chromium.org -yoshiki@chromium.org +# Primary +file://chrome/browser/sync_file_system/OWNERS + +# Secondary file://ash/projector/OWNERS
diff --git a/components/exo/wayland/clients/client_base.cc b/components/exo/wayland/clients/client_base.cc index 7b97fe0..5465a6a 100644 --- a/components/exo/wayland/clients/client_base.cc +++ b/components/exo/wayland/clients/client_base.cc
@@ -155,7 +155,7 @@ wl_registry_bind(registry, id, &wp_presentation_interface, 1))); } else if (strcmp(interface, "zaura_shell") == 0) { globals->aura_shell.reset(static_cast<zaura_shell*>( - wl_registry_bind(registry, id, &zaura_shell_interface, 14))); + wl_registry_bind(registry, id, &zaura_shell_interface, 32))); } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) { globals->linux_dmabuf.reset(static_cast<zwp_linux_dmabuf_v1*>( wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, 2))); @@ -923,6 +923,14 @@ uint32_t modifier_hi, uint32_t modifier_lo) {} +//////////////////////////////////////////////////////////////////////////////// +// zaura_output_listener + +void ClientBase::HandleInsets(const gfx::Insets& insets) {} + +//////////////////////////////////////////////////////////////////////////////// +// helper functions + std::unique_ptr<ClientBase::Buffer> ClientBase::CreateBuffer( const gfx::Size& size, int32_t drm_format, @@ -1254,7 +1262,13 @@ [](void* data, struct zaura_shell* zaura_shell, uint32_t layout_mode) {}, [](void* data, struct zaura_shell* zaura_shell, uint32_t id) { CastToClientBase(data)->bug_fix_ids_.insert(id); - }}; + }, + [](void* data, struct zaura_shell* zaura_shell, + struct wl_array* desk_names) {}, + [](void* data, struct zaura_shell* zaura_shell, + int32_t active_desk_index) {}, + [](void* data, struct zaura_shell* zaura_shell, + struct wl_surface* gained_active, struct wl_surface* lost_active) {}}; zaura_shell_add_listener(globals_.aura_shell.get(), &kAuraShellListener, this); @@ -1266,6 +1280,23 @@ } zaura_surface_set_frame(aura_surface.get(), ZAURA_SURFACE_FRAME_TYPE_NORMAL); + + static zaura_output_listener kAuraOutputListener = { + [](void* data, struct zaura_output* zaura_output, uint32_t flags, + uint32_t scale) {}, + [](void* data, struct zaura_output* zaura_output, uint32_t connection) {}, + [](void* data, struct zaura_output* zaura_output, uint32_t scale) {}, + [](void* data, struct zaura_output* zaura_output, int32_t top, + int32_t left, int32_t bottom, int32_t right) { + CastToClientBase(data)->HandleInsets( + gfx::Insets::TLBR(top, left, bottom, right)); + }, + }; + + std::unique_ptr<zaura_output> aura_output(zaura_shell_get_aura_output( + globals_.aura_shell.get(), globals_.output.get())); + zaura_output_add_listener(aura_output.get(), &kAuraOutputListener, this); + globals_.aura_output = std::move(aura_output); } void ClientBase::SetupPointerStylus() {
diff --git a/components/exo/wayland/clients/client_base.h b/components/exo/wayland/clients/client_base.h index b4e47bd..19619be 100644 --- a/components/exo/wayland/clients/client_base.h +++ b/components/exo/wayland/clients/client_base.h
@@ -15,6 +15,7 @@ #include "linux-dmabuf-unstable-v1-client-protocol.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkRefCnt.h" +#include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/size.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_surface.h" @@ -85,6 +86,7 @@ std::unique_ptr<wl_subcompositor> subcompositor; std::unique_ptr<wl_touch> touch; std::unique_ptr<zaura_shell> aura_shell; + std::unique_ptr<zaura_output> aura_output; std::unique_ptr<zxdg_shell_v6> xdg_shell_v6; std::unique_ptr<xdg_wm_base> xdg_wm_base; std::unique_ptr<zwp_fullscreen_shell_v1> fullscreen_shell; @@ -204,6 +206,9 @@ uint32_t modifier_hi, uint32_t modifier_lo); + // zaura_output_listener + virtual void HandleInsets(const gfx::Insets& insets); + gfx::Size size_ = gfx::Size(256, 256); int scale_ = 1; int transform_ = WL_OUTPUT_TRANSFORM_NORMAL;
diff --git a/components/exo/wayland/clients/info.cc b/components/exo/wayland/clients/info.cc index 1e97fac3..baf36fd 100644 --- a/components/exo/wayland/clients/info.cc +++ b/components/exo/wayland/clients/info.cc
@@ -43,6 +43,9 @@ }; // |next_scales| are swapped with |scales| after receiving output done event. std::vector<Scale> scales, next_scales; + struct { + int32_t top, left, bottom, right; + } insets; std::unique_ptr<wl_output> output; std::unique_ptr<zaura_output> aura_output; }; @@ -155,6 +158,17 @@ info->device_scale_factor = device_scale_factor; } +void AuraOutputInsets(void* data, + zaura_output* output, + int32_t top, + int32_t left, + int32_t bottom, + int32_t right) { + Info* info = static_cast<Info*>(data); + + info->insets = {top, left, bottom, right}; +} + std::string OutputSubpixelToString(int32_t subpixel) { switch (subpixel) { case WL_OUTPUT_SUBPIXEL_UNKNOWN: @@ -293,7 +307,8 @@ OutputScale}; zaura_output_listener aura_output_listener = { - AuraOutputScale, AuraOutputConnection, AuraOutputDeviceScaleFactor}; + AuraOutputScale, AuraOutputConnection, AuraOutputDeviceScaleFactor, + AuraOutputInsets}; for (auto& info : globals.outputs) { wl_output_add_listener(info.output.get(), &output_listener, &info); if (globals.aura_shell) { @@ -349,6 +364,12 @@ << AuraOutputScaleFlagsToString(scale.flags) << std::endl; } } + std::cout << " insets:" << std::endl + << " top: " << info.insets.top << std::endl + << " left: " << info.insets.left << std::endl + << " bottom: " << info.insets.bottom << std::endl + << " right: " << info.insets.right << std::endl + << std::endl; } return 0;
diff --git a/components/exo/wayland/protocol/aura-shell.xml b/components/exo/wayland/protocol/aura-shell.xml index 8a4bffb..b0fd1b5 100644 --- a/components/exo/wayland/protocol/aura-shell.xml +++ b/components/exo/wayland/protocol/aura-shell.xml
@@ -24,7 +24,7 @@ DEALINGS IN THE SOFTWARE. </copyright> - <interface name="zaura_shell" version="31"> + <interface name="zaura_shell" version="32"> <description summary="aura_shell"> The global interface exposing aura shell capabilities is used to instantiate an interface extension for a wl_surface object. @@ -512,7 +512,7 @@ </event> </interface> - <interface name="zaura_output" version="6"> + <interface name="zaura_output" version="32"> <description summary="aura shell interface to a wl_output"> An additional interface to a wl_output object, which allows the client to access aura shell specific functionality for output. @@ -614,7 +614,23 @@ </description> <arg name="scale" type="uint" enum="scale_factor" summary="output device scale factor"/> </event> - </interface> + + <!-- Version 32 additions --> + + <event name="insets" since="32"> + <description summary="advertise the insets for the output"> + This event describes the insets for the output in logical screen + coordinates, from which the work area can be calculated. + + This event is sent before wl_output.done, after which the client would + apply the change. + </description> + <arg name="top" type="int"/> + <arg name="left" type="int"/> + <arg name="bottom" type="int"/> + <arg name="right" type="int"/> + </event> + </interface> <interface name="zaura_toplevel" version="31"> <description summary="aura shell interface to the toplevel shell">
diff --git a/components/exo/wayland/zaura_shell.cc b/components/exo/wayland/zaura_shell.cc index ea481e07..468c7eefd 100644 --- a/components/exo/wayland/zaura_shell.cc +++ b/components/exo/wayland/zaura_shell.cc
@@ -774,90 +774,88 @@ #endif // BUILDFLAG(IS_CHROMEOS_ASH) -namespace { - //////////////////////////////////////////////////////////////////////////////// // aura_output_interface: -class AuraOutput : public WaylandDisplayObserver { - public: - explicit AuraOutput(wl_resource* resource) : resource_(resource) {} +AuraOutput::AuraOutput(wl_resource* resource) : resource_(resource) {} - AuraOutput(const AuraOutput&) = delete; - AuraOutput& operator=(const AuraOutput&) = delete; +AuraOutput::~AuraOutput() = default; - // Overridden from WaylandDisplayObserver: - bool SendDisplayMetrics(const display::Display& display, - uint32_t changed_metrics) override { - if (!(changed_metrics & - (display::DisplayObserver::DISPLAY_METRIC_BOUNDS | - display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR | - display::DisplayObserver::DISPLAY_METRIC_ROTATION))) { - return false; - } - - const WMHelper* wm_helper = WMHelper::GetInstance(); - const display::ManagedDisplayInfo& display_info = - wm_helper->GetDisplayInfo(display.id()); - - if (wl_resource_get_version(resource_) >= - ZAURA_OUTPUT_SCALE_SINCE_VERSION) { - display::ManagedDisplayMode active_mode; - bool rv = - wm_helper->GetActiveModeForDisplayId(display.id(), &active_mode); - DCHECK(rv); - const int32_t current_output_scale = - std::round(display_info.zoom_factor() * 1000.f); - std::vector<float> zoom_factors = - display::GetDisplayZoomFactors(active_mode); - - // Ensure that the current zoom factor is a part of the list. - auto it = std::find_if( - zoom_factors.begin(), zoom_factors.end(), - [&display_info](float zoom_factor) -> bool { - return std::abs(display_info.zoom_factor() - zoom_factor) <= - std::numeric_limits<float>::epsilon(); - }); - if (it == zoom_factors.end()) - zoom_factors.push_back(display_info.zoom_factor()); - - for (float zoom_factor : zoom_factors) { - int32_t output_scale = std::round(zoom_factor * 1000.f); - uint32_t flags = 0; - if (output_scale == 1000) - flags |= ZAURA_OUTPUT_SCALE_PROPERTY_PREFERRED; - if (current_output_scale == output_scale) - flags |= ZAURA_OUTPUT_SCALE_PROPERTY_CURRENT; - - // TODO(malaykeshav): This can be removed in the future when client - // has been updated. - if (wl_resource_get_version(resource_) < 6) - output_scale = std::round(1000.f / zoom_factor); - - zaura_output_send_scale(resource_, flags, output_scale); - } - } - - if (wl_resource_get_version(resource_) >= - ZAURA_OUTPUT_CONNECTION_SINCE_VERSION) { - zaura_output_send_connection(resource_, - display.IsInternal() - ? ZAURA_OUTPUT_CONNECTION_TYPE_INTERNAL - : ZAURA_OUTPUT_CONNECTION_TYPE_UNKNOWN); - } - - if (wl_resource_get_version(resource_) >= - ZAURA_OUTPUT_DEVICE_SCALE_FACTOR_SINCE_VERSION) { - zaura_output_send_device_scale_factor( - resource_, display_info.device_scale_factor() * 1000); - } - - return true; +bool AuraOutput::SendDisplayMetrics(const display::Display& display, + uint32_t changed_metrics) { + if (!(changed_metrics & + (display::DisplayObserver::DISPLAY_METRIC_BOUNDS | + display::DisplayObserver::DISPLAY_METRIC_WORK_AREA | + display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR | + display::DisplayObserver::DISPLAY_METRIC_ROTATION))) { + return false; } - private: - wl_resource* const resource_; -}; + const WMHelper* wm_helper = WMHelper::GetInstance(); + const display::ManagedDisplayInfo& display_info = + wm_helper->GetDisplayInfo(display.id()); + + if (wl_resource_get_version(resource_) >= ZAURA_OUTPUT_SCALE_SINCE_VERSION) { + display::ManagedDisplayMode active_mode; + bool rv = wm_helper->GetActiveModeForDisplayId(display.id(), &active_mode); + DCHECK(rv); + const int32_t current_output_scale = + std::round(display_info.zoom_factor() * 1000.f); + std::vector<float> zoom_factors = + display::GetDisplayZoomFactors(active_mode); + + // Ensure that the current zoom factor is a part of the list. + auto it = std::find_if( + zoom_factors.begin(), zoom_factors.end(), + [&display_info](float zoom_factor) -> bool { + return std::abs(display_info.zoom_factor() - zoom_factor) <= + std::numeric_limits<float>::epsilon(); + }); + if (it == zoom_factors.end()) + zoom_factors.push_back(display_info.zoom_factor()); + + for (float zoom_factor : zoom_factors) { + int32_t output_scale = std::round(zoom_factor * 1000.f); + uint32_t flags = 0; + if (output_scale == 1000) + flags |= ZAURA_OUTPUT_SCALE_PROPERTY_PREFERRED; + if (current_output_scale == output_scale) + flags |= ZAURA_OUTPUT_SCALE_PROPERTY_CURRENT; + + // TODO(malaykeshav): This can be removed in the future when client + // has been updated. + if (wl_resource_get_version(resource_) < 6) + output_scale = std::round(1000.f / zoom_factor); + + zaura_output_send_scale(resource_, flags, output_scale); + } + } + + if (wl_resource_get_version(resource_) >= + ZAURA_OUTPUT_CONNECTION_SINCE_VERSION) { + zaura_output_send_connection( + resource_, display.IsInternal() ? ZAURA_OUTPUT_CONNECTION_TYPE_INTERNAL + : ZAURA_OUTPUT_CONNECTION_TYPE_UNKNOWN); + } + + if (wl_resource_get_version(resource_) >= + ZAURA_OUTPUT_DEVICE_SCALE_FACTOR_SINCE_VERSION) { + zaura_output_send_device_scale_factor( + resource_, display_info.device_scale_factor() * 1000); + } + + if (wl_resource_get_version(resource_) >= ZAURA_OUTPUT_INSETS_SINCE_VERSION) + SendInsets(display.bounds().InsetsFrom(display.work_area())); + + return true; +} + +void AuraOutput::SendInsets(const gfx::Insets& insets) { + zaura_output_send_insets(resource_, insets.top(), insets.left(), + insets.bottom(), insets.right()); +} + +namespace { //////////////////////////////////////////////////////////////////////////////// // aura_shell_interface:
diff --git a/components/exo/wayland/zaura_shell.h b/components/exo/wayland/zaura_shell.h index dda9f92..ae7bc45 100644 --- a/components/exo/wayland/zaura_shell.h +++ b/components/exo/wayland/zaura_shell.h
@@ -10,6 +10,8 @@ #include "chromeos/ui/base/window_state_type.h" #include "components/exo/surface.h" #include "components/exo/surface_observer.h" +#include "components/exo/wayland/wayland_display_observer.h" +#include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/size_f.h" #include "ui/wm/public/activation_change_observer.h" @@ -24,7 +26,7 @@ namespace wayland { class SerialTracker; -constexpr uint32_t kZAuraShellVersion = 31; +constexpr uint32_t kZAuraShellVersion = 32; // Adds bindings to the Aura Shell. Normally this implies Ash on ChromeOS // builds. On non-ChromeOS builds the protocol provides access to Aura windowing @@ -148,6 +150,26 @@ ShellSurfaceBase* shell_surface_; }; +class AuraOutput : public WaylandDisplayObserver { + public: + explicit AuraOutput(wl_resource* resource); + + AuraOutput(const AuraOutput&) = delete; + AuraOutput& operator=(const AuraOutput&) = delete; + + ~AuraOutput() override; + + // Overridden from WaylandDisplayObserver: + bool SendDisplayMetrics(const display::Display& display, + uint32_t changed_metrics) override; + + protected: + virtual void SendInsets(const gfx::Insets& insets); + + private: + wl_resource* const resource_; +}; + } // namespace wayland } // namespace exo
diff --git a/components/exo/wayland/zaura_shell_unittest.cc b/components/exo/wayland/zaura_shell_unittest.cc index b5b975f..1ac9993 100644 --- a/components/exo/wayland/zaura_shell_unittest.cc +++ b/components/exo/wayland/zaura_shell_unittest.cc
@@ -6,6 +6,7 @@ #include <aura-shell-server-protocol.h> +#include <sys/socket.h> #include <memory> #include "ash/session/session_controller_impl.h" @@ -402,5 +403,40 @@ aura_surface().SetFullscreenMode(ZAURA_SURFACE_FULLSCREEN_MODE_IMMERSIVE); } +class MockAuraOutput : public AuraOutput { + public: + using AuraOutput::AuraOutput; + + MOCK_METHOD(void, SendInsets, (const gfx::Insets&), (override)); +}; + +using ZAuraOutputTest = test::ExoTestBase; + +TEST_F(ZAuraOutputTest, SendInsets) { + int fds[2]; + ASSERT_EQ( + socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, /*protocol=*/0, fds), 0); + wl_display* wayland_display = wl_display_create(); + wl_client* client = wl_client_create(wayland_display, fds[0]); + wl_resource* resource = wl_resource_create( + client, &zaura_output_interface, ZAURA_OUTPUT_INSETS_SINCE_VERSION, 0); + + MockAuraOutput mock_aura_output(resource); + + UpdateDisplay("800x600"); + display::Display display = + display_manager()->GetDisplayForId(display_manager()->first_display_id()); + const gfx::Rect initial_bounds{800, 600}; + EXPECT_EQ(display.bounds(), initial_bounds); + const gfx::Rect new_work_area{10, 20, 500, 400}; + EXPECT_NE(display.work_area(), new_work_area); + display.set_work_area(new_work_area); + + const gfx::Insets expected_insets = initial_bounds.InsetsFrom(new_work_area); + EXPECT_CALL(mock_aura_output, SendInsets(expected_insets)).Times(1); + mock_aura_output.SendDisplayMetrics( + display, display::DisplayObserver::DISPLAY_METRIC_WORK_AREA); +} + } // namespace wayland } // namespace exo
diff --git a/components/performance_manager/service_worker_context_adapter.cc b/components/performance_manager/service_worker_context_adapter.cc index 0f88c05..2da5bade 100644 --- a/components/performance_manager/service_worker_context_adapter.cc +++ b/components/performance_manager/service_worker_context_adapter.cc
@@ -194,6 +194,13 @@ NOTIMPLEMENTED(); } +service_manager::InterfaceProvider* +ServiceWorkerContextAdapter::GetRemoteInterfaces( + int64_t service_worker_version_id) { + NOTIMPLEMENTED(); + return nullptr; +} + void ServiceWorkerContextAdapter::StartServiceWorkerAndDispatchMessage( const GURL& scope, const blink::StorageKey& key,
diff --git a/components/performance_manager/service_worker_context_adapter.h b/components/performance_manager/service_worker_context_adapter.h index b654575..9d4ba7a 100644 --- a/components/performance_manager/service_worker_context_adapter.h +++ b/components/performance_manager/service_worker_context_adapter.h
@@ -100,6 +100,8 @@ const base::flat_map<int64_t /* version_id */, content::ServiceWorkerRunningInfo>& GetRunningServiceWorkerInfos() override; + service_manager::InterfaceProvider* GetRemoteInterfaces( + int64_t service_worker_version_id) override; // content::ServiceWorkerContextObserver: void OnRegistrationCompleted(const GURL& scope) override;
diff --git a/components/segmentation_platform/internal/BUILD.gn b/components/segmentation_platform/internal/BUILD.gn index 3fa77f6..40e7c0e5 100644 --- a/components/segmentation_platform/internal/BUILD.gn +++ b/components/segmentation_platform/internal/BUILD.gn
@@ -28,8 +28,6 @@ "database/database_maintenance.h", "database/database_maintenance_impl.cc", "database/database_maintenance_impl.h", - "database/metadata_utils.cc", - "database/metadata_utils.h", "database/segment_info_database.cc", "database/segment_info_database.h", "database/signal_database.h", @@ -84,6 +82,10 @@ "execution/processing/uma_feature_processor.h", "local_state_helper_impl.cc", "local_state_helper_impl.h", + "metadata/metadata_utils.cc", + "metadata/metadata_utils.h", + "metadata/metadata_writer.cc", + "metadata/metadata_writer.h", "metric_filter_utils.cc", "metric_filter_utils.h", "platform_options.cc", @@ -194,7 +196,6 @@ sources = [ "data_collection/training_data_collector_impl_unittest.cc", "database/database_maintenance_impl_unittest.cc", - "database/metadata_utils_unittest.cc", "database/mock_signal_database.cc", "database/mock_signal_database.h", "database/mock_signal_storage_config.cc", @@ -226,6 +227,7 @@ "execution/processing/mock_feature_list_query_processor.h", "execution/processing/query_processor.h", "execution/processing/sql_feature_processor_unittest.cc", + "metadata/metadata_utils_unittest.cc", "mock_ukm_data_manager.cc", "mock_ukm_data_manager.h", "scheduler/model_execution_scheduler_unittest.cc",
diff --git a/components/segmentation_platform/internal/data_collection/training_data_collector_impl.cc b/components/segmentation_platform/internal/data_collection/training_data_collector_impl.cc index ac00d464..8298b050 100644 --- a/components/segmentation_platform/internal/data_collection/training_data_collector_impl.cc +++ b/components/segmentation_platform/internal/data_collection/training_data_collector_impl.cc
@@ -9,9 +9,9 @@ #include "base/notreached.h" #include "base/time/clock.h" #include "components/segmentation_platform/internal/constants.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/signal_storage_config.h" #include "components/segmentation_platform/internal/execution/processing/feature_list_query_processor.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/internal/segmentation_ukm_helper.h" #include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h" @@ -235,10 +235,8 @@ base::TimeDelta signal_storage_length = model_metadata.signal_storage_length() * metadata_utils::GetTimeUnit(model_metadata); - if (LocalStateHelper::GetInstance().GetPrefTime( - kSegmentationUkmMostRecentAllowedTimeKey) + - signal_storage_length >= - clock_->Now()) { + if (!SegmentationUkmHelper::AllowedToUploadData(signal_storage_length, + clock_)) { RecordTrainingDataCollectionEvent( segment_info.segment_id(), stats::TrainingDataCollectionEvent::kPartialDataNotAllowed);
diff --git a/components/segmentation_platform/internal/data_collection/training_data_collector_impl_unittest.cc b/components/segmentation_platform/internal/data_collection/training_data_collector_impl_unittest.cc index aa2c800..c2daf82 100644 --- a/components/segmentation_platform/internal/data_collection/training_data_collector_impl_unittest.cc +++ b/components/segmentation_platform/internal/data_collection/training_data_collector_impl_unittest.cc
@@ -13,10 +13,10 @@ #include "base/test/task_environment.h" #include "components/prefs/testing_pref_service.h" #include "components/segmentation_platform/internal/constants.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/mock_signal_storage_config.h" #include "components/segmentation_platform/internal/database/test_segment_info_database.h" #include "components/segmentation_platform/internal/execution/processing/mock_feature_list_query_processor.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/internal/proto/model_prediction.pb.h" #include "components/segmentation_platform/internal/segmentation_ukm_helper.h"
diff --git a/components/segmentation_platform/internal/database/database_maintenance_impl.cc b/components/segmentation_platform/internal/database/database_maintenance_impl.cc index c81318c4..aa35a1de 100644 --- a/components/segmentation_platform/internal/database/database_maintenance_impl.cc +++ b/components/segmentation_platform/internal/database/database_maintenance_impl.cc
@@ -20,11 +20,11 @@ #include "base/time/clock.h" #include "base/time/time.h" #include "base/trace_event/typed_macros.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" #include "components/segmentation_platform/internal/database/signal_database.h" #include "components/segmentation_platform/internal/database/signal_storage_config.h" #include "components/segmentation_platform/internal/execution/default_model_manager.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/types.pb.h" #include "components/segmentation_platform/internal/stats.h" #include "components/segmentation_platform/public/config.h"
diff --git a/components/segmentation_platform/internal/database/signal_database_impl.cc b/components/segmentation_platform/internal/database/signal_database_impl.cc index 2d01518..4e8f496 100644 --- a/components/segmentation_platform/internal/database/signal_database_impl.cc +++ b/components/segmentation_platform/internal/database/signal_database_impl.cc
@@ -18,9 +18,9 @@ #include "base/time/time.h" #include "base/trace_event/typed_macros.h" #include "components/leveldb_proto/public/proto_database.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/signal_database.h" #include "components/segmentation_platform/internal/database/signal_key.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/signal.pb.h" #include "components/segmentation_platform/internal/stats.h" #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/components/segmentation_platform/internal/database/signal_storage_config.cc b/components/segmentation_platform/internal/database/signal_storage_config.cc index eef23789..e35d2bbd 100644 --- a/components/segmentation_platform/internal/database/signal_storage_config.cc +++ b/components/segmentation_platform/internal/database/signal_storage_config.cc
@@ -6,7 +6,7 @@ #include "base/callback_helpers.h" #include "base/containers/contains.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" namespace segmentation_platform { namespace {
diff --git a/components/segmentation_platform/internal/database/test_segment_info_database.cc b/components/segmentation_platform/internal/database/test_segment_info_database.cc index 5f5ff8f..3fbd7c3 100644 --- a/components/segmentation_platform/internal/database/test_segment_info_database.cc +++ b/components/segmentation_platform/internal/database/test_segment_info_database.cc
@@ -10,38 +10,13 @@ #include "base/metrics/metrics_hashes.h" #include "components/optimization_guide/proto/models.pb.h" #include "components/segmentation_platform/internal/constants.h" -#include "components/segmentation_platform/internal/proto/model_metadata.pb.h" +#include "components/segmentation_platform/internal/metadata/metadata_writer.h" #include "components/segmentation_platform/internal/proto/model_prediction.pb.h" #include "components/segmentation_platform/internal/proto/types.pb.h" -#include "components/segmentation_platform/internal/signals/ukm_config.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace segmentation_platform::test { -namespace { -void AddFeature(proto::SegmentInfo* segment_info, - proto::SignalType signal_type, - const std::string& name, - uint64_t bucket_count, - uint64_t tensor_length, - proto::Aggregation aggregation, - const std::vector<int32_t>& accepted_enum_ids) { - proto::SegmentationModelMetadata* metadata = - segment_info->mutable_model_metadata(); - proto::InputFeature* input = metadata->add_input_features(); - proto::UMAFeature* feature = input->mutable_uma_feature(); - feature->set_type(signal_type); - feature->set_name(name); - feature->set_name_hash(base::HashMetricName(name)); - feature->set_bucket_count(bucket_count); - feature->set_tensor_length(tensor_length); - feature->set_aggregation(aggregation); - - for (int32_t accepted_enum_id : accepted_enum_ids) - feature->add_enum_ids(accepted_enum_id); -} -} // namespace - TestSegmentInfoDatabase::TestSegmentInfoDatabase() : SegmentInfoDatabase(nullptr) {} @@ -123,8 +98,16 @@ uint64_t tensor_length, proto::Aggregation aggregation) { proto::SegmentInfo* info = FindOrCreateSegment(segment_id); - AddFeature(info, proto::SignalType::USER_ACTION, name, bucket_count, - tensor_length, aggregation, {}); + MetadataWriter writer(info->mutable_model_metadata()); + MetadataWriter::UMAFeature feature{ + .signal_type = proto::SignalType::USER_ACTION, + .name = name.c_str(), + .bucket_count = bucket_count, + .tensor_length = tensor_length, + .aggregation = aggregation, + .accepted_enum_ids = nullptr}; + MetadataWriter::UMAFeature features[] = {feature}; + writer.AddUmaFeatures(features, 1); } void TestSegmentInfoDatabase::AddHistogramValueFeature( @@ -134,8 +117,16 @@ uint64_t tensor_length, proto::Aggregation aggregation) { proto::SegmentInfo* info = FindOrCreateSegment(segment_id); - AddFeature(info, proto::SignalType::HISTOGRAM_VALUE, name, bucket_count, - tensor_length, aggregation, {}); + MetadataWriter writer(info->mutable_model_metadata()); + MetadataWriter::UMAFeature feature{ + .signal_type = proto::SignalType::HISTOGRAM_VALUE, + .name = name.c_str(), + .bucket_count = bucket_count, + .tensor_length = tensor_length, + .aggregation = aggregation, + .accepted_enum_ids = nullptr}; + MetadataWriter::UMAFeature features[] = {feature}; + writer.AddUmaFeatures(features, 1); } void TestSegmentInfoDatabase::AddHistogramEnumFeature( @@ -146,26 +137,26 @@ proto::Aggregation aggregation, const std::vector<int32_t>& accepted_enum_ids) { proto::SegmentInfo* info = FindOrCreateSegment(segment_id); - AddFeature(info, proto::SignalType::HISTOGRAM_ENUM, name, bucket_count, - tensor_length, aggregation, accepted_enum_ids); + MetadataWriter writer(info->mutable_model_metadata()); + MetadataWriter::UMAFeature feature{ + .signal_type = proto::SignalType::HISTOGRAM_ENUM, + .name = name.c_str(), + .bucket_count = bucket_count, + .tensor_length = tensor_length, + .aggregation = aggregation, + .enum_ids_size = accepted_enum_ids.size(), + .accepted_enum_ids = accepted_enum_ids.data()}; + MetadataWriter::UMAFeature features[] = {feature}; + writer.AddUmaFeatures(features, 1); } -void TestSegmentInfoDatabase::AddSqlFeature(OptimizationTarget segment_id, - const std::string& sql, - const UkmConfig& event_config) { +void TestSegmentInfoDatabase::AddSqlFeature( + OptimizationTarget segment_id, + const MetadataWriter::SqlFeature& feature) { proto::SegmentInfo* info = FindOrCreateSegment(segment_id); - auto* metadata = info->mutable_model_metadata(); - proto::SqlFeature* feature = - metadata->add_input_features()->mutable_sql_feature(); - feature->set_sql(sql); - for (const auto& event_it : event_config.metrics_for_event_for_testing()) { - auto* ukm_event = feature->mutable_signal_filter()->add_ukm_events(); - const UkmEventHash event_hash = event_it.first; - ukm_event->set_event_hash(event_hash.GetUnsafeValue()); - const base::flat_set<UkmMetricHash>& metrics = event_it.second; - for (const auto& metric : metrics) - ukm_event->mutable_metric_hash_filter()->Add(metric.GetUnsafeValue()); - } + MetadataWriter writer(info->mutable_model_metadata()); + MetadataWriter::SqlFeature features[] = {feature}; + writer.AddSqlFeatures(features, 1); } void TestSegmentInfoDatabase::AddPredictionResult(OptimizationTarget segment_id,
diff --git a/components/segmentation_platform/internal/database/test_segment_info_database.h b/components/segmentation_platform/internal/database/test_segment_info_database.h index abcd6de..b50d9c41 100644 --- a/components/segmentation_platform/internal/database/test_segment_info_database.h +++ b/components/segmentation_platform/internal/database/test_segment_info_database.h
@@ -11,15 +11,12 @@ #include "base/containers/flat_set.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" #include "components/segmentation_platform/internal/database/ukm_types.h" +#include "components/segmentation_platform/internal/metadata/metadata_writer.h" #include "components/segmentation_platform/internal/proto/aggregation.pb.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/internal/proto/model_prediction.pb.h" -namespace segmentation_platform { - -class UkmConfig; - -namespace test { +namespace segmentation_platform::test { // A fake database with sample entries that can be used for tests. class TestSegmentInfoDatabase : public SegmentInfoDatabase { @@ -60,8 +57,7 @@ proto::Aggregation aggregation, const std::vector<int32_t>& accepted_enum_ids); void AddSqlFeature(OptimizationTarget segment_id, - const std::string& sql, - const UkmConfig& ukm_config); + const MetadataWriter::SqlFeature& feature); void AddPredictionResult(OptimizationTarget segment_id, float score, base::Time timestamp); @@ -80,8 +76,6 @@ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>> segment_infos_; }; -} // namespace test - -} // namespace segmentation_platform +} // namespace segmentation_platform::test #endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_TEST_SEGMENT_INFO_DATABASE_H_
diff --git a/components/segmentation_platform/internal/database/ukm_types.h b/components/segmentation_platform/internal/database/ukm_types.h index 0dddd25f..5b94a59 100644 --- a/components/segmentation_platform/internal/database/ukm_types.h +++ b/components/segmentation_platform/internal/database/ukm_types.h
@@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" #include "base/time/time.h" #include "base/types/id_type.h" @@ -21,6 +22,9 @@ using UkmMetricHash = base::IdTypeU64<class UkmMetricHashTag>; using UrlId = base::IdType64<class UrlIdTag>; +using UkmEventsToMetricsMap = + base::flat_map<UkmEventHash, base::flat_set<UkmMetricHash>>; + namespace processing { // A struct that can accommodate multiple output types needed for Segmentation
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc b/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc index 5f0bc83..0c58d556 100644 --- a/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc +++ b/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc
@@ -17,8 +17,8 @@ #include "base/time/time.h" #include "base/trace_event/typed_macros.h" #include "components/optimization_guide/proto/models.pb.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/execution/model_execution_manager.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/internal/proto/model_prediction.pb.h" #include "components/segmentation_platform/internal/stats.h"
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc b/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc index 14fe745..882d042 100644 --- a/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc +++ b/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc
@@ -19,7 +19,6 @@ #include "base/test/task_environment.h" #include "base/time/time.h" #include "components/optimization_guide/proto/models.pb.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/mock_signal_database.h" #include "components/segmentation_platform/internal/database/signal_database.h" #include "components/segmentation_platform/internal/database/test_segment_info_database.h" @@ -27,6 +26,7 @@ #include "components/segmentation_platform/internal/execution/model_execution_manager.h" #include "components/segmentation_platform/internal/execution/model_execution_status.h" #include "components/segmentation_platform/internal/execution/processing/feature_list_query_processor.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/aggregation.pb.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/internal/proto/types.pb.h"
diff --git a/components/segmentation_platform/internal/execution/model_executor_impl.cc b/components/segmentation_platform/internal/execution/model_executor_impl.cc index 79a924a..8db1f8f 100644 --- a/components/segmentation_platform/internal/execution/model_executor_impl.cc +++ b/components/segmentation_platform/internal/execution/model_executor_impl.cc
@@ -62,6 +62,7 @@ std::vector<float> input_tensor; base::Time total_execution_start_time; base::Time model_execution_start_time; + base::TimeDelta signal_storage_length; }; ModelExecutorImpl::ModelExecutionTraceEvent::ModelExecutionTraceEvent( @@ -105,7 +106,7 @@ ModelExecutionTraceEvent trace_event("ModelExecutorImpl::ExecuteModel", *state); - if (!state->model_provider->ModelAvailable()) { + if (!state->model_provider || !state->model_provider->ModelAvailable()) { RunModelExecutionCallback(std::move(state), 0, ModelExecutionStatus::kSkippedModelNotReady); return; @@ -120,6 +121,10 @@ } state->model_version = segment_info.model_version(); + const proto::SegmentationModelMetadata& model_metadata = + segment_info.model_metadata(); + state->signal_storage_length = model_metadata.signal_storage_length() * + metadata_utils::GetTimeUnit(model_metadata); feature_list_query_processor_->ProcessFeatureList( segment_info.model_metadata(), segment_id, clock_->Now(), FeatureListQueryProcessor::ProcessOption::kInputsOnly, @@ -180,7 +185,8 @@ << optimization_guide::proto::OptimizationTarget_Name( state->segment_id); stats::RecordModelExecutionResult(state->segment_id, result.value()); - if (state->model_version) { + if (state->model_version && SegmentationUkmHelper::AllowedToUploadData( + state->signal_storage_length, clock_)) { SegmentationUkmHelper::GetInstance()->RecordModelExecutionResult( state->segment_id, state->model_version, state->input_tensor, result.value());
diff --git a/components/segmentation_platform/internal/execution/model_executor_impl_unittest.cc b/components/segmentation_platform/internal/execution/model_executor_impl_unittest.cc index a94e73d..868d4f4 100644 --- a/components/segmentation_platform/internal/execution/model_executor_impl_unittest.cc +++ b/components/segmentation_platform/internal/execution/model_executor_impl_unittest.cc
@@ -19,7 +19,6 @@ #include "base/test/task_environment.h" #include "base/time/time.h" #include "components/optimization_guide/proto/models.pb.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/mock_signal_database.h" #include "components/segmentation_platform/internal/database/signal_database.h" #include "components/segmentation_platform/internal/database/test_segment_info_database.h" @@ -27,6 +26,7 @@ #include "components/segmentation_platform/internal/execution/model_execution_status.h" #include "components/segmentation_platform/internal/execution/model_executor.h" #include "components/segmentation_platform/internal/execution/processing/mock_feature_list_query_processor.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/aggregation.pb.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/internal/proto/types.pb.h"
diff --git a/components/segmentation_platform/internal/execution/processing/custom_input_processor.cc b/components/segmentation_platform/internal/execution/processing/custom_input_processor.cc index f591440..4c45592 100644 --- a/components/segmentation_platform/internal/execution/processing/custom_input_processor.cc +++ b/components/segmentation_platform/internal/execution/processing/custom_input_processor.cc
@@ -6,9 +6,9 @@ #include "base/strings/string_number_conversions.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/ukm_types.h" #include "components/segmentation_platform/internal/execution/processing/feature_processor_state.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" namespace segmentation_platform::processing {
diff --git a/components/segmentation_platform/internal/execution/processing/feature_list_query_processor.cc b/components/segmentation_platform/internal/execution/processing/feature_list_query_processor.cc index dc452a47..b6f5245 100644 --- a/components/segmentation_platform/internal/execution/processing/feature_list_query_processor.cc +++ b/components/segmentation_platform/internal/execution/processing/feature_list_query_processor.cc
@@ -9,13 +9,13 @@ #include "base/memory/weak_ptr.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/time/clock.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/storage_service.h" #include "components/segmentation_platform/internal/database/ukm_types.h" #include "components/segmentation_platform/internal/execution/processing/custom_input_processor.h" #include "components/segmentation_platform/internal/execution/processing/feature_processor_state.h" #include "components/segmentation_platform/internal/execution/processing/sql_feature_processor.h" #include "components/segmentation_platform/internal/execution/processing/uma_feature_processor.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/internal/stats.h" #include "components/segmentation_platform/internal/ukm_data_manager.h"
diff --git a/components/segmentation_platform/internal/execution/processing/sql_feature_processor.cc b/components/segmentation_platform/internal/execution/processing/sql_feature_processor.cc index 7b6e835..fc7f7a48 100644 --- a/components/segmentation_platform/internal/execution/processing/sql_feature_processor.cc +++ b/components/segmentation_platform/internal/execution/processing/sql_feature_processor.cc
@@ -8,9 +8,9 @@ #include "base/bind.h" #include "base/containers/flat_map.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/execution/processing/custom_input_processor.h" #include "components/segmentation_platform/internal/execution/processing/feature_processor_state.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" namespace segmentation_platform::processing {
diff --git a/components/segmentation_platform/internal/execution/processing/uma_feature_processor.cc b/components/segmentation_platform/internal/execution/processing/uma_feature_processor.cc index 0f5b42a5..e3541c1 100644 --- a/components/segmentation_platform/internal/execution/processing/uma_feature_processor.cc +++ b/components/segmentation_platform/internal/execution/processing/uma_feature_processor.cc
@@ -9,9 +9,9 @@ #include "base/memory/weak_ptr.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/timer/elapsed_timer.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/ukm_types.h" #include "components/segmentation_platform/internal/execution/processing/feature_processor_state.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/internal/stats.h"
diff --git a/components/segmentation_platform/internal/database/metadata_utils.cc b/components/segmentation_platform/internal/metadata/metadata_utils.cc similarity index 99% rename from components/segmentation_platform/internal/database/metadata_utils.cc rename to components/segmentation_platform/internal/metadata/metadata_utils.cc index a3ceff8..7cf303ed 100644 --- a/components/segmentation_platform/internal/database/metadata_utils.cc +++ b/components/segmentation_platform/internal/metadata/metadata_utils.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 "components/segmentation_platform/internal/database/metadata_utils.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include <inttypes.h>
diff --git a/components/segmentation_platform/internal/database/metadata_utils.h b/components/segmentation_platform/internal/metadata/metadata_utils.h similarity index 95% rename from components/segmentation_platform/internal/database/metadata_utils.h rename to components/segmentation_platform/internal/metadata/metadata_utils.h index 50c4b5ae..85ff2bb 100644 --- a/components/segmentation_platform/internal/database/metadata_utils.h +++ b/components/segmentation_platform/internal/metadata/metadata_utils.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 COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_METADATA_UTILS_H_ -#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_METADATA_UTILS_H_ +#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_METADATA_METADATA_UTILS_H_ +#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_METADATA_METADATA_UTILS_H_ #include "base/time/time.h" #include "components/optimization_guide/proto/models.pb.h" @@ -119,4 +119,4 @@ } // namespace metadata_utils } // namespace segmentation_platform -#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_METADATA_UTILS_H_ +#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_METADATA_METADATA_UTILS_H_
diff --git a/components/segmentation_platform/internal/database/metadata_utils_unittest.cc b/components/segmentation_platform/internal/metadata/metadata_utils_unittest.cc similarity index 99% rename from components/segmentation_platform/internal/database/metadata_utils_unittest.cc rename to components/segmentation_platform/internal/metadata/metadata_utils_unittest.cc index 5fcbce1..962e8799 100644 --- a/components/segmentation_platform/internal/database/metadata_utils_unittest.cc +++ b/components/segmentation_platform/internal/metadata/metadata_utils_unittest.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 "components/segmentation_platform/internal/database/metadata_utils.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "base/metrics/metrics_hashes.h" #include "components/optimization_guide/proto/models.pb.h"
diff --git a/chrome/browser/segmentation_platform/default_model/metadata_writer.cc b/components/segmentation_platform/internal/metadata/metadata_writer.cc similarity index 73% rename from chrome/browser/segmentation_platform/default_model/metadata_writer.cc rename to components/segmentation_platform/internal/metadata/metadata_writer.cc index 22740c59..57b52be 100644 --- a/chrome/browser/segmentation_platform/default_model/metadata_writer.cc +++ b/components/segmentation_platform/internal/metadata/metadata_writer.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 "chrome/browser/segmentation_platform/default_model/metadata_writer.h" +#include "components/segmentation_platform/internal/metadata/metadata_writer.h" #include "base/metrics/metrics_hashes.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" @@ -32,6 +32,25 @@ } } +void MetadataWriter::AddSqlFeatures(const SqlFeature features[], + size_t features_size) { + proto::SqlFeature* feature = + metadata_->add_input_features()->mutable_sql_feature(); + for (size_t i = 0; i < features_size; ++i) { + const auto& f = features[i]; + feature->set_sql(f.sql); + for (size_t ev = 0; ev < f.events_size; ++ev) { + const auto& event = f.events[ev]; + auto* ukm_event = feature->mutable_signal_filter()->add_ukm_events(); + ukm_event->set_event_hash(event.event_hash.GetUnsafeValue()); + for (size_t m = 0; m < event.metrics_size; ++m) { + ukm_event->mutable_metric_hash_filter()->Add( + event.metrics[m].GetUnsafeValue()); + } + } + } +} + void MetadataWriter::AddDiscreteMappingEntries( const std::string& key, const std::pair<float, int>* mappings,
diff --git a/components/segmentation_platform/internal/metadata/metadata_writer.h b/components/segmentation_platform/internal/metadata/metadata_writer.h new file mode 100644 index 0000000..091a53a --- /dev/null +++ b/components/segmentation_platform/internal/metadata/metadata_writer.h
@@ -0,0 +1,97 @@ +// Copyright 2022 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_SEGMENTATION_PLATFORM_INTERNAL_METADATA_METADATA_WRITER_H_ +#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_METADATA_METADATA_WRITER_H_ + +#include <cinttypes> +#include <cstddef> + +#include "components/segmentation_platform/internal/database/ukm_types.h" +#include "components/segmentation_platform/internal/proto/model_metadata.pb.h" + +namespace segmentation_platform { + +// Utility to write metadata proto for default models. +class MetadataWriter { + public: + explicit MetadataWriter(proto::SegmentationModelMetadata* metadata); + ~MetadataWriter(); + + MetadataWriter(MetadataWriter&) = delete; + MetadataWriter& operator=(MetadataWriter&) = delete; + + // Defines a feature based on UMA metric. + struct UMAFeature { + const proto::SignalType signal_type{proto::SignalType::UNKNOWN_SIGNAL_TYPE}; + const char* name{nullptr}; + const uint64_t bucket_count{0}; + const uint64_t tensor_length{0}; + const proto::Aggregation aggregation{proto::Aggregation::UNKNOWN}; + const size_t enum_ids_size{0}; + const int32_t* const accepted_enum_ids = nullptr; + + static constexpr UMAFeature FromUserAction(const char* name, + uint64_t bucket_count) { + return MetadataWriter::UMAFeature{ + .signal_type = proto::SignalType::USER_ACTION, + .name = name, + .bucket_count = bucket_count, + .tensor_length = 1, + .aggregation = proto::Aggregation::COUNT, + .enum_ids_size = 0}; + } + static constexpr UMAFeature FromEnumHistogram(const char* name, + uint64_t bucket_count, + const int32_t* const enum_ids, + size_t enum_ids_size) { + return MetadataWriter::UMAFeature{ + .signal_type = proto::SignalType::HISTOGRAM_ENUM, + .name = name, + .bucket_count = bucket_count, + .tensor_length = 1, + .aggregation = proto::Aggregation::COUNT, + .enum_ids_size = enum_ids_size, + .accepted_enum_ids = enum_ids}; + } + }; + + // Defines a feature based on a SQL query. + // TODO(ssid): Support custom inputs. + struct SqlFeature { + const char* const sql{nullptr}; + struct EventAndMetrics { + const UkmEventHash event_hash; + const UkmMetricHash* const metrics{nullptr}; + const size_t metrics_size{0}; + }; + const EventAndMetrics* const events{nullptr}; + const size_t events_size{0}; + }; + + // Appends the list of UMA features in order. + void AddUmaFeatures(const UMAFeature features[], size_t features_size); + + // Appends the list of SQL features in order. + void AddSqlFeatures(const SqlFeature features[], size_t features_size); + + // Appends a list of discrete mapping in order. + void AddDiscreteMappingEntries(const std::string& key, + const std::pair<float, int>* mappings, + size_t mappings_size); + + // Writes the model metadata with the given parameters. + void SetSegmentationMetadataConfig(proto::TimeUnit time_unit, + uint64_t bucket_duration, + int64_t signal_storage_length, + int64_t min_signal_collection_length, + int64_t result_time_to_live); + + private: + proto::SegmentationModelMetadata* const metadata_; +}; + +} // namespace segmentation_platform + +#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_METADATA_METADATA_WRITER_H_
diff --git a/components/segmentation_platform/internal/scheduler/execution_service.cc b/components/segmentation_platform/internal/scheduler/execution_service.cc index 7087ea1..590663f 100644 --- a/components/segmentation_platform/internal/scheduler/execution_service.cc +++ b/components/segmentation_platform/internal/scheduler/execution_service.cc
@@ -8,6 +8,7 @@ #include "components/prefs/pref_service.h" #include "components/segmentation_platform/internal/data_collection/training_data_collector.h" #include "components/segmentation_platform/internal/database/storage_service.h" +#include "components/segmentation_platform/internal/execution/default_model_manager.h" #include "components/segmentation_platform/internal/execution/model_executor_impl.h" #include "components/segmentation_platform/internal/execution/processing/feature_aggregator_impl.h" #include "components/segmentation_platform/internal/execution/processing/feature_list_query_processor.h" @@ -28,10 +29,12 @@ void ExecutionService::InitForTesting( std::unique_ptr<processing::FeatureListQueryProcessor> feature_processor, std::unique_ptr<ModelExecutor> executor, - std::unique_ptr<ModelExecutionScheduler> scheduler) { + std::unique_ptr<ModelExecutionScheduler> scheduler, + std::unique_ptr<ModelExecutionManager> execution_manager) { feature_list_query_processor_ = std::move(feature_processor); model_executor_ = std::move(executor); model_execution_scheduler_ = std::move(scheduler); + model_execution_manager_ = std::move(execution_manager); } void ExecutionService::Initialize( @@ -46,6 +49,8 @@ const PlatformOptions& platform_options, std::vector<std::unique_ptr<Config>>* configs, PrefService* profile_prefs) { + storage_service_ = storage_service; + feature_list_query_processor_ = std::make_unique<processing::FeatureListQueryProcessor>( storage_service, @@ -75,27 +80,31 @@ model_execution_scheduler_->OnNewModelInfoReady(segment_info); } +ModelProvider* ExecutionService::GetModelProvider( + OptimizationTarget segment_id) { + return model_execution_manager_->GetProvider(segment_id); +} + void ExecutionService::RequestModelExecution( std::unique_ptr<ExecutionRequest> request) { DCHECK(request->segment_info); - if (!request->callback.is_null() && request->model_provider) { - DCHECK(!request->save_result_to_db) - << "save_result_to_db + callback cannot be set together"; - model_executor_->ExecuteModel( - *request->segment_info, request->model_provider, - request->record_metrics_for_default, std::move(request->callback)); - } else if (request->save_result_to_db) { + if (request->save_result_to_db) { DCHECK(!request->record_metrics_for_default) << "cannot record metics for default model from scheduler"; + // TODO(ssid): Scheduler should use the `request` instead of fetching the + // model provider. DCHECK(!request->model_provider) << "using custom model provider to save result is not supported"; DCHECK(request->callback.is_null()) << "save_result_to_db + callback cannot be set together"; model_execution_scheduler_->RequestModelExecution(*request->segment_info); - } else { - NOTREACHED() - << "On demand xecution of non-default model is not yet supported"; + return; } + + DCHECK(!request->callback.is_null()); + model_executor_->ExecuteModel(*request->segment_info, request->model_provider, + request->record_metrics_for_default, + std::move(request->callback)); } void ExecutionService::OverwriteModelExecutionResult(
diff --git a/components/segmentation_platform/internal/scheduler/execution_service.h b/components/segmentation_platform/internal/scheduler/execution_service.h index 49e8028..1b4969f 100644 --- a/components/segmentation_platform/internal/scheduler/execution_service.h +++ b/components/segmentation_platform/internal/scheduler/execution_service.h
@@ -42,7 +42,8 @@ void InitForTesting( std::unique_ptr<processing::FeatureListQueryProcessor> feature_processor, std::unique_ptr<ModelExecutor> executor, - std::unique_ptr<ModelExecutionScheduler> scheduler); + std::unique_ptr<ModelExecutionScheduler> scheduler, + std::unique_ptr<ModelExecutionManager> execution_manager); void Initialize( StorageService* storage_service, @@ -61,8 +62,12 @@ // SegmentInfo with valid metadata and features. void OnNewModelInfoReady(const proto::SegmentInfo& segment_info); + // Gets the model provider for execution. + ModelProvider* GetModelProvider(OptimizationTarget segment_id); + using ModelExecutionCallback = base::OnceCallback<void(const std::pair<float, ModelExecutionStatus>&)>; + struct ExecutionRequest { ExecutionRequest(); ~ExecutionRequest(); @@ -95,6 +100,8 @@ void RunDailyTasks(bool is_startup); private: + raw_ptr<StorageService> storage_service_{}; + // Training/inference input data generation. std::unique_ptr<processing::FeatureListQueryProcessor> feature_list_query_processor_; @@ -106,7 +113,7 @@ std::unique_ptr<ModelExecutor> model_executor_; // Model execution. - std::unique_ptr<ModelExecutionManagerImpl> model_execution_manager_; + std::unique_ptr<ModelExecutionManager> model_execution_manager_; // Model execution scheduling logic. std::unique_ptr<ModelExecutionScheduler> model_execution_scheduler_;
diff --git a/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc b/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc index f932d22..baeafe3 100644 --- a/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc +++ b/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc
@@ -8,10 +8,10 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/clock.h" #include "base/time/time.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" #include "components/segmentation_platform/internal/database/signal_storage_config.h" #include "components/segmentation_platform/internal/execution/model_execution_manager_impl.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/platform_options.h" #include "components/segmentation_platform/internal/stats.h" #include "components/segmentation_platform/public/model_provider.h"
diff --git a/components/segmentation_platform/internal/segmentation_ukm_helper.cc b/components/segmentation_platform/internal/segmentation_ukm_helper.cc index e976700a..24bc080 100644 --- a/components/segmentation_platform/internal/segmentation_ukm_helper.cc +++ b/components/segmentation_platform/internal/segmentation_ukm_helper.cc
@@ -8,10 +8,13 @@ #include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" +#include "base/time/clock.h" +#include "components/segmentation_platform/internal/constants.h" #include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h" #include "components/segmentation_platform/internal/stats.h" #include "components/segmentation_platform/public/config.h" #include "components/segmentation_platform/public/features.h" +#include "components/segmentation_platform/public/local_state_helper.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" @@ -204,4 +207,14 @@ return base::bit_cast<int64_t>(static_cast<double>(f)); } +// static +bool SegmentationUkmHelper::AllowedToUploadData( + base::TimeDelta signal_storage_length, + base::Clock* clock) { + return LocalStateHelper::GetInstance().GetPrefTime( + kSegmentationUkmMostRecentAllowedTimeKey) + + signal_storage_length < + clock->Now(); +} + } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/segmentation_ukm_helper.h b/components/segmentation_platform/internal/segmentation_ukm_helper.h index 05f33c0..4ceb6e5 100644 --- a/components/segmentation_platform/internal/segmentation_ukm_helper.h +++ b/components/segmentation_platform/internal/segmentation_ukm_helper.h
@@ -7,6 +7,7 @@ #include "base/containers/flat_set.h" #include "base/no_destructor.h" +#include "base/time/time.h" #include "components/optimization_guide/proto/models.pb.h" #include "components/segmentation_platform/internal/proto/model_prediction.pb.h" #include "services/metrics/public/cpp/ukm_source_id.h" @@ -14,6 +15,10 @@ using optimization_guide::proto::OptimizationTarget; +namespace base { +class Clock; +} + namespace ukm::builders { class Segmentation_ModelExecution; } // namespace ukm::builders @@ -57,6 +62,11 @@ // Helper method to encode a float number into int64. static int64_t FloatToInt64(float f); + // Helper method to check if data is allowed to upload through ukm + // given a clock and the signal storage length. + static bool AllowedToUploadData(base::TimeDelta signal_storage_length, + base::Clock* clock); + // Gets a set of segment IDs that are allowed to upload metrics. const base::flat_set<OptimizationTarget>& allowed_segment_ids() { return allowed_segment_ids_;
diff --git a/components/segmentation_platform/internal/segmentation_ukm_helper_unittest.cc b/components/segmentation_platform/internal/segmentation_ukm_helper_unittest.cc index b73ff78..8a3d59ff 100644 --- a/components/segmentation_platform/internal/segmentation_ukm_helper_unittest.cc +++ b/components/segmentation_platform/internal/segmentation_ukm_helper_unittest.cc
@@ -9,10 +9,15 @@ #include "base/bit_cast.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/simple_test_clock.h" #include "base/test/task_environment.h" +#include "components/prefs/testing_pref_service.h" +#include "components/segmentation_platform/internal/constants.h" #include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h" #include "components/segmentation_platform/public/config.h" #include "components/segmentation_platform/public/features.h" +#include "components/segmentation_platform/public/local_state_helper.h" +#include "components/segmentation_platform/public/segmentation_platform_service.h" #include "components/ukm/test_ukm_recorder.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "testing/gtest/include/gtest/gtest.h" @@ -256,4 +261,23 @@ ASSERT_NE(source_id, ukm::kInvalidSourceId); } +TEST_F(SegmentationUkmHelperTest, AllowedToUploadData) { + TestingPrefServiceSimple prefs; + SegmentationPlatformService::RegisterLocalStatePrefs(prefs.registry()); + LocalStateHelper::GetInstance().Initialize(&prefs); + + base::SimpleTestClock clock; + clock.SetNow(base::Time::Now()); + LocalStateHelper::GetInstance().SetPrefTime( + kSegmentationUkmMostRecentAllowedTimeKey, clock.Now()); + + ASSERT_FALSE( + SegmentationUkmHelper::AllowedToUploadData(base::Seconds(1), &clock)); + clock.Advance(base::Seconds(10)); + ASSERT_TRUE( + SegmentationUkmHelper::AllowedToUploadData(base::Seconds(1), &clock)); + ASSERT_FALSE( + SegmentationUkmHelper::AllowedToUploadData(base::Seconds(11), &clock)); +} + } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/selection/experimental_group_recorder.cc b/components/segmentation_platform/internal/selection/experimental_group_recorder.cc index d02fd90..43137e5 100644 --- a/components/segmentation_platform/internal/selection/experimental_group_recorder.cc +++ b/components/segmentation_platform/internal/selection/experimental_group_recorder.cc
@@ -6,8 +6,8 @@ #include "base/bind.h" #include "base/strings/strcat.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/metric_filter_utils.h" #include "components/segmentation_platform/public/config.h" #include "components/segmentation_platform/public/field_trial_register.h"
diff --git a/components/segmentation_platform/internal/selection/segment_result_provider.cc b/components/segmentation_platform/internal/selection/segment_result_provider.cc index 8c9ec0c..79029e1 100644 --- a/components/segmentation_platform/internal/selection/segment_result_provider.cc +++ b/components/segmentation_platform/internal/selection/segment_result_provider.cc
@@ -9,10 +9,10 @@ #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" #include "components/segmentation_platform/internal/database/signal_storage_config.h" #include "components/segmentation_platform/internal/execution/default_model_manager.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/internal/proto/model_prediction.pb.h" #include "components/segmentation_platform/internal/scheduler/execution_service.h" @@ -34,6 +34,22 @@ return rank; } +proto::SegmentInfo* GetSegmentInfo( + DefaultModelManager::SegmentInfoList& available_segments, + bool default_model) { + proto::SegmentInfo* segment_info = nullptr; + DefaultModelManager::SegmentSource needed_source = + default_model ? DefaultModelManager::SegmentSource::DEFAULT_MODEL + : DefaultModelManager::SegmentSource::DATABASE; + for (const auto& info : available_segments) { + if (info->segment_source == needed_source) { + segment_info = &info->segment_info; + break; + } + } + return segment_info; +} + class SegmentResultProviderImpl : public SegmentResultProvider { public: SegmentResultProviderImpl(SegmentInfoDatabase* segment_database, @@ -50,33 +66,33 @@ force_refresh_results_(force_refresh_results), task_runner_(base::SequencedTaskRunnerHandle::Get()) {} - void GetSegmentResult(OptimizationTarget segment_id, - const std::string& segmentation_key, - SegmentResultCallback callback) override; + void GetSegmentResult(GetResultOptions&& options) override; SegmentResultProviderImpl(SegmentResultProviderImpl&) = delete; SegmentResultProviderImpl& operator=(SegmentResultProviderImpl&) = delete; private: struct RequestState { - OptimizationTarget segment_id; - SegmentResultCallback callback; raw_ptr<ModelProvider> default_provider; - std::string segmentation_key; + GetResultOptions options; }; void OnGetSegmentInfo( std::unique_ptr<RequestState> request_state, DefaultModelManager::SegmentInfoList available_segments); + void TryExecuteModelAndGetScore( + std::unique_ptr<RequestState> request_state, + DefaultModelManager::SegmentInfoList available_segments); + void TryGetScoreFromDefaultModel( std::unique_ptr<RequestState> request_state, SegmentResultProvider::ResultState existing_state, DefaultModelManager::SegmentInfoList available_segments); - void OnDefaultModelExecuted( - std::unique_ptr<RequestState> request_state, - std::unique_ptr<proto::SegmentInfo> segment_info, - const std::pair<float, ModelExecutionStatus>& result); + void OnModelExecuted(std::unique_ptr<RequestState> request_state, + std::unique_ptr<proto::SegmentInfo> segment_info, + bool is_metrics_for_default, + const std::pair<float, ModelExecutionStatus>& result); void PostResultCallback(std::unique_ptr<RequestState> request_state, std::unique_ptr<SegmentResult> result); @@ -92,15 +108,11 @@ base::WeakPtrFactory<SegmentResultProviderImpl> weak_ptr_factory_{this}; }; -void SegmentResultProviderImpl::GetSegmentResult( - OptimizationTarget segment_id, - const std::string& segmentation_key, - SegmentResultCallback callback) { +void SegmentResultProviderImpl::GetSegmentResult(GetResultOptions&& options) { + const OptimizationTarget segment_id = options.segment_id; auto request_state = std::make_unique<RequestState>(); request_state = std::make_unique<RequestState>(); - request_state->segment_id = segment_id; - request_state->segmentation_key = segmentation_key; - request_state->callback = std::move(callback); + request_state->options = std::move(options); // Factory can be null in tests. request_state->default_provider = default_model_manager_ @@ -116,20 +128,14 @@ void SegmentResultProviderImpl::OnGetSegmentInfo( std::unique_ptr<RequestState> request_state, DefaultModelManager::SegmentInfoList available_segments) { - const proto::SegmentInfo* db_segment_info = nullptr; - for (const auto& info : available_segments) { - DCHECK_EQ(request_state->segment_id, info->segment_info.segment_id()); - if (info->segment_source == DefaultModelManager::SegmentSource::DATABASE) { - db_segment_info = &info->segment_info; - break; - } - } + const proto::SegmentInfo* db_segment_info = + GetSegmentInfo(available_segments, /*default_model=*/false); // Don't compute results if we don't have enough signals, or don't have // valid unexpired results for any of the segments. if (!db_segment_info) { VLOG(1) << __func__ << ": segment=" - << OptimizationTarget_Name(request_state->segment_id) + << OptimizationTarget_Name(request_state->options.segment_id) << " does not have segment info."; TryGetScoreFromDefaultModel(std::move(request_state), ResultState::kSegmentNotAvailable, @@ -137,8 +143,8 @@ return; } - // TODO(ssid): Remove this check since scheduler does this before executing - // the model. + // TODO(ssid): Remove this check when using database results since the + // scheduler does this before executing the model. if (!force_refresh_results_ && !signal_storage_config_->MeetsSignalCollectionRequirement( db_segment_info->model_metadata())) { @@ -151,6 +157,15 @@ return; } + if (request_state->options.ignore_db_scores) { + VLOG(1) << __func__ << ": segment=" + << OptimizationTarget_Name(db_segment_info->segment_id()) + << " executing model to get score"; + TryExecuteModelAndGetScore(std::move(request_state), + std::move(available_segments)); + return; + } + if (metadata_utils::HasExpiredOrUnavailableResult(*db_segment_info, clock_->Now())) { VLOG(1) << __func__ << ": segment=" @@ -162,13 +177,36 @@ return; } - int rank = - ComputeDiscreteMapping(request_state->segmentation_key, *db_segment_info); + int rank = ComputeDiscreteMapping(request_state->options.segmentation_key, + *db_segment_info); PostResultCallback( std::move(request_state), std::make_unique<SegmentResult>(ResultState::kSuccessFromDatabase, rank)); } +void SegmentResultProviderImpl::TryExecuteModelAndGetScore( + std::unique_ptr<RequestState> request_state, + DefaultModelManager::SegmentInfoList available_segments) { + auto db_segment_info = std::make_unique<proto::SegmentInfo>(); + proto::SegmentInfo* segment_info = + GetSegmentInfo(available_segments, /*default_model=*/false); + // Note: The db segment info in `available_segments` is no longer usable. + db_segment_info->Swap(segment_info); + DCHECK(db_segment_info); + + auto request = std::make_unique<ExecutionService::ExecutionRequest>(); + // The pointer is kept alive by the unique_ptr in the callback. + request->segment_info = db_segment_info.get(); + request->model_provider = + execution_service_->GetModelProvider(db_segment_info->segment_id()); + request->record_metrics_for_default = true; + request->callback = base::BindOnce( + &SegmentResultProviderImpl::OnModelExecuted, + weak_ptr_factory_.GetWeakPtr(), std::move(request_state), + std::move(db_segment_info), /*is_metrics_for_default=*/false); + execution_service_->RequestModelExecution(std::move(request)); +} + void SegmentResultProviderImpl::TryGetScoreFromDefaultModel( std::unique_ptr<RequestState> request_state, SegmentResultProvider::ResultState existing_state, @@ -176,27 +214,18 @@ if (!request_state->default_provider || !request_state->default_provider->ModelAvailable()) { VLOG(1) << __func__ << ": segment=" - << OptimizationTarget_Name(request_state->segment_id) + << OptimizationTarget_Name(request_state->options.segment_id) << " default provider not available"; PostResultCallback(std::move(request_state), std::make_unique<SegmentResult>(existing_state)); return; } - std::unique_ptr<proto::SegmentInfo> default_segment_info; - for (auto& info : available_segments) { - DCHECK_EQ(request_state->segment_id, info->segment_info.segment_id()); - if (info->segment_source == - DefaultModelManager::SegmentSource::DEFAULT_MODEL) { - default_segment_info = std::make_unique<proto::SegmentInfo>(); - default_segment_info->Swap(&info->segment_info); - break; - } - } - - if (!default_segment_info) { + proto::SegmentInfo* segment_info = + GetSegmentInfo(available_segments, /*default_model=*/true); + if (!segment_info) { VLOG(1) << __func__ << ": segment=" - << OptimizationTarget_Name(request_state->segment_id) + << OptimizationTarget_Name(request_state->options.segment_id) << " default segment info not available"; PostResultCallback(std::move(request_state), std::make_unique<SegmentResult>( @@ -204,6 +233,9 @@ return; } + auto default_segment_info = std::make_unique<proto::SegmentInfo>(); + default_segment_info->Swap(segment_info); + DCHECK_EQ( metadata_utils::ValidationResult::kValidationSuccess, metadata_utils::ValidateMetadata(default_segment_info->model_metadata())); @@ -211,7 +243,7 @@ !signal_storage_config_->MeetsSignalCollectionRequirement( default_segment_info->model_metadata())) { VLOG(1) << __func__ << ": segment=" - << OptimizationTarget_Name(request_state->segment_id) + << OptimizationTarget_Name(request_state->options.segment_id) << " signal collection not met"; PostResultCallback(std::move(request_state), std::make_unique<SegmentResult>( @@ -225,29 +257,36 @@ // The pointer is kept alive by the unique_ptr in the callback. request->segment_info = default_segment_info.get(); request->record_metrics_for_default = true; - request->callback = - base::BindOnce(&SegmentResultProviderImpl::OnDefaultModelExecuted, - weak_ptr_factory_.GetWeakPtr(), std::move(request_state), - std::move(default_segment_info)); + request->callback = base::BindOnce( + &SegmentResultProviderImpl::OnModelExecuted, + weak_ptr_factory_.GetWeakPtr(), std::move(request_state), + std::move(default_segment_info), /*is_metrics_for_default=*/true); request->model_provider = default_provider; execution_service_->RequestModelExecution(std::move(request)); } -void SegmentResultProviderImpl::OnDefaultModelExecuted( +void SegmentResultProviderImpl::OnModelExecuted( std::unique_ptr<RequestState> request_state, std::unique_ptr<proto::SegmentInfo> segment_info, + bool is_metrics_for_default, const std::pair<float, ModelExecutionStatus>& result) { if (result.second == ModelExecutionStatus::kSuccess) { segment_info->mutable_prediction_result()->set_result(result.first); - int rank = - ComputeDiscreteMapping(request_state->segmentation_key, *segment_info); + int rank = ComputeDiscreteMapping(request_state->options.segmentation_key, + *segment_info); + ResultState state = is_metrics_for_default + ? ResultState::kDefaultModelScoreUsed + : ResultState::kTfliteModelScoreUsed; PostResultCallback(std::move(request_state), - std::make_unique<SegmentResult>( - ResultState::kDefaultModelScoreUsed, rank)); + std::make_unique<SegmentResult>(state, rank)); } else { + // TODO(ssid): If the real model execution failed, fallback to default + // execution. + ResultState state = is_metrics_for_default + ? ResultState::kDefaultModelExecutionFailed + : ResultState::kTfliteModelExecutionFailed; PostResultCallback(std::move(request_state), - std::make_unique<SegmentResult>( - ResultState::kDefaultModelExecutionFailed)); + std::make_unique<SegmentResult>(state)); } } @@ -255,8 +294,8 @@ std::unique_ptr<RequestState> request_state, std::unique_ptr<SegmentResult> result) { task_runner_->PostTask( - FROM_HERE, - base::BindOnce(std::move(request_state->callback), std::move(result))); + FROM_HERE, base::BindOnce(std::move(request_state->options.callback), + std::move(result))); } } // namespace @@ -267,6 +306,12 @@ : state(state), rank(rank) {} SegmentResultProvider::SegmentResult::~SegmentResult() = default; +SegmentResultProvider::GetResultOptions::GetResultOptions() = default; +SegmentResultProvider::GetResultOptions::~GetResultOptions() = default; +SegmentResultProvider::GetResultOptions& +SegmentResultProvider::GetResultOptions::operator=(GetResultOptions&&) = + default; + // static std::unique_ptr<SegmentResultProvider> SegmentResultProvider::Create( SegmentInfoDatabase* segment_database,
diff --git a/components/segmentation_platform/internal/selection/segment_result_provider.h b/components/segmentation_platform/internal/selection/segment_result_provider.h index fa3bd4b..fb540f8 100644 --- a/components/segmentation_platform/internal/selection/segment_result_provider.h +++ b/components/segmentation_platform/internal/selection/segment_result_provider.h
@@ -20,6 +20,12 @@ class SignalStorageConfig; // Used for retrieving the result of a particular model. +// Supports 3 use cases: +// 1. Fetching cached and valid results from the segment database. +// 2. Fallback to default model when cached results are missing. Executes the +// default model and provides the result. +// 3. Execute the TFLite model and provide the result when `ignore_db_scores` +// is set. class SegmentResultProvider { public: SegmentResultProvider() = default; @@ -35,6 +41,8 @@ kDefaultModelMetadataMissing = 6, kDefaultModelExecutionFailed = 7, kDefaultModelScoreUsed = 8, + kTfliteModelExecutionFailed = 9, + kTfliteModelScoreUsed = 10, }; struct SegmentResult { explicit SegmentResult(ResultState state); @@ -58,10 +66,34 @@ base::Clock* clock, bool force_refresh_results); + // Options for `GetSegmentResult()`. + struct GetResultOptions { + GetResultOptions(); + ~GetResultOptions(); + GetResultOptions& operator=(GetResultOptions&&); + + // The segment ID to fetch result for. + OptimizationTarget segment_id = + OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN; + + // The key is used for recording metrics only. + std::string segmentation_key; + + // Ignores model results stored in database and executes them to fetch + // results. When set to false, the result could be from following: + // * Score cached in the database + // * Execution of default model when score is missing. + // When set to true, the result could be from following: + // * Execution of TFLite model. + // * TODO(ssid): Support fallback to default when model is missing. + bool ignore_db_scores = false; + + // Callback to return the segment result. + SegmentResultCallback callback; + }; + // Returns latest available score for the segment. - virtual void GetSegmentResult(OptimizationTarget segment_id, - const std::string& segmentation_key, - SegmentResultCallback callback) = 0; + virtual void GetSegmentResult(GetResultOptions&& options) = 0; }; } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/selection/segment_result_provider_unittest.cc b/components/segmentation_platform/internal/selection/segment_result_provider_unittest.cc index f0858e9..1355425 100644 --- a/components/segmentation_platform/internal/selection/segment_result_provider_unittest.cc +++ b/components/segmentation_platform/internal/selection/segment_result_provider_unittest.cc
@@ -34,15 +34,15 @@ const OptimizationTarget kTestSegment2 = OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE; -constexpr float kDefaultScore = 0.1; -constexpr float kModelScore = 0.6; -constexpr int kDefaultRank = 0; -constexpr int kModelRank = 1; +constexpr float kTestScore = 0.1; +constexpr float kDatabaseScore = 0.6; +constexpr int kTestRank = 0; +constexpr int kDatabaseRank = 1; -class DefaultProvider : public ModelProvider { +class TestModelProvider : public ModelProvider { public: static constexpr int64_t kVersion = 10; - explicit DefaultProvider(OptimizationTarget segment) + explicit TestModelProvider(OptimizationTarget segment) : ModelProvider(segment) {} void InitAndFetchModel( @@ -54,13 +54,20 @@ void ExecuteModelWithInput(const std::vector<float>& inputs, ExecutionCallback callback) override { - std::move(callback).Run(kDefaultScore); + std::move(callback).Run(kTestScore); } // Returns true if a model is available. bool ModelAvailable() override { return true; } }; +class MockModelExecutionManager : public ModelExecutionManager { + public: + MOCK_METHOD(ModelProvider*, + GetProvider, + (optimization_guide::proto::OptimizationTarget segment_id)); +}; + } // namespace class SegmentResultProviderTest : public testing::Test { @@ -77,10 +84,13 @@ auto query_processor = std::make_unique<processing::MockFeatureListQueryProcessor>(); mock_query_processor_ = query_processor.get(); + auto moved_execution_manager = + std::make_unique<MockModelExecutionManager>(); + mock_execution_manager_ = moved_execution_manager.get(); execution_service_->InitForTesting( std::move(query_processor), std::make_unique<ModelExecutorImpl>(&clock_, mock_query_processor_), - nullptr); + nullptr, std::move(moved_execution_manager)); score_provider_ = SegmentResultProvider::Create( segment_database_.get(), &signal_storage_config_, default_manager_.get(), execution_service_.get(), &clock_, @@ -95,24 +105,28 @@ void ExpectSegmentResultOnGet( OptimizationTarget segment_id, + bool ignore_db_scores, SegmentResultProvider::ResultState expected_state, absl::optional<int> expected_rank) { base::RunLoop wait_for_result; - score_provider_->GetSegmentResult( - segment_id, "test_key", - base::BindOnce( - [](SegmentResultProvider::ResultState expected_state, - absl::optional<int> expected_rank, base::OnceClosure quit, - std::unique_ptr<SegmentResultProvider::SegmentResult> result) { - EXPECT_EQ(result->state, expected_state); - if (expected_rank) { - EXPECT_EQ(*expected_rank, result->rank); - } else { - EXPECT_FALSE(result->rank); - } - std::move(quit).Run(); - }, - expected_state, expected_rank, wait_for_result.QuitClosure())); + SegmentResultProvider::GetResultOptions options; + options.segment_id = segment_id; + options.segmentation_key = "test_key"; + options.ignore_db_scores = ignore_db_scores; + options.callback = base::BindOnce( + [](SegmentResultProvider::ResultState expected_state, + absl::optional<int> expected_rank, base::OnceClosure quit, + std::unique_ptr<SegmentResultProvider::SegmentResult> result) { + EXPECT_EQ(result->state, expected_state); + if (expected_rank) { + EXPECT_EQ(*expected_rank, result->rank); + } else { + EXPECT_FALSE(result->rank); + } + std::move(quit).Run(); + }, + expected_state, expected_rank, wait_for_result.QuitClosure()); + score_provider_->GetSegmentResult(std::move(options)); wait_for_result.Run(); } @@ -140,8 +154,8 @@ // Initialize metadata so that score from default model returns default rank // and score from model score returns model rank. - float mapping[][2] = {{kDefaultScore + 0.1, kDefaultRank}, - {kModelScore - 0.1, kModelRank}}; + float mapping[][2] = {{kTestScore + 0.1, kTestRank}, + {kDatabaseScore - 0.1, kDatabaseRank}}; segment_database_->AddDiscreteMapping(segment_id, mapping, 2, "test_key"); } @@ -152,6 +166,7 @@ TestModelProviderFactory provider_factory_; MockSignalDatabase signal_database_; processing::MockFeatureListQueryProcessor* mock_query_processor_ = nullptr; + MockModelExecutionManager* mock_execution_manager_; SignalHandler signal_handler_; std::unique_ptr<DefaultModelManager> default_manager_; std::unique_ptr<ExecutionService> execution_service_; @@ -163,8 +178,8 @@ TEST_F(SegmentResultProviderTest, GetScoreWithoutInfo) { ExpectSegmentResultOnGet( - kTestSegment, SegmentResultProvider::ResultState::kSegmentNotAvailable, - absl::nullopt); + kTestSegment, /*ignore_db_scores=*/false, + SegmentResultProvider::ResultState::kSegmentNotAvailable, absl::nullopt); } TEST_F(SegmentResultProviderTest, GetScoreFromDbWithoutResult) { @@ -173,7 +188,8 @@ EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_, _)) .WillOnce(Return(true)); ExpectSegmentResultOnGet( - kTestSegment, SegmentResultProvider::ResultState::kDatabaseScoreNotReady, + kTestSegment, /*ignore_db_scores=*/false, + SegmentResultProvider::ResultState::kDatabaseScoreNotReady, absl::nullopt); } @@ -183,25 +199,83 @@ EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_, _)) .WillOnce(Return(false)); ExpectSegmentResultOnGet( - kTestSegment, SegmentResultProvider::ResultState::kSignalsNotCollected, - absl::nullopt); + kTestSegment, /*ignore_db_scores=*/false, + SegmentResultProvider::ResultState::kSignalsNotCollected, absl::nullopt); } TEST_F(SegmentResultProviderTest, GetScoreFromDb) { InitializeMetadata(kTestSegment); - SetSegmentResult(kTestSegment, kModelScore); + SetSegmentResult(kTestSegment, kDatabaseScore); EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_, _)) .WillOnce(Return(true)); ExpectSegmentResultOnGet( - kTestSegment, SegmentResultProvider::ResultState::kSuccessFromDatabase, - kModelRank); + kTestSegment, /*ignore_db_scores=*/false, + SegmentResultProvider::ResultState::kSuccessFromDatabase, kDatabaseRank); +} + +TEST_F(SegmentResultProviderTest, GetFromModelNotEnoughSignals) { + SetSegmentResult(kTestSegment, absl::nullopt); + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_, _)) + .WillOnce(Return(false)); + ExpectSegmentResultOnGet( + kTestSegment, /*ignore_db_scores=*/true, + SegmentResultProvider::ResultState::kSignalsNotCollected, absl::nullopt); +} + +TEST_F(SegmentResultProviderTest, GetFromModelExecutionFailed) { + InitializeMetadata(kTestSegment); + SetSegmentResult(kTestSegment, kDatabaseScore); + + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_, _)) + .Times(2) + .WillRepeatedly(Return(true)); + + // No model available to execute. + EXPECT_CALL(*mock_execution_manager_, GetProvider(kTestSegment)) + .WillOnce(Return(nullptr)); + ExpectSegmentResultOnGet( + kTestSegment, /*ignore_db_scores=*/true, + SegmentResultProvider::ResultState::kTfliteModelExecutionFailed, + absl::nullopt); + + // Feature processing failed. + TestModelProvider provider(kTestSegment); + EXPECT_CALL(*mock_execution_manager_, GetProvider(kTestSegment)) + .WillOnce(Return(&provider)); + EXPECT_CALL(*mock_query_processor_, ProcessFeatureList(_, _, _, _, _)) + .WillOnce(RunOnceCallback<4>(/*error=*/true, std::vector<float>{{1, 2}}, + std::vector<float>())); + ExpectSegmentResultOnGet( + kTestSegment, /*ignore_db_scores=*/true, + SegmentResultProvider::ResultState::kTfliteModelExecutionFailed, + absl::nullopt); +} + +TEST_F(SegmentResultProviderTest, GetFromModel) { + InitializeMetadata(kTestSegment); + SetSegmentResult(kTestSegment, kDatabaseScore); + + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_, _)) + .WillOnce(Return(true)); + + TestModelProvider provider(kTestSegment); + EXPECT_CALL(*mock_execution_manager_, GetProvider(kTestSegment)) + .WillOnce(Return(&provider)); + EXPECT_CALL(*mock_query_processor_, ProcessFeatureList(_, _, _, _, _)) + .WillOnce(RunOnceCallback<4>(/*error=*/false, std::vector<float>{{1, 2}}, + std::vector<float>())); + + // Gets the rank from test model instead of database. + ExpectSegmentResultOnGet( + kTestSegment, /*ignore_db_scores=*/true, + SegmentResultProvider::ResultState::kTfliteModelScoreUsed, kTestRank); } TEST_F(SegmentResultProviderTest, DefaultNeedsSignal) { SetSegmentResult(kTestSegment, absl::nullopt); std::map<OptimizationTarget, std::unique_ptr<ModelProvider>> p; - p.emplace(kTestSegment, std::make_unique<DefaultProvider>(kTestSegment)); + p.emplace(kTestSegment, std::make_unique<TestModelProvider>(kTestSegment)); default_manager_->SetDefaultProvidersForTesting(std::move(p)); // First call is to check opt guide model, and second is to check default @@ -211,6 +285,7 @@ .WillOnce(Return(false)); ExpectSegmentResultOnGet( kTestSegment, + /*ignore_db_scores=*/false, SegmentResultProvider::ResultState::kDefaultModelSignalNotCollected, absl::nullopt); } @@ -218,7 +293,7 @@ TEST_F(SegmentResultProviderTest, DefaultModelFailedExecution) { SetSegmentResult(kTestSegment, absl::nullopt); std::map<OptimizationTarget, std::unique_ptr<ModelProvider>> p; - p.emplace(kTestSegment, std::make_unique<DefaultProvider>(kTestSegment)); + p.emplace(kTestSegment, std::make_unique<TestModelProvider>(kTestSegment)); default_manager_->SetDefaultProvidersForTesting(std::move(p)); EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_, _)) @@ -231,6 +306,7 @@ std::vector<float>())); ExpectSegmentResultOnGet( kTestSegment, + /*ignore_db_scores=*/false, SegmentResultProvider::ResultState::kDefaultModelExecutionFailed, absl::nullopt); } @@ -238,7 +314,7 @@ TEST_F(SegmentResultProviderTest, GetFromDefault) { SetSegmentResult(kTestSegment, absl::nullopt); std::map<OptimizationTarget, std::unique_ptr<ModelProvider>> p; - p.emplace(kTestSegment, std::make_unique<DefaultProvider>(kTestSegment)); + p.emplace(kTestSegment, std::make_unique<TestModelProvider>(kTestSegment)); default_manager_->SetDefaultProvidersForTesting(std::move(p)); EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_, _)) @@ -248,19 +324,19 @@ .WillOnce(RunOnceCallback<4>(/*error=*/false, std::vector<float>{{1, 2}}, std::vector<float>())); ExpectSegmentResultOnGet( - kTestSegment, SegmentResultProvider::ResultState::kDefaultModelScoreUsed, - kDefaultRank); + kTestSegment, /*ignore_db_scores=*/false, + SegmentResultProvider::ResultState::kDefaultModelScoreUsed, kTestRank); } TEST_F(SegmentResultProviderTest, MultipleRequests) { InitializeMetadata(kTestSegment); SetSegmentResult(kTestSegment, absl::nullopt); InitializeMetadata(kTestSegment2); - SetSegmentResult(kTestSegment2, kModelScore); + SetSegmentResult(kTestSegment2, kDatabaseScore); std::map<OptimizationTarget, std::unique_ptr<ModelProvider>> p; - p.emplace(kTestSegment, std::make_unique<DefaultProvider>(kTestSegment)); - p.emplace(kTestSegment2, std::make_unique<DefaultProvider>(kTestSegment2)); + p.emplace(kTestSegment, std::make_unique<TestModelProvider>(kTestSegment)); + p.emplace(kTestSegment2, std::make_unique<TestModelProvider>(kTestSegment2)); default_manager_->SetDefaultProvidersForTesting(std::move(p)); // For the first request, the database does not have valid result, and default @@ -272,8 +348,8 @@ .WillOnce(RunOnceCallback<4>(/*error=*/false, std::vector<float>{{1, 2}}, std::vector<float>())); ExpectSegmentResultOnGet( - kTestSegment, SegmentResultProvider::ResultState::kDefaultModelScoreUsed, - kDefaultRank); + kTestSegment, /*ignore_db_scores=*/false, + SegmentResultProvider::ResultState::kDefaultModelScoreUsed, kTestRank); // For the second request the database has valid result. EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_, _)) @@ -281,8 +357,8 @@ EXPECT_CALL(*mock_query_processor_, ProcessFeatureList(_, _, _, _, _)) .Times(0); ExpectSegmentResultOnGet( - kTestSegment2, SegmentResultProvider::ResultState::kSuccessFromDatabase, - kModelRank); + kTestSegment2, /*ignore_db_scores=*/false, + SegmentResultProvider::ResultState::kSuccessFromDatabase, kDatabaseRank); } } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/selection/segment_score_provider.cc b/components/segmentation_platform/internal/selection/segment_score_provider.cc index eda9084b..6c05a9bc 100644 --- a/components/segmentation_platform/internal/selection/segment_score_provider.cc +++ b/components/segmentation_platform/internal/selection/segment_score_provider.cc
@@ -8,8 +8,8 @@ #include "base/memory/raw_ptr.h" #include "base/threading/thread_task_runner_handle.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" #include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
diff --git a/components/segmentation_platform/internal/selection/segment_selector.h b/components/segmentation_platform/internal/selection/segment_selector.h index eebbc0491..9b426e6b 100644 --- a/components/segmentation_platform/internal/selection/segment_selector.h +++ b/components/segmentation_platform/internal/selection/segment_selector.h
@@ -36,6 +36,11 @@ // asynchronously. If none, returns empty result. virtual void GetSelectedSegment(SegmentSelectionCallback callback) = 0; + // Client API. Runs models and selects a segment on demand. Returns empty + // result on failure. + virtual void GetSelectedSegmentOnDemand( + SegmentSelectionCallback callback) = 0; + // Client API. Returns the cached selected segment from the last session // synchronously. virtual SegmentSelectionResult GetCachedSegmentResult() = 0;
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.cc b/components/segmentation_platform/internal/selection/segment_selector_impl.cc index 28a01530..a3b584d5 100644 --- a/components/segmentation_platform/internal/selection/segment_selector_impl.cc +++ b/components/segmentation_platform/internal/selection/segment_selector_impl.cc
@@ -13,9 +13,9 @@ #include "base/time/clock.h" #include "base/time/time.h" #include "components/segmentation_platform/internal/constants.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" #include "components/segmentation_platform/internal/database/signal_storage_config.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/metric_filter_utils.h" #include "components/segmentation_platform/internal/platform_options.h" #include "components/segmentation_platform/internal/proto/model_metadata.pb.h" @@ -37,6 +37,7 @@ case SegmentResultProvider::ResultState::kUnknown: case SegmentResultProvider::ResultState::kSuccessFromDatabase: case SegmentResultProvider::ResultState::kDefaultModelScoreUsed: + case SegmentResultProvider::ResultState::kTfliteModelScoreUsed: NOTREACHED(); return stats::SegmentationSelectionFailureReason::kMaxValue; case SegmentResultProvider::ResultState::kDatabaseScoreNotReady: @@ -57,6 +58,9 @@ case SegmentResultProvider::ResultState::kDefaultModelExecutionFailed: return stats::SegmentationSelectionFailureReason:: kAtLeastOneSegmentDefaultExecFailed; + case SegmentResultProvider::ResultState::kTfliteModelExecutionFailed: + return stats::SegmentationSelectionFailureReason:: + kAtLeastOneSegmentTfliteExecFailed; } } @@ -136,7 +140,7 @@ segment_database_, signal_storage_config_, default_model_manager_, execution_service, clock_, platform_options_.force_refresh_results); if (IsPreviousSelectionInvalid()) { - GetRankForNextSegment(std::make_unique<SegmentRanks>()); + SelectSegmentAndStoreToPrefs(); } // If the segment selection is ready, also record the subsegment for all the @@ -164,6 +168,12 @@ return selected_segment_last_session_; } +void SegmentSelectorImpl::GetSelectedSegmentOnDemand( + SegmentSelectionCallback callback) { + DCHECK(config_->on_demand_execution); + GetRankForNextSegment(std::make_unique<SegmentRanks>(), std::move(callback)); +} + void SegmentSelectorImpl::OnModelExecutionCompleted( OptimizationTarget segment_id) { DCHECK(segment_result_provider_); @@ -175,7 +185,7 @@ if (!IsPreviousSelectionInvalid()) return; - GetRankForNextSegment(std::make_unique<SegmentRanks>()); + SelectSegmentAndStoreToPrefs(); } bool SegmentSelectorImpl::IsPreviousSelectionInvalid() { @@ -203,24 +213,50 @@ return true; } +void SegmentSelectorImpl::SelectSegmentAndStoreToPrefs() { + if (config_->on_demand_execution) { + return; + } + GetRankForNextSegment(std::make_unique<SegmentRanks>(), + SegmentSelectionCallback()); +} + void SegmentSelectorImpl::GetRankForNextSegment( - std::unique_ptr<SegmentRanks> ranks) { + std::unique_ptr<SegmentRanks> ranks, + SegmentSelectionCallback callback) { for (OptimizationTarget needed_segment : config_->segment_ids) { if (ranks->count(needed_segment) == 0) { - segment_result_provider_->GetSegmentResult( - needed_segment, config_->segmentation_key, + SegmentResultProvider::GetResultOptions options; + options.segment_id = needed_segment; + options.segmentation_key = config_->segmentation_key; + options.ignore_db_scores = config_->on_demand_execution; + options.callback = base::BindOnce(&SegmentSelectorImpl::OnGetResultForSegmentSelection, weak_ptr_factory_.GetWeakPtr(), std::move(ranks), - needed_segment)); + std::move(callback), needed_segment); + + segment_result_provider_->GetSegmentResult(std::move(options)); return; } } + + // Finished fetching ranks for all segments. OptimizationTarget selected_segment = FindBestSegment(*ranks); - UpdateSelectedSegment(selected_segment); + if (config_->on_demand_execution) { + DCHECK(!callback.is_null()); + SegmentSelectionResult result; + result.is_ready = true; + result.segment = selected_segment; + std::move(callback).Run(result); + } else { + DCHECK(callback.is_null()); + UpdateSelectedSegment(selected_segment); + } } void SegmentSelectorImpl::OnGetResultForSegmentSelection( std::unique_ptr<SegmentRanks> ranks, + SegmentSelectionCallback callback, OptimizationTarget current_segment_id, std::unique_ptr<SegmentResultProvider::SegmentResult> result) { if (!result->rank) { @@ -230,7 +266,7 @@ } ranks->insert(std::make_pair(current_segment_id, *result->rank)); - GetRankForNextSegment(std::move(ranks)); + GetRankForNextSegment(std::move(ranks), std::move(callback)); } OptimizationTarget SegmentSelectorImpl::FindBestSegment(
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.h b/components/segmentation_platform/internal/selection/segment_selector_impl.h index ce1ab1e..003d26d 100644 --- a/components/segmentation_platform/internal/selection/segment_selector_impl.h +++ b/components/segmentation_platform/internal/selection/segment_selector_impl.h
@@ -56,6 +56,7 @@ void OnPlatformInitialized(ExecutionService* execution_service) override; void GetSelectedSegment(SegmentSelectionCallback callback) override; SegmentSelectionResult GetCachedSegmentResult() override; + void GetSelectedSegmentOnDemand(SegmentSelectionCallback callback) override; // Helper function to update the selected segment in the prefs. Auto-extends // the selection if the new result is unknown. @@ -65,6 +66,11 @@ // best segment, and writes it to the pref. void OnModelExecutionCompleted(OptimizationTarget segment_id) override; + void set_segment_result_provider_for_testing( + std::unique_ptr<SegmentResultProvider> result_provider) { + segment_result_provider_ = std::move(result_provider); + } + private: // For testing. friend class SegmentSelectorTest; @@ -75,13 +81,19 @@ // segment selection TTL has expired, or selection is unavailable. bool IsPreviousSelectionInvalid(); + // Gets scores for all segments and recomputes selection and stores the result + // to prefs. + void SelectSegmentAndStoreToPrefs(); + // Gets ranks for each segment from SegmentResultProvider, and then computes // segment selection. - void GetRankForNextSegment(std::unique_ptr<SegmentRanks> ranks); + void GetRankForNextSegment(std::unique_ptr<SegmentRanks> ranks, + SegmentSelectionCallback callback); // Callback used to get result from SegmentResultProvider for each segment. void OnGetResultForSegmentSelection( std::unique_ptr<SegmentRanks> ranks, + SegmentSelectionCallback callback, OptimizationTarget current_segment_id, std::unique_ptr<SegmentResultProvider::SegmentResult> result);
diff --git a/components/segmentation_platform/internal/selection/segment_selector_unittest.cc b/components/segmentation_platform/internal/selection/segment_selector_unittest.cc index 1a8e4df..be23e38 100644 --- a/components/segmentation_platform/internal/selection/segment_selector_unittest.cc +++ b/components/segmentation_platform/internal/selection/segment_selector_unittest.cc
@@ -8,12 +8,12 @@ #include "base/test/simple_test_clock.h" #include "base/test/task_environment.h" #include "components/segmentation_platform/internal/constants.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/mock_signal_storage_config.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" #include "components/segmentation_platform/internal/database/test_segment_info_database.h" #include "components/segmentation_platform/internal/execution/default_model_manager.h" #include "components/segmentation_platform/internal/execution/mock_model_provider.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/metric_filter_utils.h" #include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h" #include "components/segmentation_platform/public/config.h" @@ -56,6 +56,11 @@ return config; } +class MockResultProvider : public SegmentResultProvider { + public: + MOCK_METHOD1(GetSegmentResult, void(GetResultOptions&& options)); +}; + } // namespace class TestSegmentationResultPrefs : public SegmentationResultPrefs { @@ -169,6 +174,51 @@ ASSERT_EQ(segment_id2, prefs_->selection->segment_id); } +TEST_F(SegmentSelectorTest, RunSelectionOnDemand) { + Config config = CreateTestConfig(); + config.on_demand_execution = true; + SetUpWithConfig(config); + EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_, _)) + .WillRepeatedly(Return(true)); + + static constexpr OptimizationTarget kSegmentId = + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; + float mapping[][2] = {{0.2, 1}, {0.5, 3}, {0.7, 4}}; + InitializeMetadataForSegment(kSegmentId, mapping, 3); + + static constexpr OptimizationTarget kSegmentId2 = + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE; + float mapping2[][2] = {{0.3, 1}, {0.4, 4}}; + InitializeMetadataForSegment(kSegmentId2, mapping2, 2); + + auto result_provider = std::make_unique<MockResultProvider>(); + EXPECT_CALL(*result_provider, GetSegmentResult(_)) + .Times(2) + .WillRepeatedly( + Invoke([](SegmentResultProvider::GetResultOptions&& options) { + EXPECT_TRUE(options.ignore_db_scores); + int rank = options.segment_id == kSegmentId ? 3 : 4; + auto result = + std::make_unique<SegmentResultProvider::SegmentResult>( + SegmentResultProvider::ResultState::kTfliteModelScoreUsed, + rank); + std::move(options.callback).Run(std::move(result)); + })); + segment_selector_->set_segment_result_provider_for_testing( + std::move(result_provider)); + + clock_.Advance(base::Days(1)); + base::RunLoop wait_for_selection; + segment_selector_->GetSelectedSegmentOnDemand(base::BindOnce( + [](base::OnceClosure quit, const SegmentSelectionResult& result) { + EXPECT_TRUE(result.is_ready); + EXPECT_EQ(kSegmentId2, result.segment); + std::move(quit).Run(); + }, + wait_for_selection.QuitClosure())); + wait_for_selection.Run(); +} + TEST_F(SegmentSelectorTest, NewSegmentResultOverridesThePreviousBest) { Config config = CreateTestConfig(); config.unknown_selection_ttl = base::TimeDelta();
diff --git a/components/segmentation_platform/internal/service_proxy_impl.cc b/components/segmentation_platform/internal/service_proxy_impl.cc index ae6d0470..4aab9ffc 100644 --- a/components/segmentation_platform/internal/service_proxy_impl.cc +++ b/components/segmentation_platform/internal/service_proxy_impl.cc
@@ -11,8 +11,8 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/signal_storage_config.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/scheduler/execution_service.h" #include "components/segmentation_platform/internal/segmentation_platform_service_impl.h" #include "components/segmentation_platform/internal/selection/segment_selector_impl.h"
diff --git a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc index 18f3e3d..9e2aeb6e 100644 --- a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc +++ b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
@@ -204,7 +204,8 @@ auto scheduler_moved = std::make_unique<MockModelExecutionScheduler>(); MockModelExecutionScheduler* scheduler = scheduler_moved.get(); ExecutionService execution; - execution.InitForTesting(nullptr, nullptr, std::move(scheduler_moved)); + execution.InitForTesting(nullptr, nullptr, std::move(scheduler_moved), + nullptr); // Scheduler is not set, ExecuteModel() will do nothing. EXPECT_CALL(*scheduler, RequestModelExecution(_)).Times(0); @@ -241,7 +242,8 @@ auto scheduler_moved = std::make_unique<MockModelExecutionScheduler>(); MockModelExecutionScheduler* scheduler = scheduler_moved.get(); ExecutionService execution; - execution.InitForTesting(nullptr, nullptr, std::move(scheduler_moved)); + execution.InitForTesting(nullptr, nullptr, std::move(scheduler_moved), + nullptr); // Scheduler is not set, OverwriteValue() will do nothing. EXPECT_CALL(*scheduler, OnModelExecutionCompleted(_, _)).Times(0);
diff --git a/components/segmentation_platform/internal/signals/signal_filter_processor.cc b/components/segmentation_platform/internal/signals/signal_filter_processor.cc index a7cc4cfa..6ddb2c36 100644 --- a/components/segmentation_platform/internal/signals/signal_filter_processor.cc +++ b/components/segmentation_platform/internal/signals/signal_filter_processor.cc
@@ -7,11 +7,11 @@ #include <set> #include "base/logging.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" #include "components/segmentation_platform/internal/database/signal_storage_config.h" #include "components/segmentation_platform/internal/database/storage_service.h" #include "components/segmentation_platform/internal/execution/default_model_manager.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/model_prediction.pb.h" #include "components/segmentation_platform/internal/proto/types.pb.h" #include "components/segmentation_platform/internal/signals/histogram_signal_handler.h"
diff --git a/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc b/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc index d157db8..d895da33 100644 --- a/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc +++ b/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc
@@ -35,11 +35,11 @@ namespace segmentation_platform { namespace { -UkmEventHash TestEvent(uint64_t val) { +constexpr UkmEventHash TestEvent(uint64_t val) { return UkmEventHash::FromUnsafeValue(val); } -UkmMetricHash TestMetric(uint64_t val) { +constexpr UkmMetricHash TestMetric(uint64_t val) { return UkmMetricHash::FromUnsafeValue(val); } @@ -197,6 +197,33 @@ TEST_F(SignalFilterProcessorTest, UkmMetricsConfig) { const OptimizationTarget kSegmentId = OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; + const UkmEventHash kEvent1 = TestEvent(10); + const UkmEventHash kEvent2 = TestEvent(11); + const std::array<UkmMetricHash, 3> kMetrics1_1{ + TestMetric(100), TestMetric(101), TestMetric(102)}; + const std::array<UkmMetricHash, 3> kMetrics1_2{ + TestMetric(100), TestMetric(104), TestMetric(105)}; + const std::array<UkmMetricHash, 3> kMetrics2{TestMetric(103), TestMetric(104), + TestMetric(105)}; + const std::array<MetadataWriter::SqlFeature::EventAndMetrics, 2> kConfig1{ + MetadataWriter::SqlFeature::EventAndMetrics{ + .event_hash = kEvent1, + .metrics = kMetrics1_1.data(), + .metrics_size = kMetrics1_1.size()}, + MetadataWriter::SqlFeature::EventAndMetrics{ + .event_hash = kEvent2, + .metrics = kMetrics2.data(), + .metrics_size = kMetrics2.size()}}; + const std::array<MetadataWriter::SqlFeature::EventAndMetrics, 1> kConfig2{ + MetadataWriter::SqlFeature::EventAndMetrics{ + .event_hash = kEvent1, + .metrics = kMetrics1_2.data(), + .metrics_size = kMetrics1_2.size()}}; + MetadataWriter::SqlFeature feature1{ + .sql = "", .events = kConfig1.data(), .events_size = kConfig1.size()}; + MetadataWriter::SqlFeature feature2{ + .sql = "", .events = kConfig2.data(), .events_size = kConfig2.size()}; + EXPECT_CALL(*histogram_signal_handler_, SetRelevantHistograms( std::set<std::pair<std::string, proto::SignalType>>())) @@ -214,15 +241,16 @@ signal_filter_processor_->OnSignalListUpdated(); UkmConfig config1; - config1.AddEvent(TestEvent(10), - {TestMetric(100), TestMetric(101), TestMetric(102)}); - config1.AddEvent(TestEvent(11), - {TestMetric(103), TestMetric(104), TestMetric(105)}); - segment_database_->AddSqlFeature(kSegmentId, "", config1); + config1.AddEvent(kEvent1, base::flat_set<UkmMetricHash>(kMetrics1_1.begin(), + kMetrics1_1.end())); + config1.AddEvent(kEvent2, base::flat_set<UkmMetricHash>(kMetrics2.begin(), + kMetrics2.end())); + segment_database_->AddSqlFeature(kSegmentId, feature1); + UkmConfig config2; - config2.AddEvent(TestEvent(10), - {TestMetric(100), TestMetric(104), TestMetric(105)}); - segment_database_->AddSqlFeature(kSegmentId, "", config2); + config2.AddEvent(kEvent1, base::flat_set<UkmMetricHash>(kMetrics1_2.begin(), + kMetrics1_2.end())); + segment_database_->AddSqlFeature(kSegmentId, feature2); config2.Merge(config1);
diff --git a/components/segmentation_platform/internal/stats.h b/components/segmentation_platform/internal/stats.h index 6e482a47..3a468da 100644 --- a/components/segmentation_platform/internal/stats.h +++ b/components/segmentation_platform/internal/stats.h
@@ -6,8 +6,8 @@ #define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_STATS_H_ #include "components/optimization_guide/proto/models.pb.h" -#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/execution/model_execution_status.h" +#include "components/segmentation_platform/internal/metadata/metadata_utils.h" #include "components/segmentation_platform/internal/proto/types.pb.h" #include "components/segmentation_platform/public/segment_selection_result.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -170,7 +170,8 @@ kAtLeastOneSegmentDefaultSignalNotCollected = 12, kAtLeastOneSegmentDefaultExecFailed = 13, kAtLeastOneSegmentDefaultMissingMetadata = 14, - kMaxValue = kAtLeastOneSegmentDefaultMissingMetadata + kAtLeastOneSegmentTfliteExecFailed = 15, + kMaxValue = kAtLeastOneSegmentTfliteExecFailed }; // Records the reason for failure or success to compute a segment selection.
diff --git a/components/segmentation_platform/public/config.h b/components/segmentation_platform/public/config.h index 8d649bf8..79a58bc4 100644 --- a/components/segmentation_platform/public/config.h +++ b/components/segmentation_platform/public/config.h
@@ -70,6 +70,11 @@ // List of segment ids that the current config requires to be available. std::vector<optimization_guide::proto::OptimizationTarget> segment_ids; + + // The selection only supports returning results from on-demand model + // executions instead of returning result from previous sessions. The + // selection TTLs are ignored in this config. + bool on_demand_execution = false; }; } // namespace segmentation_platform
diff --git a/components/shared_highlighting/core/common/shared_highlighting_features.cc b/components/shared_highlighting/core/common/shared_highlighting_features.cc index a46aced..0eaa4f4 100644 --- a/components/shared_highlighting/core/common/shared_highlighting_features.cc +++ b/components/shared_highlighting/core/common/shared_highlighting_features.cc
@@ -29,6 +29,17 @@ const base::Feature kSharedHighlightingRefinedBlocklist{ "SharedHighlightingRefinedBlocklist", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kSharedHighlightingRefinedMaxContextWords{ + "SharedHighlightingRefinedMaxContextWords", + base::FEATURE_DISABLED_BY_DEFAULT}; + +const char kSharedHighlightingRefinedMaxContextWordsName[] = + "SharedHighlightingRefinedMaxContextWords"; + +const base::FeatureParam<int> kSharedHighlightingMaxContextWords{ + &kSharedHighlightingRefinedMaxContextWords, + kSharedHighlightingRefinedMaxContextWordsName, 10}; + int GetPreemptiveLinkGenTimeoutLengthMs() { return kPreemptiveLinkGenTimeoutLengthMs.Get(); }
diff --git a/components/shared_highlighting/core/common/shared_highlighting_features.h b/components/shared_highlighting/core/common/shared_highlighting_features.h index fbaf89be..9ed78fee 100644 --- a/components/shared_highlighting/core/common/shared_highlighting_features.h +++ b/components/shared_highlighting/core/common/shared_highlighting_features.h
@@ -27,6 +27,12 @@ // Feature flag that enables a narrower blocklist. extern const base::Feature kSharedHighlightingRefinedBlocklist; +// Feature flag that allows to experiment with different Max Context Words. +extern const base::Feature kSharedHighlightingRefinedMaxContextWords; +// Feature name and parameter to capture the different maxContextWords values. +extern const char kSharedHighlightingRefinedMaxContextWordsName[]; +extern const base::FeatureParam<int> kSharedHighlightingMaxContextWords; + // Returns the pre-emptive link generation timeout length. int GetPreemptiveLinkGenTimeoutLengthMs();
diff --git a/components/user_education/views/help_bubble_delegate.h b/components/user_education/views/help_bubble_delegate.h index abe4dd7..d417282 100644 --- a/components/user_education/views/help_bubble_delegate.h +++ b/components/user_education/views/help_bubble_delegate.h
@@ -40,13 +40,12 @@ // These methods return color codes that will be handled by the app's theming // system. - virtual int GetHelpBubbleBackgroundColor() const = 0; - virtual int GetHelpBubbleForegroundColor() const = 0; - virtual int GetHelpBubbleDefaultButtonBackgroundColor() const = 0; - virtual int GetHelpBubbleDefaultButtonForegroundColor() const = 0; - virtual int GetHelpBubbleButtonBorderColor() const = 0; - virtual int GetHelpBubbleCloseButtonInkDropColor() const = 0; virtual ui::ColorId GetHelpBubbleBackgroundColorId() const = 0; + virtual ui::ColorId GetHelpBubbleForegroundColorId() const = 0; + virtual ui::ColorId GetHelpBubbleDefaultButtonBackgroundColorId() const = 0; + virtual ui::ColorId GetHelpBubbleDefaultButtonForegroundColorId() const = 0; + virtual ui::ColorId GetHelpBubbleButtonBorderColorId() const = 0; + virtual ui::ColorId GetHelpBubbleCloseButtonInkDropColorId() const = 0; }; } // namespace user_education
diff --git a/components/user_education/views/help_bubble_view.cc b/components/user_education/views/help_bubble_view.cc index ce457631..bea56fab 100644 --- a/components/user_education/views/help_bubble_view.cc +++ b/components/user_education/views/help_bubble_view.cc
@@ -26,7 +26,7 @@ #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/models/image_model.h" -#include "ui/base/theme_provider.h" +#include "ui/color/color_provider.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/geometry/insets.h" @@ -136,21 +136,21 @@ // Prominent MD button does not have a border. // Override this method to draw a border. // Adapted from MdTextButton::UpdateBackgroundColor() - const auto* theme_provider = GetThemeProvider(); - if (!theme_provider) + const auto* color_provider = GetColorProvider(); + if (!color_provider) return; - SkColor background_color = theme_provider->GetColor( + SkColor background_color = color_provider->GetColor( is_default_button_ - ? delegate_->GetHelpBubbleDefaultButtonBackgroundColor() - : delegate_->GetHelpBubbleBackgroundColor()); + ? delegate_->GetHelpBubbleDefaultButtonBackgroundColorId() + : delegate_->GetHelpBubbleBackgroundColorId()); if (GetState() == STATE_PRESSED) { background_color = GetNativeTheme()->GetSystemButtonPressedColor(background_color); } - const SkColor stroke_color = theme_provider->GetColor( + const SkColor stroke_color = color_provider->GetColor( is_default_button_ - ? delegate_->GetHelpBubbleDefaultButtonBackgroundColor() - : delegate_->GetHelpBubbleButtonBorderColor()); + ? delegate_->GetHelpBubbleDefaultButtonBackgroundColorId() + : delegate_->GetHelpBubbleButtonBorderColorId()); SetBackground(CreateBackgroundFromPainter( views::Painter::CreateRoundRectWith1PxBorderPainter( background_color, stroke_color, GetCornerRadius()))); @@ -159,15 +159,15 @@ void OnThemeChanged() override { views::MdTextButton::OnThemeChanged(); - const auto* theme_provider = GetThemeProvider(); + const auto* color_provider = GetColorProvider(); const SkColor background_color = - theme_provider->GetColor(delegate_->GetHelpBubbleBackgroundColor()); + color_provider->GetColor(delegate_->GetHelpBubbleBackgroundColorId()); views::FocusRing::Get(this)->SetColor(background_color); - const SkColor foreground_color = theme_provider->GetColor( + const SkColor foreground_color = color_provider->GetColor( is_default_button_ - ? delegate_->GetHelpBubbleDefaultButtonForegroundColor() - : delegate_->GetHelpBubbleForegroundColor()); + ? delegate_->GetHelpBubbleDefaultButtonForegroundColorId() + : delegate_->GetHelpBubbleForegroundColorId()); SetEnabledTextColors(foreground_color); // TODO(crbug/1112244): Temporary fix for Mac. Bubble shouldn't be in @@ -199,25 +199,25 @@ this, std::make_unique<views::CircleHighlightPathGenerator>(gfx::Insets())); SetAccessibleName(accessible_name); + + constexpr int kIconSize = 16; + SetImageModel(views::ImageButton::STATE_NORMAL, + ui::ImageModel::FromVectorIcon( + views::kIcCloseIcon, + delegate_->GetHelpBubbleForegroundColorId(), kIconSize)); + + constexpr float kCloseButtonFocusRingHaloThickness = 1.25f; + views::FocusRing::Get(this)->SetHaloThickness( + kCloseButtonFocusRingHaloThickness); } void OnThemeChanged() override { views::ImageButton::OnThemeChanged(); - - constexpr float kCloseButtonFocusRingHaloThickness = 1.25f; - - const auto* theme_provider = GetThemeProvider(); - SetImage( - views::ImageButton::STATE_NORMAL, - gfx::CreateVectorIcon(views::kIcCloseIcon, 16, - theme_provider->GetColor( - delegate_->GetHelpBubbleForegroundColor()))); - views::InkDrop::Get(this)->SetBaseColor(theme_provider->GetColor( - delegate_->GetHelpBubbleCloseButtonInkDropColor())); + const auto* color_provider = GetColorProvider(); + views::InkDrop::Get(this)->SetBaseColor(color_provider->GetColor( + delegate_->GetHelpBubbleCloseButtonInkDropColorId())); views::FocusRing::Get(this)->SetColor( - theme_provider->GetColor(delegate_->GetHelpBubbleForegroundColor())); - views::FocusRing::Get(this)->SetHaloThickness( - kCloseButtonFocusRingHaloThickness); + color_provider->GetColor(delegate_->GetHelpBubbleForegroundColorId())); } private: @@ -253,8 +253,8 @@ const gfx::PointF center_point = local_bounds.CenterPoint(); const float radius = (size_.width() - kStrokeWidth) / 2.0f; - const SkColor color = - GetThemeProvider()->GetColor(delegate_->GetHelpBubbleForegroundColor()); + const SkColor color = GetColorProvider()->GetColor( + delegate_->GetHelpBubbleForegroundColorId()); if (should_fill_) { cc::PaintFlags fill_flags; fill_flags.setStyle(cc::PaintFlags::kFill_Style); @@ -655,13 +655,13 @@ void HelpBubbleView::OnThemeChanged() { views::BubbleDialogDelegateView::OnThemeChanged(); - const auto* theme_provider = GetThemeProvider(); + const auto* color_provider = GetColorProvider(); const SkColor background_color = - theme_provider->GetColor(delegate_->GetHelpBubbleBackgroundColor()); + color_provider->GetColor(delegate_->GetHelpBubbleBackgroundColorId()); set_color(background_color); const SkColor foreground_color = - theme_provider->GetColor(delegate_->GetHelpBubbleForegroundColor()); + color_provider->GetColor(delegate_->GetHelpBubbleForegroundColorId()); if (icon_view_) { icon_view_->SetBackground(views::CreateRoundedRectBackground( foreground_color, icon_view_->GetPreferredSize().height() / 2));
diff --git a/components/user_education/views/help_bubble_view_unittest.cc b/components/user_education/views/help_bubble_view_unittest.cc index 12df66c..8ed909a 100644 --- a/components/user_education/views/help_bubble_view_unittest.cc +++ b/components/user_education/views/help_bubble_view_unittest.cc
@@ -50,13 +50,18 @@ // These methods return color codes that will be handled by the app's theming // system. - int GetHelpBubbleBackgroundColor() const override { return 0; } - int GetHelpBubbleForegroundColor() const override { return 0; } - int GetHelpBubbleDefaultButtonBackgroundColor() const override { return 0; } - int GetHelpBubbleDefaultButtonForegroundColor() const override { return 0; } - int GetHelpBubbleButtonBorderColor() const override { return 0; } - int GetHelpBubbleCloseButtonInkDropColor() const override { return 0; } ui::ColorId GetHelpBubbleBackgroundColorId() const override { return 0; } + ui::ColorId GetHelpBubbleForegroundColorId() const override { return 0; } + ui::ColorId GetHelpBubbleDefaultButtonBackgroundColorId() const override { + return 0; + } + ui::ColorId GetHelpBubbleDefaultButtonForegroundColorId() const override { + return 0; + } + ui::ColorId GetHelpBubbleButtonBorderColorId() const override { return 0; } + ui::ColorId GetHelpBubbleCloseButtonInkDropColorId() const override { + return 0; + } }; // Fake theme provider. There's a similar TestThemeProvider in chrome/test but
diff --git a/components/viz/service/display/overlay_processor_ozone.cc b/components/viz/service/display/overlay_processor_ozone.cc index 828be28..1c83da9 100644 --- a/components/viz/service/display/overlay_processor_ozone.cc +++ b/components/viz/service/display/overlay_processor_ozone.cc
@@ -71,13 +71,6 @@ (mailbox.name[2] << 8) + mailbox.name[3]; } -void ReportSharedImageExists(bool exists) { - UMA_HISTOGRAM_BOOLEAN( - "Compositing.Display.OverlayProcessorOzone." - "SharedImageExists", - exists); -} - #if BUILDFLAG(IS_CHROMEOS_ASH) bool AllowColorSpaceCombination( const gfx::ColorSpace& source_color_space, @@ -305,11 +298,6 @@ bool is_primary) { DCHECK(shared_image_interface_); - UMA_HISTOGRAM_BOOLEAN( - "Compositing.Display.OverlayProcessorOzone." - "IsCandidateSharedImage", - mailbox.IsSharedImage()); - if (!mailbox.IsSharedImage()) return false; @@ -323,10 +311,8 @@ // candidate. We will try again next frame. DLOG(ERROR) << "Unable to find the NativePixmap corresponding to the " "overlay candidate"; - ReportSharedImageExists(false); return false; } - ReportSharedImageExists(true); if (is_primary && (candidate->buffer_size != native_pixmap->GetBufferSize() || candidate->format != native_pixmap->GetBufferFormat())) {
diff --git a/content/BUILD.gn b/content/BUILD.gn index e0b59ac..8e616f8 100644 --- a/content/BUILD.gn +++ b/content/BUILD.gn
@@ -116,6 +116,7 @@ "//content/browser/prerender:mojo_bindings_webui_js", "//content/browser/process_internals:mojo_bindings_webui_js", "//content/browser/resources/attribution_reporting:build_ts", + "//content/browser/resources/gpu:web_components", "//storage/browser/quota:mojo_bindings_webui_js", ] }
diff --git a/content/browser/gpu/gpu_internals_ui.cc b/content/browser/gpu/gpu_internals_ui.cc index 489f429..a07be30a 100644 --- a/content/browser/gpu/gpu_internals_ui.cc +++ b/content/browser/gpu/gpu_internals_ui.cc
@@ -74,15 +74,19 @@ WebUIDataSource* source = WebUIDataSource::Create(kChromeUIGpuHost); source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::ScriptSrc, - "script-src chrome://resources 'self' 'unsafe-eval';"); + "script-src chrome://resources 'self';"); source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::TrustedTypes, - "trusted-types jstemplate;"); + "trusted-types static-types;"); source->UseStringsJs(); source->AddResourcePath("browser_bridge.js", IDR_GPU_BROWSER_BRIDGE_JS); source->AddResourcePath("gpu_internals.js", IDR_GPU_INTERNALS_JS); - source->AddResourcePath("info_view.js", IDR_GPU_INFO_VIEW_JS); + source->AddResourcePath("info_view.js", IDR_GPU_INTERNALS_INFO_VIEW_JS); + source->AddResourcePath("info_view_table.js", + IDR_GPU_INTERNALS_INFO_VIEW_TABLE_JS); + source->AddResourcePath("info_view_table_row.js", + IDR_GPU_INTERNALS_INFO_VIEW_TABLE_ROW_JS); source->AddResourcePath("vulkan_info.js", IDR_GPU_VULKAN_INFO_JS); source->AddResourcePath("vulkan_info.mojom-webui.js", IDR_VULKAN_INFO_MOJO_JS);
diff --git a/content/browser/interest_group/auction_runner_unittest.cc b/content/browser/interest_group/auction_runner_unittest.cc index e484380..a83340a 100644 --- a/content/browser/interest_group/auction_runner_unittest.cc +++ b/content/browser/interest_group/auction_runner_unittest.cc
@@ -2517,17 +2517,17 @@ TestDevToolsAgentClient::Event breakpoint_hit = debug.WaitForMethodNotification("Debugger.paused"); - base::Value* hit_breakpoints = - breakpoint_hit.value.FindListPath("params.hitBreakpoints"); + ASSERT_TRUE(breakpoint_hit.value.is_dict()); + base::Value::List* hit_breakpoints = + breakpoint_hit.value.GetDict().FindListByDottedPath( + "params.hitBreakpoints"); ASSERT_TRUE(hit_breakpoints); - base::Value::ConstListView hit_breakpoints_list = - hit_breakpoints->GetListDeprecated(); // This is LE and not EQ to work around // https://bugs.chromium.org/p/v8/issues/detail?id=12586 - ASSERT_LE(1u, hit_breakpoints_list.size()); - ASSERT_TRUE(hit_breakpoints_list[0].is_string()); + ASSERT_LE(1u, hit_breakpoints->size()); + ASSERT_TRUE((*hit_breakpoints)[0].is_string()); EXPECT_EQ(base::StringPrintf("1:11:0:%s", debug_url.spec().c_str()), - hit_breakpoints_list[0].GetString()); + (*hit_breakpoints)[0].GetString()); // Just resume execution. debug.RunCommandAndWaitForResult(
diff --git a/content/browser/interest_group/interest_group_storage.cc b/content/browser/interest_group/interest_group_storage.cc index c87fb52..31e81717 100644 --- a/content/browser/interest_group/interest_group_storage.cc +++ b/content/browser/interest_group/interest_group_storage.cc
@@ -120,18 +120,20 @@ } base::Value ToValue(const blink::InterestGroup::Ad& ad) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("url", ad.render_url.spec()); + base::Value value(base::Value::Type::DICTIONARY); + base::Value::Dict& dict = value.GetDict(); + dict.Set("url", ad.render_url.spec()); if (ad.metadata) - dict.SetStringKey("metadata", ad.metadata.value()); - return dict; + dict.Set("metadata", ad.metadata.value()); + return value; } -blink::InterestGroup::Ad FromInterestGroupAdValue(const base::Value* value) { +blink::InterestGroup::Ad FromInterestGroupAdValue( + const base::Value::Dict& dict) { blink::InterestGroup::Ad result; - const std::string* maybe_url = value->FindStringKey("url"); + const std::string* maybe_url = dict.FindString("url"); if (maybe_url) result.render_url = GURL(*maybe_url); - const std::string* maybe_metadata = value->FindStringKey("metadata"); + const std::string* maybe_metadata = dict.FindString("metadata"); if (maybe_metadata) result.metadata = *maybe_metadata; return result; @@ -153,8 +155,10 @@ if (!ads_value || !ads_value->is_list()) return absl::nullopt; std::vector<blink::InterestGroup::Ad> result; - for (const auto& ad_value : ads_value->GetListDeprecated()) { - result.emplace_back(FromInterestGroupAdValue(&ad_value)); + for (const auto& ad_value : ads_value->GetList()) { + const base::Value::Dict* dict = ad_value.GetIfDict(); + if (dict) + result.emplace_back(FromInterestGroupAdValue(*dict)); } return result; }
diff --git a/content/browser/interest_group/interest_group_update_manager.cc b/content/browser/interest_group/interest_group_update_manager.cc index c285354..327866f 100644 --- a/content/browser/interest_group/interest_group_update_manager.cc +++ b/content/browser/interest_group/interest_group_update_manager.cc
@@ -79,16 +79,17 @@ // TODO(crbug.com/1186444): Report errors to devtools for the TryToCopy*(). // functions. -// Name and owner are optional in `value` (parsed server JSON response), but +// Name and owner are optional in `dict` (parsed server JSON response), but // must match `name` and `owner`, respectively, if either is specified. Returns // true if the check passes, and false otherwise. -[[nodiscard]] bool ValidateNameAndOwnerIfPresent(const url::Origin& owner, - const std::string& name, - const base::Value& value) { - const std::string* maybe_owner = value.FindStringKey("owner"); +[[nodiscard]] bool ValidateNameAndOwnerIfPresent( + const url::Origin& owner, + const std::string& name, + const base::Value::Dict& dict) { + const std::string* maybe_owner = dict.FindString("owner"); if (maybe_owner && url::Origin::Create(GURL(*maybe_owner)) != owner) return false; - const std::string* maybe_name = value.FindStringKey("name"); + const std::string* maybe_name = dict.FindString("name"); if (maybe_name && *maybe_name != name) return false; return true; @@ -99,14 +100,14 @@ // completed. [[nodiscard]] bool TryToCopyTrustedBiddingSignalsKeys( blink::InterestGroup& interest_group_update, - const base::Value& value) { - const base::Value* maybe_update_trusted_bidding_signals_keys = - value.FindListKey("trustedBiddingSignalsKeys"); + const base::Value::Dict& dict) { + const base::Value::List* maybe_update_trusted_bidding_signals_keys = + dict.FindList("trustedBiddingSignalsKeys"); if (!maybe_update_trusted_bidding_signals_keys) return true; std::vector<std::string> trusted_bidding_signals_keys; for (const base::Value& keys_value : - maybe_update_trusted_bidding_signals_keys->GetListDeprecated()) { + *maybe_update_trusted_bidding_signals_keys) { const std::string* maybe_key = keys_value.GetIfString(); if (!maybe_key) return false; @@ -119,17 +120,18 @@ // Helper for TryToCopyAds() and TryToCopyAdComponents(). [[nodiscard]] absl::optional<std::vector<blink::InterestGroup::Ad>> ExtractAds( - const base::Value& ads_list) { + const base::Value::List& ads_list) { std::vector<blink::InterestGroup::Ad> ads; - for (const base::Value& ads_value : ads_list.GetListDeprecated()) { - if (!ads_value.is_dict()) + for (const base::Value& ads_value : ads_list) { + const base::Value::Dict* ads_dict = ads_value.GetIfDict(); + if (!ads_dict) return absl::nullopt; - const std::string* maybe_render_url = ads_value.FindStringKey("renderUrl"); + const std::string* maybe_render_url = ads_dict->FindString("renderUrl"); if (!maybe_render_url) return absl::nullopt; blink::InterestGroup::Ad ad; ad.render_url = GURL(*maybe_render_url); - const base::Value* maybe_metadata = ads_value.FindKey("metadata"); + const base::Value* maybe_metadata = ads_dict->Find("metadata"); if (maybe_metadata) { std::string metadata; JSONStringValueSerializer serializer(&metadata); @@ -148,8 +150,8 @@ // Copies the `ads` list JSON field into `interest_group_update`, returns true // iff the JSON is valid and the copy completed. [[nodiscard]] bool TryToCopyAds(blink::InterestGroup& interest_group_update, - const base::Value& value) { - const base::Value* maybe_ads = value.FindListKey("ads"); + const base::Value::Dict& dict) { + const base::Value::List* maybe_ads = dict.FindList("ads"); if (!maybe_ads) return true; absl::optional<std::vector<blink::InterestGroup::Ad>> maybe_extracted_ads = @@ -164,8 +166,8 @@ // returns true iff the JSON is valid and the copy completed. [[nodiscard]] bool TryToCopyAdComponents( blink::InterestGroup& interest_group_update, - const base::Value& value) { - const base::Value* maybe_ads = value.FindListKey("adComponents"); + const base::Value::Dict& dict) { + const base::Value::List* maybe_ads = dict.FindList("adComponents"); if (!maybe_ads) return true; absl::optional<std::vector<blink::InterestGroup::Ad>> maybe_extracted_ads = @@ -184,45 +186,45 @@ if (result.error) { return absl::nullopt; } - const base::Value& value = *result.value; - if (!value.is_dict()) { + const base::Value::Dict* dict = result.value->GetIfDict(); + if (!dict) { return absl::nullopt; } - if (!ValidateNameAndOwnerIfPresent(owner, name, value)) { + if (!ValidateNameAndOwnerIfPresent(owner, name, *dict)) { return absl::nullopt; } blink::InterestGroup interest_group_update; interest_group_update.owner = owner; interest_group_update.name = name; - const base::Value* maybe_priority_value = value.FindKey("priority"); + const base::Value* maybe_priority_value = dict->Find("priority"); if (maybe_priority_value) { // If the field is specified, it must be an integer or a double. if (!maybe_priority_value->is_int() && !maybe_priority_value->is_double()) return absl::nullopt; interest_group_update.priority = maybe_priority_value->GetDouble(); } - const std::string* maybe_bidding_url = value.FindStringKey("biddingLogicUrl"); + const std::string* maybe_bidding_url = dict->FindString("biddingLogicUrl"); if (maybe_bidding_url) interest_group_update.bidding_url = GURL(*maybe_bidding_url); const std::string* maybe_bidding_wasm_helper_url = - value.FindStringKey("biddingWasmHelperUrl"); + dict->FindString("biddingWasmHelperUrl"); if (maybe_bidding_wasm_helper_url) { interest_group_update.bidding_wasm_helper_url = GURL(*maybe_bidding_wasm_helper_url); } const std::string* maybe_update_trusted_bidding_signals_url = - value.FindStringKey("trustedBiddingSignalsUrl"); + dict->FindString("trustedBiddingSignalsUrl"); if (maybe_update_trusted_bidding_signals_url) { interest_group_update.trusted_bidding_signals_url = GURL(*maybe_update_trusted_bidding_signals_url); } - if (!TryToCopyTrustedBiddingSignalsKeys(interest_group_update, value)) { + if (!TryToCopyTrustedBiddingSignalsKeys(interest_group_update, *dict)) { return absl::nullopt; } - if (!TryToCopyAds(interest_group_update, value)) { + if (!TryToCopyAds(interest_group_update, *dict)) { return absl::nullopt; } - if (!TryToCopyAdComponents(interest_group_update, value)) { + if (!TryToCopyAdComponents(interest_group_update, *dict)) { return absl::nullopt; } if (!interest_group_update.IsValid()) {
diff --git a/content/browser/portal/portal_browsertest.cc b/content/browser/portal/portal_browsertest.cc index 13a8021..a26874ce4 100644 --- a/content/browser/portal/portal_browsertest.cc +++ b/content/browser/portal/portal_browsertest.cc
@@ -698,7 +698,7 @@ TestNavigationObserver navigation_observer(a_url); navigation_observer.StartWatchingNewWebContents(); EXPECT_TRUE(ExecJs( - main_frame, JsReplace("var portal = document.createElement('portal');" + main_frame, JsReplace("let portal = document.createElement('portal');" "portal.src = $1;" "portal.style.width = '500px';" "portal.style.height = '500px';"
diff --git a/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc b/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc index a4989f1b..bab2c910 100644 --- a/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc +++ b/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
@@ -136,8 +136,6 @@ TRACE_EVENT0("dwrite,fonts", "FontProxyHost::OnFindFamily"); UINT32 family_index = UINT32_MAX; if (collection_) { - SCOPED_UMA_HISTOGRAM_TIMER_MICROS( - "DirectWrite.Fonts.Content.FindFamilyTime"); BOOL exists = FALSE; UINT32 index = UINT32_MAX; HRESULT hr = collection_->FindFamilyName(base::as_wcstr(family_name), @@ -153,8 +151,6 @@ void DWriteFontProxyImpl::GetFamilyCount(GetFamilyCountCallback callback) { InitializeDirectWrite(); TRACE_EVENT0("dwrite,fonts", "FontProxyHost::OnGetFamilyCount"); - SCOPED_UMA_HISTOGRAM_TIMER_MICROS( - "DirectWrite.Fonts.Content.GetFamilyCountTime"); std::move(callback).Run(collection_ ? collection_->GetFontFamilyCount() : 0); } @@ -167,8 +163,6 @@ if (!collection_) return; - SCOPED_UMA_HISTOGRAM_TIMER_MICROS( - "DirectWrite.Fonts.Content.GetFamilyNamesTime"); TRACE_EVENT0("dwrite,fonts", "FontProxyHost::DoGetFamilyNames"); mswr::ComPtr<IDWriteFontFamily> family; @@ -231,8 +225,6 @@ if (!collection_) return; - SCOPED_UMA_HISTOGRAM_TIMER_MICROS( - "DirectWrite.Fonts.Content.GetFontFilesTime"); mswr::ComPtr<IDWriteFontFamily> family; HRESULT hr = collection_->GetFontFamily(family_index, &family); if (FAILED(hr)) { @@ -319,8 +311,6 @@ } } - SCOPED_UMA_HISTOGRAM_TIMER_MICROS( - "DirectWrite.Fonts.Content.MapCharactersTime"); mswr::ComPtr<IDWriteFont> mapped_font; mswr::ComPtr<IDWriteNumberSubstitution> number_substitution; @@ -530,8 +520,6 @@ if (!codepoint || !collection_ || !factory_) return; - SCOPED_UMA_HISTOGRAM_TIMER_MICROS( - "DirectWrite.Fonts.Content.FallbackFamilyAndStyleForCodepointTime"); sk_sp<SkFontMgr> font_mgr( SkFontMgr_New_DirectWrite(factory_.Get(), collection_.Get())); @@ -563,7 +551,6 @@ void DWriteFontProxyImpl::InitializeDirectWrite() { if (direct_write_initialized_) return; - SCOPED_UMA_HISTOGRAM_TIMER_MICROS("DirectWrite.Fonts.Content.InitializeTime"); direct_write_initialized_ = true; TRACE_EVENT0("dwrite,fonts", "DWriteFontProxyImpl::InitializeDirectWrite");
diff --git a/content/browser/renderer_host/input/fling_controller_unittest.cc b/content/browser/renderer_host/input/fling_controller_unittest.cc index ebd445ad..81208f00 100644 --- a/content/browser/renderer_host/input/fling_controller_unittest.cc +++ b/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -216,6 +216,7 @@ bool first_wheel_event_sent_ = false; int sent_scroll_gesture_count_ = 0; #if BUILDFLAG(IS_WIN) + // This is necessary for static methods of `display::ScreenWin`. display::win::test::ScopedScreenWin scoped_screen_win_; #endif
diff --git a/content/browser/renderer_host/input/fling_scheduler_unittest.cc b/content/browser/renderer_host/input/fling_scheduler_unittest.cc index f8de4972b..1b45630 100644 --- a/content/browser/renderer_host/input/fling_scheduler_unittest.cc +++ b/content/browser/renderer_host/input/fling_scheduler_unittest.cc
@@ -15,10 +15,6 @@ #include "content/test/test_render_widget_host.h" #include "testing/gtest/include/gtest/gtest.h" -#if BUILDFLAG(IS_WIN) -#include "ui/display/win/test/scoped_screen_win.h" -#endif - namespace content { class FakeFlingScheduler : public FlingScheduler { @@ -139,9 +135,6 @@ scoped_refptr<SiteInstanceGroup> site_instance_group_; std::unique_ptr<TestRenderWidgetHostView> view_; std::unique_ptr<MockRenderWidgetHostDelegate> delegate_; -#if BUILDFLAG(IS_WIN) - display::win::test::ScopedScreenWin scoped_screen_win_; -#endif }; TEST_F(FlingSchedulerTest, ScheduleNextFlingProgress) {
diff --git a/content/browser/renderer_host/input/gesture_event_queue_unittest.cc b/content/browser/renderer_host/input/gesture_event_queue_unittest.cc index 292f17f..8ba2b0f7 100644 --- a/content/browser/renderer_host/input/gesture_event_queue_unittest.cc +++ b/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
@@ -25,10 +25,6 @@ #include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h" #include "ui/events/blink/blink_features.h" -#if BUILDFLAG(IS_WIN) -#include "ui/display/win/test/scoped_screen_win.h" -#endif - using blink::WebGestureDevice; using blink::WebGestureEvent; using blink::WebInputEvent; @@ -244,9 +240,6 @@ std::unique_ptr<blink::mojom::InputEventResultState> sync_ack_result_; std::unique_ptr<WebGestureEvent> sync_followup_event_; base::test::ScopedFeatureList feature_list_; -#if BUILDFLAG(IS_WIN) - display::win::test::ScopedScreenWin scoped_screen_win_; -#endif }; class GestureEventQueueWithCompositorEventQueueTest
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc index b4e1505c..3e4d7c6 100644 --- a/content/browser/renderer_host/input/input_router_impl_unittest.cc +++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -46,10 +46,6 @@ #include "ui/events/event.h" #endif -#if BUILDFLAG(IS_WIN) -#include "ui/display/win/test/scoped_screen_win.h" -#endif - using blink::SyntheticWebGestureEventBuilder; using blink::SyntheticWebMouseEventBuilder; using blink::SyntheticWebMouseWheelEventBuilder; @@ -970,9 +966,6 @@ TEST_F(InputRouterImplTest, DISABLED_GestureTypesIgnoringAck) { // We test every gesture type, ensuring that the stream of gestures is valid. -#if BUILDFLAG(IS_WIN) - display::win::test::ScopedScreenWin scoped_screen_win_; -#endif const WebInputEvent::Type eventTypes[] = { WebInputEvent::Type::kGestureTapDown, WebInputEvent::Type::kGestureShowPress,
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index c983b5f..b41b617 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -1101,6 +1101,24 @@ std::move(callback).Run({}); } +// Creates a JavaScriptExecuteRequestForTestsCallback callback that delegates +// to the given JavaScriptResultCallback. +blink::mojom::LocalFrame::JavaScriptExecuteRequestForTestsCallback +CreateJavaScriptExecuteRequestForTestsCallback( + RenderFrameHost::JavaScriptResultCallback callback) { + if (!callback) + return base::NullCallback(); + return base::BindOnce( + [](RenderFrameHost::JavaScriptResultCallback callback, + blink::mojom::JavaScriptExecutionResultType type, base::Value value) { + if (type == blink::mojom::JavaScriptExecutionResultType::kSuccess) + std::move(callback).Run(value.Clone()); + else + std::move(callback).Run(base::Value()); + }, + std::move(callback)); +} + } // namespace class RenderFrameHostImpl::SubresourceLoaderFactoriesConfig { @@ -2483,34 +2501,42 @@ const std::u16string& javascript, JavaScriptResultCallback callback, int32_t world_id) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - AssertNonSpeculativeFrame(); - - const bool has_user_gesture = false; - const bool wants_result = !callback.is_null(); - GetAssociatedLocalFrame()->JavaScriptExecuteRequestForTests( // IN-TEST - javascript, wants_result, has_user_gesture, world_id, - std::move(callback)); + ExecuteJavaScriptForTests( // IN-TEST + javascript, /*has_user_gesture=*/false, + /*resolve_promises=*/false, world_id, + CreateJavaScriptExecuteRequestForTestsCallback(std::move(callback))); } void RenderFrameHostImpl::ExecuteJavaScriptWithUserGestureForTests( const std::u16string& javascript, JavaScriptResultCallback callback, int32_t world_id) { + ExecuteJavaScriptForTests( // IN-TEST + javascript, /*has_user_gesture=*/true, + /*resolve_promises=*/false, world_id, + CreateJavaScriptExecuteRequestForTestsCallback(std::move(callback))); +} + +void RenderFrameHostImpl::ExecuteJavaScriptForTests( + const std::u16string& javascript, + bool has_user_gesture, + bool resolve_promises, + int32_t world_id, + JavaScriptResultAndTypeCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); AssertNonSpeculativeFrame(); - // TODO(mustaq): The render-to-browser state update caused by the below - // JavaScriptExecuteRequestsForTests call is redundant with this update. We - // should determine if the redundancy can be removed. - frame_tree_node()->UpdateUserActivationState( - blink::mojom::UserActivationUpdateType::kNotifyActivation, - blink::mojom::UserActivationNotificationType::kTest); + if (has_user_gesture) { + // TODO(mustaq): The render-to-browser state update caused by the below + // JavaScriptExecuteRequestsForTests call is redundant with this update. We + // should determine if the redundancy can be removed. + frame_tree_node()->UpdateUserActivationState( + blink::mojom::UserActivationUpdateType::kNotifyActivation, + blink::mojom::UserActivationNotificationType::kTest); + } - const bool has_user_gesture = true; - const bool wants_result = !callback.is_null(); GetAssociatedLocalFrame()->JavaScriptExecuteRequestForTests( // IN-TEST - javascript, wants_result, has_user_gesture, world_id, + javascript, has_user_gesture, resolve_promises, world_id, std::move(callback)); } @@ -6210,25 +6236,31 @@ void RenderFrameHostImpl::EnterFullscreen( blink::mojom::FullscreenOptionsPtr options, EnterFullscreenCallback callback) { - // Consume the user activation when entering fullscreen mode in the browser - // side when the renderer is compromised and the fullscreen request is denied. - // Fullscreen can only be triggered by: a user activation, a user-generated - // screen orientation change, or another feature-specific transient allowance. + const bool had_fullscreen_token = fullscreen_request_token_.IsActive(); + + // Entering fullscreen requires a transient user activation, a fullscreen + // capability delegation token, a user-generated screen orientation change, or + // another feature-specific transient allowance. // CanEnterFullscreenWithoutUserActivation is only ever true in tests, to // allow fullscreen when mocking screen orientation changes. - // TODO(lanwei): Investigate whether we can terminate the renderer when the - // user activation has already been consumed. if (!delegate_->HasSeenRecentScreenOrientationChange() && !WindowPlacementAllowsFullscreen() && !HasSeenRecentXrOverlaySetup() && !GetContentClient() ->browser() ->CanEnterFullscreenWithoutUserActivation()) { - bool is_consumed = frame_tree_node_->UpdateUserActivationState( - blink::mojom::UserActivationUpdateType::kConsumeTransientActivation, - blink::mojom::UserActivationNotificationType::kNone); - if (!is_consumed) { + // Consume any transient user activation and delegated fullscreen token. + // Reject requests made without transient user activation or a token. + // TODO(lanwei): Investigate whether we can terminate the renderer when + // transient user activation and the delegated token are both inactive. + const bool consumed_activation = + frame_tree_node_->UpdateUserActivationState( + blink::mojom::UserActivationUpdateType::kConsumeTransientActivation, + blink::mojom::UserActivationNotificationType::kNone); + const bool consumed_token = fullscreen_request_token_.ConsumeIfActive(); + if (!consumed_activation && !consumed_token) { DLOG(ERROR) << "Cannot enter fullscreen because there is no transient " - << "user activation, orientation change, or XR overlay."; + << "user activation, orientation change, XR overlay, nor " + << "capability delegation."; std::move(callback).Run(/*granted=*/false); return; } @@ -6284,6 +6316,9 @@ notified_instances.insert(parent_site_instance); } + // Focus the window if another frame may have delegated the capability. + if (had_fullscreen_token && !GetView()->HasFocus()) + GetView()->Focus(); delegate_->EnterFullscreenMode(this, *options); delegate_->FullscreenStateChanged(this, /*is_fullscreen=*/true, std::move(options)); @@ -7343,6 +7378,14 @@ child->SetSrcdocValue(srcdoc_value); } +void RenderFrameHostImpl::ReceivedDelegatedCapability( + blink::mojom::DelegatedCapability delegated_capability) { + if (delegated_capability == + blink::mojom::DelegatedCapability::kFullscreenRequest) { + fullscreen_request_token_.Activate(); + } +} + // TODO(ahemery): Move checks to mojo bad message reporting. void RenderFrameHostImpl::BeginNavigation( blink::mojom::CommonNavigationParamsPtr common_params, @@ -11948,6 +11991,9 @@ blink::TransferableMessage message) { DCHECK(is_render_frame_created()); + if (message.delegated_capability != blink::mojom::DelegatedCapability::kNone) + ReceivedDelegatedCapability(message.delegated_capability); + GetAssociatedLocalFrame()->PostMessageEvent( source_token, source_origin, target_origin, std::move(message)); }
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index bd7e408..7acb4e3 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -101,6 +101,7 @@ #include "services/network/public/mojom/url_loader_network_service_observer.mojom-forward.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/frame/frame_owner_element_type.h" +#include "third_party/blink/public/common/frame/fullscreen_request_token.h" #include "third_party/blink/public/common/permissions_policy/permissions_policy.h" #include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h" #include "third_party/blink/public/common/storage_key/storage_key.h" @@ -2149,6 +2150,8 @@ void FrameSizeChanged(const gfx::Size& frame_size) override; void DidChangeSrcDoc(const blink::FrameToken& child_frame_token, const std::string& srcdoc_value) override; + void ReceivedDelegatedCapability( + blink::mojom::DelegatedCapability delegated_capability) override; // blink::mojom::BackForwardCacheControllerHost: void EvictFromBackForwardCache(blink::mojom::RendererEvictionReason) override; @@ -2486,6 +2489,19 @@ kIframeNestedWithinFencedFrame }; + using JavaScriptResultAndTypeCallback = + base::OnceCallback<void(blink::mojom::JavaScriptExecutionResultType, + base::Value)>; + + // Runs JavaScript in this frame, without restrictions. ONLY FOR TESTS. + // This method can optionally trigger a fake user activation notification, + // and can wait for returned promises to be resolved. + void ExecuteJavaScriptForTests(const std::u16string& javascript, + bool has_user_gesture, + bool resolve_promises, + int32_t world_id, + JavaScriptResultAndTypeCallback callback); + protected: friend class RenderFrameHostFactory; @@ -4228,6 +4244,9 @@ // Manages a transient affordance for this frame or subframes to open a popup. TransientAllowPopup transient_allow_popup_; + // Manages a transient affordance for this frame to request fullscreen. + blink::FullscreenRequestToken fullscreen_request_token_; + // Used to avoid sending AXTreeData to the renderer if the renderer has not // been told root ID yet. See UpdateAXTreeData() for more details. bool needs_ax_root_id_ = true;
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc index 2e82237e..d4d89d9 100644 --- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc +++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
@@ -4387,7 +4387,9 @@ // Execute script in an isolated world to avoid causing a Trusted Types // violation due to eval. EXPECT_EQ("Graphics Feature Status", - EvalJs(main_document, "document.querySelector('h3').textContent", + EvalJs(main_document, + "document.querySelector('info-view').shadowRoot" + ".querySelector('h3').textContent", EXECUTE_SCRIPT_DEFAULT_OPTIONS, /*world_id=*/1)); }
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index b22ccbf..17c5ed84 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -81,6 +81,7 @@ #if BUILDFLAG(IS_MAC) #include "content/browser/renderer_host/test_render_widget_host_view_mac_factory.h" +#include "ui/display/test/test_screen.h" #endif #if defined(USE_AURA) || BUILDFLAG(IS_MAC) @@ -558,6 +559,10 @@ // calls display::Screen::SetScreenInstance(). ui::SetScreenAndroid(false /* use_display_wide_color_gamut */); #endif +#if BUILDFLAG(IS_MAC) + screen_ = std::make_unique<display::test::TestScreen>(); + display::Screen::SetScreenInstance(screen_.get()); +#endif #if defined(USE_AURA) screen_.reset(aura::TestScreen::Create(gfx::Size())); display::Screen::SetScreenInstance(screen_.get()); @@ -619,11 +624,11 @@ browser_context_.reset(); #if defined(USE_AURA) - display::Screen::SetScreenInstance(nullptr); - screen_.reset(); + ImageTransportFactory::Terminate(); #endif #if defined(USE_AURA) || BUILDFLAG(IS_MAC) - ImageTransportFactory::Terminate(); + display::Screen::SetScreenInstance(nullptr); + screen_.reset(); #endif #if BUILDFLAG(IS_ANDROID) display::Screen::SetScreenInstance(nullptr);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index f4fc156..9253f16c 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -131,7 +131,6 @@ #if BUILDFLAG(IS_WIN) #include "ui/base/view_prop.h" #include "ui/base/win/window_event_target.h" -#include "ui/display/win/test/scoped_screen_win.h" #endif using testing::_; @@ -3766,11 +3765,6 @@ ScrollEventsOverscrollWithFling) { SetUpOverscrollEnvironment(); -#if BUILDFLAG(IS_WIN) - // Create a ScopedScreenWin. - display::win::test::ScopedScreenWin scoped_screen_win; -#endif - // Send a wheel event. ACK the event as not processed. This should not // initiate an overscroll gesture since it doesn't cross the threshold yet. SimulateWheelEvent(10, 0, 0, true, WebMouseWheelEvent::kPhaseBegan); @@ -3847,11 +3841,6 @@ ScrollEventsOverscrollWithZeroFling) { SetUpOverscrollEnvironment(); -#if BUILDFLAG(IS_WIN) - // Create a ScopedScreenWin. - display::win::test::ScopedScreenWin scoped_screen_win; -#endif - // Send a wheel event. ACK the event as not processed. This should not // initiate an overscroll gesture since it doesn't cross the threshold yet. SimulateWheelEvent(10, 0, 0, true, WebMouseWheelEvent::kPhaseBegan); @@ -3929,11 +3918,6 @@ MAYBE_ReverseFlingCancelsOverscroll) { SetUpOverscrollEnvironment(); -#if BUILDFLAG(IS_WIN) - // Create a ScopedScreenWin. - display::win::test::ScopedScreenWin scoped_screen_win; -#endif - { PressAndSetTouchActionAuto(); // Start and end a gesture in the same direction without processing the @@ -4804,11 +4788,6 @@ OverscrollStateResetsAfterScroll) { SetUpOverscrollEnvironment(); -#if BUILDFLAG(IS_WIN) - // Create a ScopedScreenWin. - display::win::test::ScopedScreenWin scoped_screen_win; -#endif - SimulateWheelEvent(0, 5, 0, true, WebMouseWheelEvent::kPhaseBegan); // sent directly SimulateWheelEvent(0, 30, 0, true, @@ -5246,11 +5225,6 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, ScrollDeltasResetOnEnd) { SetUpOverscrollEnvironment(); -#if BUILDFLAG(IS_WIN) - // Create a ScopedScreenWin. - display::win::test::ScopedScreenWin scoped_screen_win; -#endif - PressAndSetTouchActionAuto(); // Wheel event scroll ending with mouse move. SimulateWheelEvent(-30, -10, 0, true,
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm index c79d604..8f8fb19c 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -27,6 +27,7 @@ #include "testing/platform_test.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/base/layout.h" +#include "ui/display/screen.h" using content::RenderWidgetHostViewMac; @@ -122,6 +123,7 @@ void TearDown() override { ImageTransportFactory::Terminate(); } private: + display::ScopedNativeScreen screen_; // This has a MessageLoop for ImageTransportFactory and enables // BrowserThread::UI for RecyclableCompositorMac used by // RenderWidgetHostViewMac.
diff --git a/content/browser/resources/gpu/BUILD.gn b/content/browser/resources/gpu/BUILD.gn new file mode 100644 index 0000000..9a4a963 --- /dev/null +++ b/content/browser/resources/gpu/BUILD.gn
@@ -0,0 +1,13 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//tools/polymer/html_to_js.gni") + +html_to_js("web_components") { + js_files = [ + "info_view.js", + "info_view_table.js", + "info_view_table_row.js", + ] +}
diff --git a/content/browser/resources/gpu/gpu_internals.html b/content/browser/resources/gpu/gpu_internals.html index 0f13f54..092da842 100644 --- a/content/browser/resources/gpu/gpu_internals.html +++ b/content/browser/resources/gpu/gpu_internals.html
@@ -8,35 +8,31 @@ <head> <meta name="viewport" content="width=device-width" /> <style> -* { - box-sizing: border-box; - user-select: none; -} + * { + box-sizing: border-box; + user-select: none; + } -body { - background-color: white; - cursor: default; - font-family: sans-serif; - padding: 0; -} + body { + background-color: white; + cursor: default; + font-family: sans-serif; + margin: 8px; + padding: 0; + } -#debug-div { - border: 1px solid red; - display: -webkit-box; - left: 50%; - position: fixed; - top: 0; -} - + #debug-div { + border: 1px solid red; + display: flex; + left: 50%; + position: fixed; + top: 0; + } </style> -<link rel="stylesheet" href="info_view.css"> -<link rel="stylesheet" href="chrome://resources/css/widgets.css"> <script type="module" src="gpu_internals.js"></script> </head> <body> - <div id="debug-div"> - </div> - <include src="info_view.html"> - <script src="chrome://resources/js/jstemplate_compiled.js"></script> + <div id="debug-div"></div> + <info-view></info-view> </body> </html>
diff --git a/content/browser/resources/gpu/gpu_internals.js b/content/browser/resources/gpu/gpu_internals.js index 0dc4da9..1c3f6d95 100644 --- a/content/browser/resources/gpu/gpu_internals.js +++ b/content/browser/resources/gpu/gpu_internals.js
@@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {decorate} from 'chrome://resources/js/cr/ui.m.js'; +import './info_view.js'; import {BrowserBridge} from './browser_bridge.js'; -import {makeInfoView} from './info_view.js'; // Injected script from C++ or test environments may reference `browserBridge` // as a property of the global object. @@ -16,7 +15,8 @@ */ function onLoad() { // Create the views. - decorate('#info-view', makeInfoView(window.browserBridge)); + document.querySelector('info-view') + .addBrowserBridgeListeners(window.browserBridge); // Because of inherent raciness (between the deprecated DevTools API which // telemtry uses to drive the relevant tests, and the asynchronous loading of
diff --git a/content/browser/resources/gpu/info_view.css b/content/browser/resources/gpu/info_view.css deleted file mode 100644 index 0709d98..0000000 --- a/content/browser/resources/gpu/info_view.css +++ /dev/null
@@ -1,80 +0,0 @@ -/* Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. */ - -#info-view { - -webkit-box-flex: 1; - overflow: auto; - padding: 10px; -} - -#info-view * { - -webkit-user-select: text; -} - -#info-view[selected] { - -webkit-box-orient: vertical; - display: -webkit-box; -} - -#info-view h3, -#info-view ul { - margin-bottom: 0; - margin-top: 0; -} - -#info-view > div { - margin-bottom: 1em; -} - -#info-view .row-title { - font-weight: bold; -} - -#info-view table { - border-collapse: collapse; - cursor: auto; - table-layout: fixed; - width: 100%; -} - -#info-view table, -#info-view th, -#info-view td { - border: 1px solid #777; - padding-end: 4px; - padding-start: 4px; - text-align: top; -} - -#info-view td { - overflow-x: auto; -} - -#info-view .feature-green { - color: rgb(0, 128, 0); -} - -#info-view .feature-yellow { - color: rgb(128, 128, 0); -} - -#info-view .feature-red { - color: rgb(255, 0, 0); -} - -#info-view .feature-gray { - color: rgb(128, 128, 128); -} - -#info-view .bg-yellow { - background-color: yellow; -} - -#vulkan-info-value { - white-space: pre; -} - -#copy-to-clipboard { - user-select: none; -}
diff --git a/content/browser/resources/gpu/info_view.html b/content/browser/resources/gpu/info_view.html index 0753fad..b9de047 100644 --- a/content/browser/resources/gpu/info_view.html +++ b/content/browser/resources/gpu/info_view.html
@@ -3,139 +3,183 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<div id="info-view"> - <div> - <input type="button" id="copy-to-clipboard" value="Copy Report to Clipboard"> - </div> - <div> - <h3>Graphics Feature Status</h3> - <ul class="feature-status-list"> - </ul> - </div> +<style> + :host { + display: block; + flex: 1; + overflow: auto; + padding: 10px; + } - <div class='workarounds-div'> - <h3>Driver Bug Workarounds</h3> - <ul class="workarounds-list"> - </ul> - </div> + :host * { + user-select: text; + } - <div class='problems-div'> - <h3>Problems Detected</h3> - <ul class="problems-list"> - </ul> - </div> + :host([selected]) { + display: flex; + flex-direction: column; + } - <div class='angle-features-div'> - <h3>ANGLE Features</h3> - <ul class="angle-features-list"> - </ul> - </div> + h3, + ul { + margin-bottom: 0; + margin-top: 0; + } - <div class='dawn-info-div'> - <h3>DAWN Info</h3> - <ul class="dawn-info-list"> - </ul> - </div> + :host > div { + margin-bottom: 1em; + } - <div> - <h3>Version Information</h3> - <div id="client-info"></div> - </div> + .feature-green { + color: rgb(0, 128, 0); + } - <div> - <h3>Driver Information</h3> - <div id="basic-info"></div> - </div> + .feature-yellow { + color: rgb(128, 128, 0); + } - <div> - <h3>Compositor Information</h3> - <div id="compositor-info"></div> - </div> + .feature-red { + color: rgb(255, 0, 0); + } - <div> - <h3>GpuMemoryBuffers Status</h3> - <div id="gpu-memory-buffer-info"></div> - </div> + .feature-gray { + color: rgb(128, 128, 128); + } - <div> - <h3>Display(s) Information</h3> - <div id="display-info"></div> - </div> + .bg-yellow { + background-color: yellow; + } - <div> - <h3>Video Acceleration Information</h3> - <div id="video-acceleration-info"></div> - </div> + #vulkan-info-value { + white-space: pre; + } - <div> - <h3>Vulkan Information</h3> - <div id="vulkan-info"></div> - </div> + #copy-to-clipboard { + background-image: linear-gradient(#ededed, #ededed 38%, #dedede); + border: 1px solid rgba(0, 0, 0, .25); + border-radius: 2px; + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), + inset 0 1px 2px rgba(255, 255, 255, 0.75); + color: #444; + font: inherit; + margin: 0 1px 0 0; + min-height: 2em; + outline: none; + padding: 1px 10px; + text-shadow: 0 1px 0 rgb(240, 240, 240); + user-select: none; + } - <div> - <h3>Device Performance Information</h3> - <div id="device-perf-info"></div> - </div> + #copy-to-clipboard:enabled:hover { + background-image: linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); + border-color: rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), + inset 0 1px 2px rgba(255, 255, 255, 0.95); + color: black; + } - <div class="diagnostics"> - <h3>Diagnostics</h3> - <div class="diagnostics-loading">... loading ...</div> - <div id="diagnostics-table">None</div> - </div> + #copy-to-clipboard:enabled:active { + background-image: linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); + box-shadow: none; + text-shadow: none; + } +</style> - <div class='basic-info-for-hardware-gpu-div'> - <h3>Driver Information for Hardware GPU</h3> - <div id="basic-info-for-hardware-gpu"></div> - </div> +<div> + <button id="copy-to-clipboard">Copy Report to Clipboard</button> +</div> +<div> + <h3>Graphics Feature Status</h3> + <ul class="feature-status-list"></ul> +</div> - <div class='feature-status-for-hardware-gpu-div'> - <h3>Graphics Feature Status for Hardware GPU</h3> - <ul class="feature-status-for-hardware-gpu-list"> - </ul> - </div> +<div class='workarounds-div'> + <h3>Driver Bug Workarounds</h3> + <ul class="workarounds-list"></ul> +</div> - <div class='workarounds-for-hardware-gpu-div'> - <h3>Driver Bug Workarounds for Hardware GPU</h3> - <ul class="workarounds-for-hardware-gpu-list"> - </ul> - </div> +<div class='problems-div'> + <h3>Problems Detected</h3> + <ul class="problems-list"></ul> +</div> - <div class='problems-for-hardware-gpu-div'> - <h3>Problems Detected for Hardware GPU</h3> - <ul class="problems-for-hardware-gpu-list"> - </ul> - </div> +<div class='angle-features-div'> + <h3>ANGLE Features</h3> + <ul class="angle-features-list"></ul> +</div> - <div id="log-messages" jsdisplay="values.length"> - <h3>Log Messages</h3> - <ul> - <li jsselect="values"> - <span jscontent="header"></span>: <span jscontent="message"></span> - </li> - </ul> - </div> +<div class='dawn-info-div'> + <h3>DAWN Info</h3> + <ul class="dawn-info-list"></ul> +</div> - <!-- templates --> - <div style="display:none"> - <div id="info-view-table-template"> - <table id="info-view-table"> - <colgroup> - <col style="width: 25%" /> - <col style="width: 75%" /> - </colgroup> - <tr jsselect="value"> - <td jsdisplay="!(value instanceof Array)"> - <span class="row-title" jscontent="description">title</span> - </td> - <td jsdisplay="!(value instanceof Array)"> - <span jscontent="value" jsvalues=".id:id">value</span> - </td> - <td jsdisplay="value instanceof Array" colspan=2> - <span jscontent="description" class="row-title"></span> - <div transclude="info-view-table-template"></div> - </td> - </tr> - </table> - </div> - </div> +<div> + <h3>Version Information</h3> + <div id="client-info"></div> +</div> + +<div> + <h3>Driver Information</h3> + <div id="basic-info"></div> +</div> + +<div> + <h3>Compositor Information</h3> + <div id="compositor-info"></div> +</div> + +<div> + <h3>GpuMemoryBuffers Status</h3> + <div id="gpu-memory-buffer-info"></div> +</div> + +<div> + <h3>Display(s) Information</h3> + <div id="display-info"></div> +</div> + +<div> + <h3>Video Acceleration Information</h3> + <div id="video-acceleration-info"></div> +</div> + +<div> + <h3>Vulkan Information</h3> + <div id="vulkan-info"></div> +</div> + +<div> + <h3>Device Performance Information</h3> + <div id="device-perf-info"></div> +</div> + +<div class="diagnostics"> + <h3>Diagnostics</h3> + <div class="diagnostics-loading">... loading ...</div> + <div id="diagnostics-table">None</div> +</div> + +<div class='basic-info-for-hardware-gpu-div'> + <h3>Driver Information for Hardware GPU</h3> + <div id="basic-info-for-hardware-gpu"></div> +</div> + +<div class='feature-status-for-hardware-gpu-div'> + <h3>Graphics Feature Status for Hardware GPU</h3> + <ul class="feature-status-for-hardware-gpu-list"></ul> +</div> + +<div class='workarounds-for-hardware-gpu-div'> + <h3>Driver Bug Workarounds for Hardware GPU</h3> + <ul class="workarounds-for-hardware-gpu-list"></ul> +</div> + +<div class='problems-for-hardware-gpu-div'> + <h3>Problems Detected for Hardware GPU</h3> + <ul class="problems-for-hardware-gpu-list"></ul> +</div> + +<div id="log-messages"> + <h3>Log Messages</h3> + <ul></ul> </div>
diff --git a/content/browser/resources/gpu/info_view.js b/content/browser/resources/gpu/info_view.js index f85a768..bf70baa 100644 --- a/content/browser/resources/gpu/info_view.js +++ b/content/browser/resources/gpu/info_view.js
@@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {define as crUiDefine} from 'chrome://resources/js/cr/ui.m.js'; -import {$} from 'chrome://resources/js/util.m.js'; +import './info_view_table.js'; + +import {CustomElement} from 'chrome://resources/js/custom_element.js'; +import {getTrustedHTML} from 'chrome://resources/js/static_types.js'; import {VulkanInfo} from './vulkan_info.js'; @@ -12,613 +14,617 @@ * hardware. Its primary usefulness is to allow users to copy-paste * their data in an easy to read format for bug reports. */ -export function makeInfoView(browserBridge) { +export class InfoViewElement extends CustomElement { + static get template() { + return getTrustedHTML`{__html_template__}`; + } + + addBrowserBridgeListeners(browserBridge) { + browserBridge.addEventListener( + 'gpuInfoUpdate', this.refresh.bind(this, browserBridge)); + browserBridge.addEventListener( + 'logMessagesChange', this.refresh.bind(this, browserBridge)); + browserBridge.addEventListener( + 'clientInfoChange', this.refresh.bind(this, browserBridge)); + this.refresh(browserBridge); + } + + connectedCallback() { + // Add handler to 'copy to clipboard' button + this.shadowRoot.querySelector('#copy-to-clipboard').onclick = (() => { + // Make sure nothing is selected + const s = window.getSelection(); + s.removeAllRanges(); + s.selectAllChildren(this.shadowRoot); + document.execCommand('copy'); + + // And deselect everything at the end. + window.getSelection().removeAllRanges(); + }); + } + /** - * Provides information on the GPU process and underlying graphics hardware. - * @constructor + * Updates the view based on its currently known data */ - const InfoView = crUiDefine('div'); - - InfoView.prototype = { - __proto__: HTMLDivElement.prototype, - - decorate: function() { - browserBridge.addEventListener('gpuInfoUpdate', this.refresh.bind(this)); - browserBridge.addEventListener( - 'logMessagesChange', this.refresh.bind(this)); - browserBridge.addEventListener( - 'clientInfoChange', this.refresh.bind(this)); - - // Add handler to 'copy to clipboard' button - $('copy-to-clipboard').onclick = function() { - // Make sure nothing is selected - window.getSelection().removeAllRanges(); - - document.execCommand('selectAll'); - document.execCommand('copy'); - - // And deselect everything at the end. - window.getSelection().removeAllRanges(); - }; - - this.refresh(); - }, - - /** - * Updates the view based on its currently known data - */ - refresh: function(data) { - let clientInfo; - function createSourcePermalink(revisionIdentifier, filepath) { - if (revisionIdentifier.length !== 40) { - // If the revision id isn't a hash, just use the 0.0.0.0 version - // from the Chrome version string "Chrome/0.0.0.0". - revisionIdentifier = clientInfo.version.split('/')[1]; - } - return `https://chromium.googlesource.com/chromium/src/+/${ - revisionIdentifier}/${filepath}`; + refresh(browserBridge) { + let clientInfo; + function createSourcePermalink(revisionIdentifier, filepath) { + if (revisionIdentifier.length !== 40) { + // If the revision id isn't a hash, just use the 0.0.0.0 version + // from the Chrome version string "Chrome/0.0.0.0". + revisionIdentifier = clientInfo.version.split('/')[1]; } + return `https://chromium.googlesource.com/chromium/src/+/${ + revisionIdentifier}/${filepath}`; + } - // Client info - if (browserBridge.clientInfo) { - clientInfo = browserBridge.clientInfo; + // Client info + if (browserBridge.clientInfo) { + clientInfo = browserBridge.clientInfo; - this.setTable_('client-info', [ - {description: 'Data exported', value: (new Date()).toISOString()}, - {description: 'Chrome version', value: clientInfo.version}, - {description: 'Operating system', value: clientInfo.operating_system}, - { - description: 'Software rendering list URL', - value: createSourcePermalink( - clientInfo.revision_identifier, - 'gpu/config/software_rendering_list.json') - }, - { - description: 'Driver bug list URL', - value: createSourcePermalink( - clientInfo.revision_identifier, - 'gpu/config/gpu_driver_bug_list.json') - }, - {description: 'ANGLE commit id', value: clientInfo.angle_commit_id}, { - description: '2D graphics backend', - value: clientInfo.graphics_backend - }, - {description: 'Command Line', value: clientInfo.command_line} - ]); + this.setTable_('client-info', [ + {description: 'Data exported', value: (new Date()).toISOString()}, + {description: 'Chrome version', value: clientInfo.version}, + {description: 'Operating system', value: clientInfo.operating_system}, { + description: 'Software rendering list URL', + value: createSourcePermalink( + clientInfo.revision_identifier, + 'gpu/config/software_rendering_list.json') + }, + { + description: 'Driver bug list URL', + value: createSourcePermalink( + clientInfo.revision_identifier, + 'gpu/config/gpu_driver_bug_list.json') + }, + {description: 'ANGLE commit id', value: clientInfo.angle_commit_id}, { + description: '2D graphics backend', + value: clientInfo.graphics_backend + }, + {description: 'Command Line', value: clientInfo.command_line} + ]); + } else { + this.setText_('client-info', '... loading...'); + } + + + // GPU info, basic + const diagnosticsDiv = this.shadowRoot.querySelector('.diagnostics'); + const diagnosticsLoadingDiv = + this.shadowRoot.querySelector('.diagnostics-loading'); + const featureStatusList = + this.shadowRoot.querySelector('.feature-status-list'); + const problemsDiv = this.shadowRoot.querySelector('.problems-div'); + const problemsList = this.shadowRoot.querySelector('.problems-list'); + const workaroundsDiv = this.shadowRoot.querySelector('.workarounds-div'); + const workaroundsList = this.shadowRoot.querySelector('.workarounds-list'); + const ANGLEFeaturesDiv = + this.shadowRoot.querySelector('.angle-features-div'); + const ANGLEFeaturesList = + this.shadowRoot.querySelector('.angle-features-list'); + const DAWNInfoDiv = this.shadowRoot.querySelector('.dawn-info-div'); + const DAWNInfoList = this.shadowRoot.querySelector('.dawn-info-list'); + + const basicInfoForHardwareGpuDiv = + this.shadowRoot.querySelector('.basic-info-for-hardware-gpu-div'); + const featureStatusForHardwareGpuDiv = + this.shadowRoot.querySelector('.feature-status-for-hardware-gpu-div'); + const featureStatusForHardwareGpuList = + this.shadowRoot.querySelector('.feature-status-for-hardware-gpu-list'); + const problemsForHardwareGpuDiv = + this.shadowRoot.querySelector('.problems-for-hardware-gpu-div'); + const problemsForHardwareGpuList = + this.shadowRoot.querySelector('.problems-for-hardware-gpu-list'); + const workaroundsForHardwareGpuDiv = + this.shadowRoot.querySelector('.workarounds-for-hardware-gpu-div'); + const workaroundsForHardwareGpuList = + this.shadowRoot.querySelector('.workarounds-for-hardware-gpu-list'); + + const gpuInfo = browserBridge.gpuInfo; + let i; + if (gpuInfo) { + // Not using jstemplate here for blocklist status because we construct + // href from data, which jstemplate can't seem to do. + if (gpuInfo.featureStatus) { + this.appendFeatureInfo_( + gpuInfo.featureStatus, featureStatusList, problemsDiv, problemsList, + workaroundsDiv, workaroundsList); } else { - this.setText_('client-info', '... loading...'); - } - - - // GPU info, basic - const diagnosticsDiv = this.querySelector('.diagnostics'); - const diagnosticsLoadingDiv = this.querySelector('.diagnostics-loading'); - const featureStatusList = this.querySelector('.feature-status-list'); - const problemsDiv = this.querySelector('.problems-div'); - const problemsList = this.querySelector('.problems-list'); - const workaroundsDiv = this.querySelector('.workarounds-div'); - const workaroundsList = this.querySelector('.workarounds-list'); - const ANGLEFeaturesDiv = this.querySelector('.angle-features-div'); - const ANGLEFeaturesList = this.querySelector('.angle-features-list'); - const DAWNInfoDiv = this.querySelector('.dawn-info-div'); - const DAWNInfoList = this.querySelector('.dawn-info-list'); - - const basicInfoForHardwareGpuDiv = - this.querySelector('.basic-info-for-hardware-gpu-div'); - const featureStatusForHardwareGpuDiv = - this.querySelector('.feature-status-for-hardware-gpu-div'); - const featureStatusForHardwareGpuList = - this.querySelector('.feature-status-for-hardware-gpu-list'); - const problemsForHardwareGpuDiv = - this.querySelector('.problems-for-hardware-gpu-div'); - const problemsForHardwareGpuList = - this.querySelector('.problems-for-hardware-gpu-list'); - const workaroundsForHardwareGpuDiv = - this.querySelector('.workarounds-for-hardware-gpu-div'); - const workaroundsForHardwareGpuList = - this.querySelector('.workarounds-for-hardware-gpu-list'); - - const gpuInfo = browserBridge.gpuInfo; - let i; - if (gpuInfo) { - // Not using jstemplate here for blocklist status because we construct - // href from data, which jstemplate can't seem to do. - if (gpuInfo.featureStatus) { - this.appendFeatureInfo_( - gpuInfo.featureStatus, featureStatusList, problemsDiv, - problemsList, workaroundsDiv, workaroundsList); - } else { - featureStatusList.textContent = ''; - problemsList.hidden = true; - workaroundsList.hidden = true; - } - - if (gpuInfo.featureStatusForHardwareGpu) { - basicInfoForHardwareGpuDiv.hidden = false; - featureStatusForHardwareGpuDiv.hidden = false; - problemsForHardwareGpuDiv.hidden = false; - workaroundsForHardwareGpuDiv.hidden = false; - this.appendFeatureInfo_( - gpuInfo.featureStatusForHardwareGpu, - featureStatusForHardwareGpuList, problemsForHardwareGpuDiv, - problemsForHardwareGpuList, workaroundsForHardwareGpuDiv, - workaroundsForHardwareGpuList); - if (gpuInfo.basicInfoForHardwareGpu) { - this.setTable_( - 'basic-info-for-hardware-gpu', gpuInfo.basicInfoForHardwareGpu); - } else { - this.setTable_('basic-info-for-hardware-gpu', []); - } - } else { - basicInfoForHardwareGpuDiv.hidden = true; - featureStatusForHardwareGpuDiv.hidden = true; - problemsForHardwareGpuDiv.hidden = true; - workaroundsForHardwareGpuDiv.hidden = true; - } - - if (gpuInfo.basicInfo) { - this.setTable_('basic-info', gpuInfo.basicInfo); - } else { - this.setTable_('basic-info', []); - } - - if (gpuInfo.compositorInfo) { - this.setTable_('compositor-info', gpuInfo.compositorInfo); - } else { - this.setTable_('compositor-info', []); - } - - if (gpuInfo.gpuMemoryBufferInfo) { - this.setTable_('gpu-memory-buffer-info', gpuInfo.gpuMemoryBufferInfo); - } else { - this.setTable_('gpu-memory-buffer-info', []); - } - - if (gpuInfo.displayInfo) { - this.setTable_('display-info', gpuInfo.displayInfo); - } else { - this.setTable_('display-info', []); - } - - if (gpuInfo.videoAcceleratorsInfo) { - this.setTable_( - 'video-acceleration-info', gpuInfo.videoAcceleratorsInfo); - } else { - this.setTable_('video-acceleration-info', []); - } - - if (gpuInfo.ANGLEFeatures) { - if (gpuInfo.ANGLEFeatures.length) { - ANGLEFeaturesDiv.hidden = false; - ANGLEFeaturesList.textContent = ''; - for (const ANGLEFeature of gpuInfo.ANGLEFeatures) { - const ANGLEFeatureEl = this.createANGLEFeatureEl_(ANGLEFeature); - ANGLEFeaturesList.appendChild(ANGLEFeatureEl); - } - } else { - ANGLEFeaturesDiv.hidden = true; - } - } - - if (gpuInfo.dawnInfo) { - if (gpuInfo.dawnInfo.length) { - DAWNInfoDiv.hidden = false; - this.createDawnInfoEl_(DAWNInfoList, gpuInfo.dawnInfo); - } else { - DAWNInfoDiv.hidden = true; - } - } - - if (gpuInfo.diagnostics) { - diagnosticsDiv.hidden = false; - diagnosticsLoadingDiv.hidden = true; - $('diagnostics-table').hidden = false; - this.setTable_('diagnostics-table', gpuInfo.diagnostics); - } else if (gpuInfo.diagnostics === null) { - // gpu_internals.cc sets diagnostics to null when it is being loaded - diagnosticsDiv.hidden = false; - diagnosticsLoadingDiv.hidden = false; - $('diagnostics-table').hidden = true; - } else { - diagnosticsDiv.hidden = true; - } - - if (gpuInfo.vulkanInfo) { - const vulkanInfo = new VulkanInfo(gpuInfo.vulkanInfo); - const data = [{ - 'description': 'info', - 'value': vulkanInfo.toString(), - 'id': 'vulkan-info-value' - }]; - this.setTable_('vulkan-info', data); - } else { - this.setTable_('vulkan-info', []); - } - - if (gpuInfo.devicePerfInfo) { - this.setTable_('device-perf-info', gpuInfo.devicePerfInfo); - } else { - this.setTable_('device-perf-info', []); - } - } else { - this.setText_('basic-info', '... loading ...'); - diagnosticsDiv.hidden = true; featureStatusList.textContent = ''; - problemsDiv.hidden = true; - DAWNInfoDiv.hidden = true; + problemsList.hidden = true; + workaroundsList.hidden = true; } - // Log messages - jstProcess( - new JsEvalContext({values: browserBridge.logMessages}), - $('log-messages')); - }, - - appendFeatureInfo_: function( - featureInfo, featureStatusList, problemsDiv, problemsList, - workaroundsDiv, workaroundsList) { - // Feature map - const featureLabelMap = { - '2d_canvas': 'Canvas', - 'gpu_compositing': 'Compositing', - 'webgl': 'WebGL', - 'multisampling': 'WebGL multisampling', - 'texture_sharing': 'Texture Sharing', - 'video_decode': 'Video Decode', - 'rasterization': 'Rasterization', - 'opengl': 'OpenGL', - 'metal': 'Metal', - 'vulkan': 'Vulkan', - 'multiple_raster_threads': 'Multiple Raster Threads', - 'native_gpu_memory_buffers': 'Native GpuMemoryBuffers', - 'protected_video_decode': 'Hardware Protected Video Decode', - 'surface_control': 'Surface Control', - 'vpx_decode': 'VPx Video Decode', - 'webgl2': 'WebGL2', - 'skia_renderer': 'Skia Renderer', - 'canvas_oop_rasterization': 'Canvas out-of-process rasterization', - 'raw_draw': 'Raw Draw', - 'video_encode': 'Video Encode', - 'direct_rendering_display_compositor': - 'Direct Rendering Display Compositor', - 'webgpu': 'WebGPU', - }; - - const statusMap = { - 'disabled_software': { - 'label': 'Software only. Hardware acceleration disabled', - 'class': 'feature-yellow' - }, - 'disabled_off': {'label': 'Disabled', 'class': 'feature-red'}, - 'disabled_off_ok': {'label': 'Disabled', 'class': 'feature-yellow'}, - 'unavailable_software': { - 'label': 'Software only, hardware acceleration unavailable', - 'class': 'feature-yellow' - }, - 'unavailable_off': {'label': 'Unavailable', 'class': 'feature-red'}, - 'unavailable_off_ok': - {'label': 'Unavailable', 'class': 'feature-yellow'}, - 'enabled_readback': { - 'label': 'Hardware accelerated but at reduced performance', - 'class': 'feature-yellow' - }, - 'enabled_force': { - 'label': 'Hardware accelerated on all pages', - 'class': 'feature-green' - }, - 'enabled': {'label': 'Hardware accelerated', 'class': 'feature-green'}, - 'enabled_on': {'label': 'Enabled', 'class': 'feature-green'}, - 'enabled_force_on': - {'label': 'Force enabled', 'class': 'feature-green'}, - }; - - // feature status list - featureStatusList.textContent = ''; - for (const featureName in featureInfo.featureStatus) { - const featureStatus = featureInfo.featureStatus[featureName]; - const featureEl = document.createElement('li'); - - const nameEl = document.createElement('span'); - if (!featureLabelMap[featureName]) { - console.info('Missing featureLabel for', featureName); - } - nameEl.textContent = featureLabelMap[featureName] + ': '; - featureEl.appendChild(nameEl); - - const statusEl = document.createElement('span'); - const statusInfo = statusMap[featureStatus]; - if (!statusInfo) { - console.info('Missing status for ', featureStatus); - statusEl.textContent = 'Unknown'; - statusEl.className = 'feature-red'; + if (gpuInfo.featureStatusForHardwareGpu) { + basicInfoForHardwareGpuDiv.hidden = false; + featureStatusForHardwareGpuDiv.hidden = false; + problemsForHardwareGpuDiv.hidden = false; + workaroundsForHardwareGpuDiv.hidden = false; + this.appendFeatureInfo_( + gpuInfo.featureStatusForHardwareGpu, + featureStatusForHardwareGpuList, problemsForHardwareGpuDiv, + problemsForHardwareGpuList, workaroundsForHardwareGpuDiv, + workaroundsForHardwareGpuList); + if (gpuInfo.basicInfoForHardwareGpu) { + this.setTable_( + 'basic-info-for-hardware-gpu', gpuInfo.basicInfoForHardwareGpu); } else { - statusEl.textContent = statusInfo['label']; - statusEl.className = statusInfo['class']; - } - featureEl.appendChild(statusEl); - - featureStatusList.appendChild(featureEl); - } - - // problems list - if (featureInfo.problems.length) { - problemsDiv.hidden = false; - problemsList.textContent = ''; - for (const problem of featureInfo.problems) { - const problemEl = this.createProblemEl_(problem); - problemsList.appendChild(problemEl); + this.setTable_('basic-info-for-hardware-gpu', []); } } else { - problemsDiv.hidden = true; + basicInfoForHardwareGpuDiv.hidden = true; + featureStatusForHardwareGpuDiv.hidden = true; + problemsForHardwareGpuDiv.hidden = true; + workaroundsForHardwareGpuDiv.hidden = true; } - // driver bug workarounds list - if (featureInfo.workarounds.length) { - workaroundsDiv.hidden = false; - workaroundsList.textContent = ''; - for (const workaround of featureInfo.workarounds) { - const workaroundEl = document.createElement('li'); - workaroundEl.textContent = workaround; - workaroundsList.appendChild(workaroundEl); - } + if (gpuInfo.basicInfo) { + this.setTable_('basic-info', gpuInfo.basicInfo); } else { - workaroundsDiv.hidden = true; + this.setTable_('basic-info', []); } - }, - createProblemEl_: function(problem) { - const problemEl = document.createElement('li'); - - // Description of issue - const desc = document.createElement('a'); - let text = problem.description; - const pattern = ' Please update your graphics driver via this link: '; - const pos = text.search(pattern); - let url = ''; - if (pos > 0) { - url = text.substring(pos + pattern.length); - text = text.substring(0, pos); + if (gpuInfo.compositorInfo) { + this.setTable_('compositor-info', gpuInfo.compositorInfo); + } else { + this.setTable_('compositor-info', []); } - desc.textContent = text; - problemEl.appendChild(desc); - // Spacing ':' element - if (problem.crBugs.length > 0) { + if (gpuInfo.gpuMemoryBufferInfo) { + this.setTable_('gpu-memory-buffer-info', gpuInfo.gpuMemoryBufferInfo); + } else { + this.setTable_('gpu-memory-buffer-info', []); + } + + if (gpuInfo.displayInfo) { + this.setTable_('display-info', gpuInfo.displayInfo); + } else { + this.setTable_('display-info', []); + } + + if (gpuInfo.videoAcceleratorsInfo) { + this.setTable_( + 'video-acceleration-info', gpuInfo.videoAcceleratorsInfo); + } else { + this.setTable_('video-acceleration-info', []); + } + + if (gpuInfo.ANGLEFeatures) { + if (gpuInfo.ANGLEFeatures.length) { + ANGLEFeaturesDiv.hidden = false; + ANGLEFeaturesList.textContent = ''; + for (const ANGLEFeature of gpuInfo.ANGLEFeatures) { + const ANGLEFeatureEl = this.createANGLEFeatureEl_(ANGLEFeature); + ANGLEFeaturesList.appendChild(ANGLEFeatureEl); + } + } else { + ANGLEFeaturesDiv.hidden = true; + } + } + + if (gpuInfo.dawnInfo) { + if (gpuInfo.dawnInfo.length) { + DAWNInfoDiv.hidden = false; + this.createDawnInfoEl_(DAWNInfoList, gpuInfo.dawnInfo); + } else { + DAWNInfoDiv.hidden = true; + } + } + + if (gpuInfo.diagnostics) { + diagnosticsDiv.hidden = false; + diagnosticsLoadingDiv.hidden = true; + this.shadowRoot.querySelector('#diagnostics-table').hidden = false; + this.setTable_('diagnostics-table', gpuInfo.diagnostics); + } else if (gpuInfo.diagnostics === null) { + // gpu_internals.cc sets diagnostics to null when it is being loaded + diagnosticsDiv.hidden = false; + diagnosticsLoadingDiv.hidden = false; + this.shadowRoot.querySelector('#diagnostics-table').hidden = true; + } else { + diagnosticsDiv.hidden = true; + } + + if (gpuInfo.vulkanInfo) { + const vulkanInfo = new VulkanInfo(gpuInfo.vulkanInfo); + const data = [{ + 'description': 'info', + 'value': vulkanInfo.toString(), + 'id': 'vulkan-info-value' + }]; + this.setTable_('vulkan-info', data); + } else { + this.setTable_('vulkan-info', []); + } + + if (gpuInfo.devicePerfInfo) { + this.setTable_('device-perf-info', gpuInfo.devicePerfInfo); + } else { + this.setTable_('device-perf-info', []); + } + } else { + this.setText_('basic-info', '... loading ...'); + diagnosticsDiv.hidden = true; + featureStatusList.textContent = ''; + problemsDiv.hidden = true; + DAWNInfoDiv.hidden = true; + } + + // Log messages + const messageList = this.shadowRoot.querySelector('#log-messages > ul'); + messageList.innerHTML = + window.trustedTypes ? window.trustedTypes.emptyHTML : ''; + browserBridge.logMessages.forEach(messageObj => { + const messageEl = document.createElement('span'); + messageEl.textContent = `${messageObj.header}: ${messageObj.message}`; + const li = document.createElement('li'); + li.appendChild(messageEl); + messageList.appendChild(li); + }); + } + + appendFeatureInfo_( + featureInfo, featureStatusList, problemsDiv, problemsList, workaroundsDiv, + workaroundsList) { + // Feature map + const featureLabelMap = { + '2d_canvas': 'Canvas', + 'gpu_compositing': 'Compositing', + 'webgl': 'WebGL', + 'multisampling': 'WebGL multisampling', + 'texture_sharing': 'Texture Sharing', + 'video_decode': 'Video Decode', + 'rasterization': 'Rasterization', + 'opengl': 'OpenGL', + 'metal': 'Metal', + 'vulkan': 'Vulkan', + 'multiple_raster_threads': 'Multiple Raster Threads', + 'native_gpu_memory_buffers': 'Native GpuMemoryBuffers', + 'protected_video_decode': 'Hardware Protected Video Decode', + 'surface_control': 'Surface Control', + 'vpx_decode': 'VPx Video Decode', + 'webgl2': 'WebGL2', + 'skia_renderer': 'Skia Renderer', + 'canvas_oop_rasterization': 'Canvas out-of-process rasterization', + 'raw_draw': 'Raw Draw', + 'video_encode': 'Video Encode', + 'direct_rendering_display_compositor': + 'Direct Rendering Display Compositor', + 'webgpu': 'WebGPU', + }; + + const statusMap = { + 'disabled_software': { + 'label': 'Software only. Hardware acceleration disabled', + 'class': 'feature-yellow' + }, + 'disabled_off': {'label': 'Disabled', 'class': 'feature-red'}, + 'disabled_off_ok': {'label': 'Disabled', 'class': 'feature-yellow'}, + 'unavailable_software': { + 'label': 'Software only, hardware acceleration unavailable', + 'class': 'feature-yellow' + }, + 'unavailable_off': {'label': 'Unavailable', 'class': 'feature-red'}, + 'unavailable_off_ok': {'label': 'Unavailable', 'class': 'feature-yellow'}, + 'enabled_readback': { + 'label': 'Hardware accelerated but at reduced performance', + 'class': 'feature-yellow' + }, + 'enabled_force': { + 'label': 'Hardware accelerated on all pages', + 'class': 'feature-green' + }, + 'enabled': {'label': 'Hardware accelerated', 'class': 'feature-green'}, + 'enabled_on': {'label': 'Enabled', 'class': 'feature-green'}, + 'enabled_force_on': {'label': 'Force enabled', 'class': 'feature-green'}, + }; + + // feature status list + featureStatusList.textContent = ''; + for (const featureName in featureInfo.featureStatus) { + const featureStatus = featureInfo.featureStatus[featureName]; + const featureEl = document.createElement('li'); + + const nameEl = document.createElement('span'); + if (!featureLabelMap[featureName]) { + console.info('Missing featureLabel for', featureName); + } + nameEl.textContent = featureLabelMap[featureName] + ': '; + featureEl.appendChild(nameEl); + + const statusEl = document.createElement('span'); + const statusInfo = statusMap[featureStatus]; + if (!statusInfo) { + console.info('Missing status for ', featureStatus); + statusEl.textContent = 'Unknown'; + statusEl.className = 'feature-red'; + } else { + statusEl.textContent = statusInfo['label']; + statusEl.className = statusInfo['class']; + } + featureEl.appendChild(statusEl); + + featureStatusList.appendChild(featureEl); + } + + // problems list + if (featureInfo.problems.length) { + problemsDiv.hidden = false; + problemsList.textContent = ''; + for (const problem of featureInfo.problems) { + const problemEl = this.createProblemEl_(problem); + problemsList.appendChild(problemEl); + } + } else { + problemsDiv.hidden = true; + } + + // driver bug workarounds list + if (featureInfo.workarounds.length) { + workaroundsDiv.hidden = false; + workaroundsList.textContent = ''; + for (const workaround of featureInfo.workarounds) { + const workaroundEl = document.createElement('li'); + workaroundEl.textContent = workaround; + workaroundsList.appendChild(workaroundEl); + } + } else { + workaroundsDiv.hidden = true; + } + } + + createProblemEl_(problem) { + const problemEl = document.createElement('li'); + + // Description of issue + const desc = document.createElement('a'); + let text = problem.description; + const pattern = ' Please update your graphics driver via this link: '; + const pos = text.search(pattern); + let url = ''; + if (pos > 0) { + url = text.substring(pos + pattern.length); + text = text.substring(0, pos); + } + desc.textContent = text; + problemEl.appendChild(desc); + + // Spacing ':' element + if (problem.crBugs.length > 0) { + const tmp = document.createElement('span'); + tmp.textContent = ': '; + problemEl.appendChild(tmp); + } + + let nbugs = 0; + let j; + + // crBugs + for (j = 0; j < problem.crBugs.length; ++j) { + if (nbugs > 0) { const tmp = document.createElement('span'); - tmp.textContent = ': '; + tmp.textContent = ', '; problemEl.appendChild(tmp); } - let nbugs = 0; - let j; + const link = document.createElement('a'); + const bugid = parseInt(problem.crBugs[j]); + link.textContent = bugid; + link.href = 'http://crbug.com/' + bugid; + problemEl.appendChild(link); + nbugs++; + } - // crBugs - for (j = 0; j < problem.crBugs.length; ++j) { - if (nbugs > 0) { - const tmp = document.createElement('span'); - tmp.textContent = ', '; - problemEl.appendChild(tmp); - } + if (problem.affectedGpuSettings.length > 0) { + const brNode = document.createElement('br'); + problemEl.appendChild(brNode); - const link = document.createElement('a'); - const bugid = parseInt(problem.crBugs[j]); - link.textContent = bugid; - link.href = 'http://crbug.com/' + bugid; - problemEl.appendChild(link); - nbugs++; + const iNode = document.createElement('i'); + problemEl.appendChild(iNode); + + const headNode = document.createElement('span'); + if (problem.tag === 'disabledFeatures') { + headNode.textContent = 'Disabled Features: '; + } else { // problem.tag === 'workarounds' + headNode.textContent = 'Applied Workarounds: '; } - - if (problem.affectedGpuSettings.length > 0) { - const brNode = document.createElement('br'); - problemEl.appendChild(brNode); - - const iNode = document.createElement('i'); - problemEl.appendChild(iNode); - - const headNode = document.createElement('span'); + iNode.appendChild(headNode); + for (j = 0; j < problem.affectedGpuSettings.length; ++j) { + if (j > 0) { + const separateNode = document.createElement('span'); + separateNode.textContent = ', '; + iNode.appendChild(separateNode); + } + const nameNode = document.createElement('span'); if (problem.tag === 'disabledFeatures') { - headNode.textContent = 'Disabled Features: '; + nameNode.classList.add('feature-red'); } else { // problem.tag === 'workarounds' - headNode.textContent = 'Applied Workarounds: '; + nameNode.classList.add('feature-yellow'); } - iNode.appendChild(headNode); - for (j = 0; j < problem.affectedGpuSettings.length; ++j) { - if (j > 0) { - const separateNode = document.createElement('span'); - separateNode.textContent = ', '; - iNode.appendChild(separateNode); - } - const nameNode = document.createElement('span'); - if (problem.tag === 'disabledFeatures') { - nameNode.classList.add('feature-red'); - } else { // problem.tag === 'workarounds' - nameNode.classList.add('feature-yellow'); - } - nameNode.textContent = problem.affectedGpuSettings[j]; - iNode.appendChild(nameNode); - } + nameNode.textContent = problem.affectedGpuSettings[j]; + iNode.appendChild(nameNode); } + } - // Append driver update link. - if (pos > 0) { - const brNode = document.createElement('br'); - problemEl.appendChild(brNode); + // Append driver update link. + if (pos > 0) { + const brNode = document.createElement('br'); + problemEl.appendChild(brNode); - const bNode = document.createElement('b'); - bNode.classList.add('bg-yellow'); - problemEl.appendChild(bNode); + const bNode = document.createElement('b'); + bNode.classList.add('bg-yellow'); + problemEl.appendChild(bNode); - const tmp = document.createElement('span'); - tmp.textContent = 'Please update your graphics driver via '; - bNode.appendChild(tmp); + const tmp = document.createElement('span'); + tmp.textContent = 'Please update your graphics driver via '; + bNode.appendChild(tmp); - const link = document.createElement('a'); - link.textContent = 'this link'; - link.href = url; - bNode.appendChild(link); - } + const link = document.createElement('a'); + link.textContent = 'this link'; + link.href = url; + bNode.appendChild(link); + } - return problemEl; - }, + return problemEl; + } - createANGLEFeatureEl_: function(ANGLEFeature) { - const ANGLEFeatureEl = document.createElement('li'); + createANGLEFeatureEl_(ANGLEFeature) { + const ANGLEFeatureEl = document.createElement('li'); - // Name comes first, bolded - const name = document.createElement('b'); - name.textContent = ANGLEFeature.name; - ANGLEFeatureEl.appendChild(name); + // Name comes first, bolded + const name = document.createElement('b'); + name.textContent = ANGLEFeature.name; + ANGLEFeatureEl.appendChild(name); - // If there's a category, it follows the name in parentheses - if (ANGLEFeature.category) { - const separator = document.createElement('span'); - separator.textContent = ' '; - ANGLEFeatureEl.appendChild(separator); - - const category = document.createElement('span'); - category.textContent = '(' + ANGLEFeature.category + ')'; - ANGLEFeatureEl.appendChild(category); - } - - // If there's a bug link, try to parse the crbug/anglebug number - if (ANGLEFeature.bug) { - const separator = document.createElement('span'); - separator.textContent = ' '; - ANGLEFeatureEl.appendChild(separator); - - const bug = document.createElement('a'); - if (ANGLEFeature.bug.includes('crbug.com/')) { - bug.textContent = ANGLEFeature.bug.match(/\d+/); - } else if (ANGLEFeature.bug.includes('anglebug.com/')) { - bug.textContent = 'anglebug:' + ANGLEFeature.bug.match(/\d+/); - } else { - bug.textContent = ANGLEFeature.bug; - } - bug.href = ANGLEFeature.bug; - ANGLEFeatureEl.appendChild(bug); - } - - // Follow with a colon, and the status (colored) + // If there's a category, it follows the name in parentheses + if (ANGLEFeature.category) { const separator = document.createElement('span'); - separator.textContent = ': '; + separator.textContent = ' '; ANGLEFeatureEl.appendChild(separator); - const status = document.createElement('span'); - if (ANGLEFeature.status === 'enabled') { - status.textContent = 'Enabled'; - status.classList.add('feature-green'); + const category = document.createElement('span'); + category.textContent = '(' + ANGLEFeature.category + ')'; + ANGLEFeatureEl.appendChild(category); + } + + // If there's a bug link, try to parse the crbug/anglebug number + if (ANGLEFeature.bug) { + const separator = document.createElement('span'); + separator.textContent = ' '; + ANGLEFeatureEl.appendChild(separator); + + const bug = document.createElement('a'); + if (ANGLEFeature.bug.includes('crbug.com/')) { + bug.textContent = ANGLEFeature.bug.match(/\d+/); + } else if (ANGLEFeature.bug.includes('anglebug.com/')) { + bug.textContent = 'anglebug:' + ANGLEFeature.bug.match(/\d+/); } else { - status.textContent = 'Disabled'; - status.classList.add('feature-red'); + bug.textContent = ANGLEFeature.bug; } - ANGLEFeatureEl.appendChild(status); + bug.href = ANGLEFeature.bug; + ANGLEFeatureEl.appendChild(bug); + } - if (ANGLEFeature.condition) { - const condition = document.createElement('span'); - condition.textContent = ': ' + ANGLEFeature.condition; - condition.classList.add('feature-gray'); - ANGLEFeatureEl.appendChild(condition); - } + // Follow with a colon, and the status (colored) + const separator = document.createElement('span'); + separator.textContent = ': '; + ANGLEFeatureEl.appendChild(separator); - // if there's a description, put on new line, italicized - if (ANGLEFeature.description) { - const brNode = document.createElement('br'); - ANGLEFeatureEl.appendChild(brNode); + const status = document.createElement('span'); + if (ANGLEFeature.status === 'enabled') { + status.textContent = 'Enabled'; + status.classList.add('feature-green'); + } else { + status.textContent = 'Disabled'; + status.classList.add('feature-red'); + } + ANGLEFeatureEl.appendChild(status); - const iNode = document.createElement('i'); - ANGLEFeatureEl.appendChild(iNode); + if (ANGLEFeature.condition) { + const condition = document.createElement('span'); + condition.textContent = ': ' + ANGLEFeature.condition; + condition.classList.add('feature-gray'); + ANGLEFeatureEl.appendChild(condition); + } - const description = document.createElement('span'); - description.textContent = ANGLEFeature.description; - iNode.appendChild(description); - } + // if there's a description, put on new line, italicized + if (ANGLEFeature.description) { + const brNode = document.createElement('br'); + ANGLEFeatureEl.appendChild(brNode); - return ANGLEFeatureEl; - }, + const iNode = document.createElement('i'); + ANGLEFeatureEl.appendChild(iNode); - setText_: function(outputElementId, text) { - const peg = $(outputElementId); - peg.textContent = text; - }, + const description = document.createElement('span'); + description.textContent = ANGLEFeature.description; + iNode.appendChild(description); + } - setTable_: function(outputElementId, inputData) { - const template = jstGetTemplate('info-view-table-template'); - jstProcess(new JsEvalContext({value: inputData}), template); + return ANGLEFeatureEl; + } - const peg = $(outputElementId); - if (!peg) { - throw new Error('Node ' + outputElementId + ' not found'); - } + setText_(outputElementId, text) { + const peg = this.shadowRoot.querySelector(`#${outputElementId}`); + peg.textContent = text; + } - peg.innerHTML = trustedTypes.emptyHTML; - peg.appendChild(template); - }, + setTable_(outputElementId, inputData) { + const table = document.createElement('info-view-table'); + table.setData(inputData); - createDawnInfoEl_: function(DAWNInfoList, gpuDawnInfo) { - DAWNInfoList.textContent = ''; - let inProcessingToggles = false; + const peg = this.shadowRoot.querySelector(`#${outputElementId}`); + if (!peg) { + throw new Error('Node ' + outputElementId + ' not found'); + } - for (let i = 0; i < gpuDawnInfo.length; ++i) { - let infoString = gpuDawnInfo[i]; - let infoEl; + peg.innerHTML = window.trustedTypes.emptyHTML; + peg.appendChild(table); + } - if (infoString.startsWith('<')) { - // GPU type and backend type. - // Add an empty line for the next adaptor. - const separator = document.createElement('br'); - separator.textContent = ''; - DAWNInfoList.appendChild(separator); + createDawnInfoEl_(DAWNInfoList, gpuDawnInfo) { + DAWNInfoList.textContent = ''; + let inProcessingToggles = false; - // e.g. <Discrete GPU> D3D12 backend - infoEl = document.createElement('b'); - infoEl.textContent = infoString; - DAWNInfoList.appendChild(infoEl); - // Go to the next line. - infoEl = document.createElement('br'); - infoEl.textContent = ''; - inProcessingToggles = false; - } else if (infoString.startsWith('[')) { - // e.g. [Default Toggle Names] - infoEl = document.createElement('span'); - infoEl.classList.add('feature-green'); - infoEl.textContent = infoString; + for (let i = 0; i < gpuDawnInfo.length; ++i) { + let infoString = gpuDawnInfo[i]; + let infoEl; - if (infoString === '[Supported Features]') { - inProcessingToggles = false; - } else { - inProcessingToggles = true; - } - } else if (inProcessingToggles) { - // Each toggle takes 3 strings - infoEl = document.createElement('li'); + if (infoString.startsWith('<')) { + // GPU type and backend type. + // Add an empty line for the next adaptor. + const separator = document.createElement('br'); + separator.textContent = ''; + DAWNInfoList.appendChild(separator); - // The toggle name comes first, bolded. - const name = document.createElement('b'); - name.textContent = infoString + ': '; - infoEl.appendChild(name); - - // URL - infoString = gpuDawnInfo[++i]; - const url = document.createElement('a'); - url.textContent = infoString; - url.href = infoString; - infoEl.appendChild(url); - - // Description, italicized - infoString = gpuDawnInfo[++i]; - const description = document.createElement('i'); - description.textContent = ': ' + infoString; - infoEl.appendChild(description); - } else { - // Display supported extensions - infoEl = document.createElement('li'); - infoEl.textContent = infoString; - } - + // e.g. <Discrete GPU> D3D12 backend + infoEl = document.createElement('b'); + infoEl.textContent = infoString; DAWNInfoList.appendChild(infoEl); - } - }, - }; + // Go to the next line. + infoEl = document.createElement('br'); + infoEl.textContent = ''; + inProcessingToggles = false; + } else if (infoString.startsWith('[')) { + // e.g. [Default Toggle Names] + infoEl = document.createElement('span'); + infoEl.classList.add('feature-green'); + infoEl.textContent = infoString; - return InfoView; + if (infoString === '[Supported Features]') { + inProcessingToggles = false; + } else { + inProcessingToggles = true; + } + } else if (inProcessingToggles) { + // Each toggle takes 3 strings + infoEl = document.createElement('li'); + + // The toggle name comes first, bolded. + const name = document.createElement('b'); + name.textContent = infoString + ': '; + infoEl.appendChild(name); + + // URL + infoString = gpuDawnInfo[++i]; + const url = document.createElement('a'); + url.textContent = infoString; + url.href = infoString; + infoEl.appendChild(url); + + // Description, italicized + infoString = gpuDawnInfo[++i]; + const description = document.createElement('i'); + description.textContent = ': ' + infoString; + infoEl.appendChild(description); + } else { + // Display supported extensions + infoEl = document.createElement('li'); + infoEl.textContent = infoString; + } + + DAWNInfoList.appendChild(infoEl); + } + } } + +customElements.define('info-view', InfoViewElement);
diff --git a/content/browser/resources/gpu/info_view_table.html b/content/browser/resources/gpu/info_view_table.html new file mode 100644 index 0000000..a29cbd35 --- /dev/null +++ b/content/browser/resources/gpu/info_view_table.html
@@ -0,0 +1,12 @@ +<style> + :host { + display: flex; + cursor: auto; + width: 100%; + } + + div { + width: 100%; + } +</style> +<div id="info-view-table"></div>
diff --git a/content/browser/resources/gpu/info_view_table.js b/content/browser/resources/gpu/info_view_table.js new file mode 100644 index 0000000..07e5f69 --- /dev/null +++ b/content/browser/resources/gpu/info_view_table.js
@@ -0,0 +1,24 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import './info_view_table_row.js'; + +import {CustomElement} from 'chrome://resources/js/custom_element.js'; +import {getTrustedHTML} from 'chrome://resources/js/static_types.js'; + +export class InfoViewTableElement extends CustomElement { + static get template() { + return getTrustedHTML`{__html_template__}`; + } + + setData(dataArray) { + dataArray.forEach(data => { + const row = document.createElement('info-view-table-row'); + row.setData(data); + this.shadowRoot.querySelector('#info-view-table').appendChild(row); + }); + } +} + +customElements.define('info-view-table', InfoViewTableElement);
diff --git a/content/browser/resources/gpu/info_view_table_row.html b/content/browser/resources/gpu/info_view_table_row.html new file mode 100644 index 0000000..4fd6046 --- /dev/null +++ b/content/browser/resources/gpu/info_view_table_row.html
@@ -0,0 +1,48 @@ +<style> + :host { + border: none; + display: flex; + } + + #array { + width: 100%; + } + + #title { + overflow-x: auto; + width: 25%; + } + + #value { + overflow-x: auto; + width: 75%; + } + + :host(:not([is-array])) #array { + display: none; + } + + :host([is-array]) #title, + :host([is-array]) #value { + display: none; + } + + div { + border: 1px solid #777; + margin-inline-end: -1px; + margin-top: -1px; + } + + .row-title { + font-weight: bold; + } +</style> +<div id="title"> + <span class="row-title">title</span> +</div> +<div id="value"> + <span>value</span> +</div> +<div id="array"> + <span class="row-title"></span> +</div>
diff --git a/content/browser/resources/gpu/info_view_table_row.js b/content/browser/resources/gpu/info_view_table_row.js new file mode 100644 index 0000000..e569662d --- /dev/null +++ b/content/browser/resources/gpu/info_view_table_row.js
@@ -0,0 +1,39 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {CustomElement} from 'chrome://resources/js/custom_element.js'; +import {getTrustedHTML} from 'chrome://resources/js/static_types.js'; + +export class InfoViewTableRowElement extends CustomElement { + static get template() { + return getTrustedHTML`{__html_template__}`; + } + + constructor() { + super(); + + this.data = null; + } + + setData(data) { + const isArray = data.value instanceof Array; + this.toggleAttribute('is-array', isArray); + if (!isArray) { + this.shadowRoot.querySelector('.row-title').textContent = + data.description; + this.shadowRoot.querySelector('#value > span').textContent = data.value; + this.shadowRoot.querySelector('#value > span').id = data.id; + } else { + const array = this.shadowRoot.querySelector('#array'); + array.querySelector('span').textContent = data.description; + data.value.forEach(value => { + const row = document.createElement('info-view-table-row'); + row.setData(value); + array.appendChild(row); + }); + } + } +} + +customElements.define('info-view-table-row', InfoViewTableRowElement);
diff --git a/content/browser/screen_enumeration/screen_enumeration_browsertest.cc b/content/browser/screen_enumeration/screen_enumeration_browsertest.cc index 6267f67..feb76c9 100644 --- a/content/browser/screen_enumeration/screen_enumeration_browsertest.cc +++ b/content/browser/screen_enumeration/screen_enumeration_browsertest.cc
@@ -135,18 +135,26 @@ protected: // ScreenEnumerationTest: - void SetUpOnMainThread() override { - ScreenEnumerationTest::SetUpOnMainThread(); - original_screen_ = display::Screen::GetScreen(); - display::Screen::SetScreenInstance(&screen_); + void SetUp() override { + display::Screen::SetScreenInstance(&screen_); // Create a shell that observes the fake screen. A display is required. screen()->display_list().AddDisplay({0, gfx::Rect(100, 100, 801, 802)}, display::DisplayList::Type::PRIMARY); + + ScreenEnumerationTest::SetUp(); + } + void TearDown() override { + ScreenEnumerationTest::TearDown(); + display::Screen::SetScreenInstance(nullptr); + } + + void SetUpOnMainThread() override { + ScreenEnumerationTest::SetUpOnMainThread(); + test_shell_ = CreateBrowser(); } void TearDownOnMainThread() override { - display::Screen::SetScreenInstance(original_screen_); ScreenEnumerationTest::TearDownOnMainThread(); } @@ -154,7 +162,6 @@ Shell* test_shell() { return test_shell_; } private: - raw_ptr<display::Screen> original_screen_ = nullptr; display::ScreenBase screen_; raw_ptr<Shell> test_shell_ = nullptr; };
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc index 025bef9..127ad11 100644 --- a/content/browser/service_worker/embedded_worker_instance.cc +++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -558,8 +558,10 @@ // The host must be alive as long as |params->provider_info| is alive. owner_version_->worker_host()->CompleteStartWorkerPreparation( - process_id(), params->provider_info->browser_interface_broker - .InitWithNewPipeAndPassReceiver()); + process_id(), + params->provider_info->browser_interface_broker + .InitWithNewPipeAndPassReceiver(), + params->interface_provider.InitWithNewPipeAndPassRemote()); // TODO(bashi): Always pass a valid outside fetch client settings object. // See crbug.com/937177.
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index 9aba6de..8bc9112 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -843,6 +843,23 @@ return running_service_workers_; } +service_manager::InterfaceProvider* +ServiceWorkerContextWrapper::GetRemoteInterfaces( + int64_t service_worker_version_id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (!context()) + return nullptr; + + auto* version = context()->GetLiveVersion(service_worker_version_id); + if (!version) + return nullptr; + + CHECK(version->running_status() == EmbeddedWorkerStatus::STARTING || + version->running_status() == EmbeddedWorkerStatus::RUNNING); + + return &version->worker_host()->remote_interfaces(); +} + scoped_refptr<ServiceWorkerRegistration> ServiceWorkerContextWrapper::GetLiveRegistration(int64_t registration_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h index b88e2809..6bb75b6d 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.h +++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -208,6 +208,8 @@ void StopAllServiceWorkers(base::OnceClosure callback) override; const base::flat_map<int64_t, ServiceWorkerRunningInfo>& GetRunningServiceWorkerInfos() override; + service_manager::InterfaceProvider* GetRemoteInterfaces( + int64_t service_worker_version_id) override; scoped_refptr<ServiceWorkerRegistration> GetLiveRegistration( int64_t registration_id);
diff --git a/content/browser/service_worker/service_worker_host.cc b/content/browser/service_worker/service_worker_host.cc index 8efd4a2..33af82d 100644 --- a/content/browser/service_worker/service_worker_host.cc +++ b/content/browser/service_worker/service_worker_host.cc
@@ -65,13 +65,15 @@ void ServiceWorkerHost::CompleteStartWorkerPreparation( int process_id, - mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> - broker_receiver) { + mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> broker_receiver, + mojo::PendingRemote<service_manager::mojom::InterfaceProvider> + interface_provider_remote) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, worker_process_id_); DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id); worker_process_id_ = process_id; broker_receiver_.Bind(std::move(broker_receiver)); + remote_interfaces_.Bind(std::move(interface_provider_remote)); } void ServiceWorkerHost::CreateWebTransportConnector(
diff --git a/content/browser/service_worker/service_worker_host.h b/content/browser/service_worker/service_worker_host.h index 7e3d08f..f1658ed 100644 --- a/content/browser/service_worker/service_worker_host.h +++ b/content/browser/service_worker/service_worker_host.h
@@ -27,6 +27,7 @@ #include "net/base/network_isolation_key.h" #include "services/network/public/mojom/fetch_api.mojom.h" #include "services/network/public/mojom/network_context.mojom.h" +#include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/mojom/broadcastchannel/broadcast_channel.mojom.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h" #include "third_party/blink/public/mojom/loader/code_cache.mojom.h" @@ -63,12 +64,18 @@ int worker_process_id() const { return worker_process_id_; } ServiceWorkerVersion* version() const { return version_; } + service_manager::InterfaceProvider& remote_interfaces() { + return remote_interfaces_; + } + // Completes initialization of this provider host. It is called once a // renderer process has been found to host the worker. void CompleteStartWorkerPreparation( int process_id, mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> - broker_receiver); + broker_receiver, + mojo::PendingRemote<service_manager::mojom::InterfaceProvider> + interface_provider_remote); void CreateWebTransportConnector( mojo::PendingReceiver<blink::mojom::WebTransportConnector> receiver); @@ -117,6 +124,9 @@ std::unique_ptr<ServiceWorkerContainerHost> container_host_; + service_manager::InterfaceProvider remote_interfaces_{ + base::ThreadTaskRunnerHandle::Get()}; + // CodeCacheHost processes requests to fetch / write generated code for // JavaScript / WebAssembly resources. std::unique_ptr<CodeCacheHostImpl::ReceiverSet> code_cache_host_receivers_;
diff --git a/content/browser/service_worker/service_worker_test_utils.cc b/content/browser/service_worker/service_worker_test_utils.cc index 272c9200..86ccb48 100644 --- a/content/browser/service_worker/service_worker_test_utils.cc +++ b/content/browser/service_worker/service_worker_test_utils.cc
@@ -365,9 +365,13 @@ provider_info->host_remote.InitWithNewEndpointAndPassReceiver(), hosted_version, std::move(context)); + mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> + pending_interface_provider; + host->CompleteStartWorkerPreparation( process_id, - provider_info->browser_interface_broker.InitWithNewPipeAndPassReceiver()); + provider_info->browser_interface_broker.InitWithNewPipeAndPassReceiver(), + pending_interface_provider.InitWithNewPipeAndPassRemote()); output_endpoint->BindForServiceWorker(std::move(provider_info)); return host; }
diff --git a/content/browser/shared_storage/shared_storage_browsertest.cc b/content/browser/shared_storage/shared_storage_browsertest.cc index 72fe7fe..56bcbb63 100644 --- a/content/browser/shared_storage/shared_storage_browsertest.cc +++ b/content/browser/shared_storage/shared_storage_browsertest.cc
@@ -383,11 +383,11 @@ WebContentsConsoleObserver console_observer(shell()->web_contents()); std::string expected_error = base::StrCat( - {"a JavaScript error:\nError: Failed to load ", + {"a JavaScript error: \"Error: Failed to load ", https_server() ->GetURL("a.test", "/shared_storage/nonexistent_module.js") .spec(), - " HTTP status = 404 Not Found.\n"}); + " HTTP status = 404 Not Found.\"\n"}); EvalJsResult result = EvalJs(shell(), R"( sharedStorage.worklet.addModule('shared_storage/nonexistent_module.js'); @@ -407,12 +407,12 @@ WebContentsConsoleObserver console_observer(shell()->web_contents()); std::string expected_error = base::StrCat( - {"a JavaScript error:\nError: Unexpected redirect on ", + {"a JavaScript error: \"Error: Unexpected redirect on ", https_server() ->GetURL("a.test", "/server-redirect?shared_storage/simple_module.js") .spec(), - ".\n"}); + ".\"\n"}); EvalJsResult result = EvalJs(shell(), R"( sharedStorage.worklet.addModule( @@ -434,11 +434,11 @@ WebContentsConsoleObserver console_observer(shell()->web_contents()); std::string expected_error = base::StrCat( - {"a JavaScript error:\nError: ", + {"a JavaScript error: \"Error: ", https_server() ->GetURL("a.test", "/shared_storage/erroneous_module.js") .spec(), - ":6 Uncaught ReferenceError: undefinedVariable is not defined.\n"}); + ":6 Uncaught ReferenceError: undefinedVariable is not defined.\"\n"}); EvalJsResult result = EvalJs(shell(), R"( sharedStorage.worklet.addModule('shared_storage/erroneous_module.js'); @@ -465,8 +465,8 @@ )")); std::string expected_error = - "a JavaScript error:\nError: sharedStorage.worklet.addModule() can only " - "be invoked once per browsing context.\n"; + "a JavaScript error: \"Error: sharedStorage.worklet.addModule() can only " + "be invoked once per browsing context.\"\n"; EvalJsResult result = EvalJs(shell(), R"( sharedStorage.worklet.addModule('shared_storage/simple_module.js'); @@ -573,12 +573,11 @@ )"); EXPECT_EQ( - std::string( - "a JavaScript error:\nError: function testFunction() {} could not be " - "cloned.\n at eval (__const_std::string&_script__:4:21):\n " - " .then((result) => true ? result : Promise.reject(),\n " - " ^^^^^\n at eval (<anonymous>)\n at " - "EvalJs-runner.js:2:34\n"), + std::string("a JavaScript error: \"" + "Error: function testFunction() {} could not be cloned.\n" + " at __const_std::string&_script__:4:21):\n" + " sharedStorage.run(\n" + " ^^^^^\n"), result.error); }
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index b94e87b6..0ae2131 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3399,6 +3399,7 @@ OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::EnterFullscreenMode"); DCHECK(CanEnterFullscreenMode(requesting_frame, options)); DCHECK(requesting_frame->IsActive()); + DCHECK(ContainsOrIsFocusedWebContents()); if (delegate_) { delegate_->EnterFullscreenModeForTab(requesting_frame, options);
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc index 781b7dd0..df80043e 100644 --- a/content/browser/webauth/authenticator_common.cc +++ b/content/browser/webauth/authenticator_common.cc
@@ -549,16 +549,6 @@ BeginRequestTimeout(options->timeout); - if (options->remote_desktop_client_override) { - // WebAuthRequestSecurityChecker will validate whether use of the extension - // is authorized. - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kWebAuthRemoteDesktopSupport)) { - mojo::ReportBadMessage("--webauthn-remote-desktop-support not enabled"); - return; - } - } - WebAuthRequestSecurityChecker::RequestType request_type = options->is_payment_credential_creation ? WebAuthRequestSecurityChecker::RequestType::kMakePaymentCredential @@ -866,16 +856,6 @@ DCHECK(get_assertion_response_callback_.is_null()); get_assertion_response_callback_ = std::move(callback); - if (options->remote_desktop_client_override) { - // WebAuthRequestSecurityChecker will validate whether use of the extension - // is authorized. - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kWebAuthRemoteDesktopSupport)) { - mojo::ReportBadMessage("--webauthn-remote-desktop-support not enabled"); - return; - } - } - if (!options->is_conditional) { BeginRequestTimeout(options->timeout); }
diff --git a/content/browser/webui/web_ui_browsertest.cc b/content/browser/webui/web_ui_browsertest.cc index e1d0ed9..310d7c77 100644 --- a/content/browser/webui/web_ui_browsertest.cc +++ b/content/browser/webui/web_ui_browsertest.cc
@@ -653,8 +653,8 @@ GetWebUIURL("test-host/web_ui_shared_worker.js"), kLoadSharedWorkerScript); - std::string expected_failure = R"(a JavaScript error: -Error: Failed to construct 'SharedWorker')"; + std::string expected_failure = + "a JavaScript error: \"Error: Failed to construct 'SharedWorker'"; EXPECT_THAT(result.error, ::testing::StartsWith(expected_failure)); } @@ -728,7 +728,7 @@ kLoadSharedWorkerScript); std::string expected_failure = - "a JavaScript error:\nError: Failed to construct 'SharedWorker': " + "a JavaScript error: \"Error: Failed to construct 'SharedWorker': " "Script at 'chrome-untrusted://untrusted/web_ui_shared_worker.js' cannot " "be accessed from origin 'chrome://trusted'"; EXPECT_THAT(result.error, ::testing::StartsWith(expected_failure)); @@ -746,7 +746,7 @@ kLoadSharedWorkerScript); std::string expected_failure = - "a JavaScript error:\nError: Failed to construct 'SharedWorker': " + "a JavaScript error: \"Error: Failed to construct 'SharedWorker': " "Script at 'chrome-untrusted://untrusted/web_ui_shared_worker.js' cannot " "be accessed from origin 'http://localhost"; EXPECT_THAT(result.error, ::testing::StartsWith(expected_failure)); @@ -763,7 +763,7 @@ GetWebUIURL("trusted/web_ui_shared_worker.js"), kLoadSharedWorkerScript); std::string expected_failure = - "a JavaScript error:\nError: Failed to construct 'SharedWorker': Script " + "a JavaScript error: \"Error: Failed to construct 'SharedWorker': Script " "at 'chrome://trusted/web_ui_shared_worker.js' cannot be accessed from " "origin 'chrome-untrusted://untrusted'."; EXPECT_THAT(result.error, ::testing::StartsWith(expected_failure)); @@ -792,8 +792,8 @@ GURL(GetWebUIURL("test-host/web_ui_dedicated_worker.js")), kLoadDedicatedWorkerScript); - std::string expected_failure = R"(a JavaScript error: -Error: Failed to construct 'Worker')"; + std::string expected_failure = + "a JavaScript error: \"Error: Failed to construct 'Worker'"; EXPECT_THAT(result.error, ::testing::StartsWith(expected_failure)); } @@ -865,7 +865,7 @@ kLoadDedicatedWorkerScript); std::string expected_failure = - "a JavaScript error:\nError: Failed to construct 'Worker': " + "a JavaScript error: \"Error: Failed to construct 'Worker': " "Script at 'chrome-untrusted://untrusted/web_ui_dedicated_worker.js' " "cannot be accessed from origin 'chrome://trusted'"; EXPECT_THAT(result.error, ::testing::StartsWith(expected_failure)); @@ -883,7 +883,7 @@ kLoadDedicatedWorkerScript); std::string expected_failure = - "a JavaScript error:\nError: Failed to construct 'Worker': " + "a JavaScript error: \"Error: Failed to construct 'Worker': " "Script at 'chrome-untrusted://untrusted/web_ui_dedicated_worker.js' " "cannot be accessed from origin 'http://localhost"; EXPECT_THAT(result.error, ::testing::StartsWith(expected_failure)); @@ -902,7 +902,7 @@ kLoadDedicatedWorkerScript); std::string expected_failure = - "a JavaScript error:\nError: Failed to construct 'Worker': Script " + "a JavaScript error: \"Error: Failed to construct 'Worker': Script " "at 'chrome://trusted/web_ui_dedicated_worker.js' cannot be accessed " "from origin 'chrome-untrusted://untrusted'."; EXPECT_THAT(result.error, ::testing::StartsWith(expected_failure));
diff --git a/content/dev_ui_content_resources.grd b/content/dev_ui_content_resources.grd index 601d735..eca74292 100644 --- a/content/dev_ui_content_resources.grd +++ b/content/dev_ui_content_resources.grd
@@ -22,9 +22,11 @@ <include name="IDR_ATTRIBUTION_INTERNALS_CSS" file="browser/resources/attribution_reporting/attribution_internals.css" type="BINDATA" /> <include name="IDR_ATTRIBUTION_INTERNALS_MOJOM_JS" file="${root_gen_dir}/mojom-webui/content/browser/attribution_reporting/attribution_internals.mojom-webui.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_GPU_BROWSER_BRIDGE_JS" file="browser/resources/gpu/browser_bridge.js" type="BINDATA" /> - <include name="IDR_GPU_INFO_VIEW_JS" file="browser/resources/gpu/info_view.js" type="BINDATA" /> - <include name="IDR_GPU_INTERNALS_HTML" file="browser/resources/gpu/gpu_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> + <include name="IDR_GPU_INTERNALS_HTML" file="browser/resources/gpu/gpu_internals.html" type="BINDATA" /> <include name="IDR_GPU_INTERNALS_JS" file="browser/resources/gpu/gpu_internals.js" type="BINDATA" /> + <include name="IDR_GPU_INTERNALS_INFO_VIEW_JS" file="${root_gen_dir}/content/browser/resources/gpu/info_view.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_GPU_INTERNALS_INFO_VIEW_TABLE_JS" file="${root_gen_dir}/content/browser/resources/gpu/info_view_table.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_GPU_INTERNALS_INFO_VIEW_TABLE_ROW_JS" file="${root_gen_dir}/content/browser/resources/gpu/info_view_table_row.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_GPU_VULKAN_INFO_JS" file="browser/resources/gpu/vulkan_info.js" type="BINDATA" /> <include name="IDR_INDEXED_DB_INTERNALS_HTML" file="browser/resources/indexed_db/indexeddb_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_INDEXED_DB_INTERNALS_JS" file="browser/resources/indexed_db/indexeddb_internals.js" type="BINDATA" />
diff --git a/content/gpu/gpu_sandbox_hook_linux.cc b/content/gpu/gpu_sandbox_hook_linux.cc index 4475f9a..a89406e 100644 --- a/content/gpu/gpu_sandbox_hook_linux.cc +++ b/content/gpu/gpu_sandbox_hook_linux.cc
@@ -104,6 +104,16 @@ constexpr int dlopen_flag = RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE; +void AddStandardChromeOsPermissions( + std::vector<BrokerFilePermission>* permissions) { + static const char kAngleEglPath[] = "/opt/google/chrome/libEGL.so"; + static const char kAngleGlesPath[] = "/opt/google/chrome/libGLESv2.so"; + + // For the ANGLE passthrough command decoder. + permissions->push_back(BrokerFilePermission::ReadOnly(kAngleEglPath)); + permissions->push_back(BrokerFilePermission::ReadOnly(kAngleGlesPath)); +} + void AddV4L2GpuPermissions( std::vector<BrokerFilePermission>* permissions, const sandbox::policy::SandboxSeccompBPF::Options& options) { @@ -388,6 +398,7 @@ AddVulkanICDPermissions(&permissions); if (IsChromeOS()) { + AddStandardChromeOsPermissions(&permissions); if (UseV4L2Codec()) AddV4L2GpuPermissions(&permissions, options); if (IsArchitectureArm()) {
diff --git a/content/public/browser/service_worker_context.h b/content/public/browser/service_worker_context.h index 985ee83..10ac5f92 100644 --- a/content/public/browser/service_worker_context.h +++ b/content/public/browser/service_worker_context.h
@@ -25,6 +25,10 @@ class StorageKey; } // namespace blink +namespace service_manager { +class InterfaceProvider; +} + namespace url { class Origin; } // namespace url @@ -255,6 +259,16 @@ ServiceWorkerRunningInfo>& GetRunningServiceWorkerInfos() = 0; + // Returns the InterfaceProvider for the worker specified by + // `service_worker_version_id`. The caller can use InterfaceProvider to bind + // interfaces exposed by the Service Worker. + // + // Returns nullptr: + // - if there is no service worker with |service_worker_version_id| + // - during shutdown + virtual service_manager::InterfaceProvider* GetRemoteInterfaces( + int64_t service_worker_version_id) = 0; + protected: ServiceWorkerContext() {} virtual ~ServiceWorkerContext() {}
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index d7091fc..ade9ed12e 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -1598,7 +1598,7 @@ // |source_frame_pattern| should match any line that looks like a stack frame // from a source file named |source_name|. const std::string source_frame_pattern = - base::StringPrintf(" at * (%s:*:*)", source_name.c_str()); + base::StringPrintf(" at *%s:*:*", source_name.c_str()); // This is the amount of indentation that is applied to the lines of inserted // annotations. @@ -1668,93 +1668,149 @@ return annotated_error.str(); } -EvalJsResult EvalRunnerScript(const ToRenderFrameHost& execution_target, - const std::string& script, - int options, - int32_t world_id, - const std::string& token) { - const char* kSourceURL = "__const_std::string&_script__"; - bool use_automatic_reply = !(options & EXECUTE_SCRIPT_USE_MANUAL_REPLY); - bool user_gesture = - execution_target.render_frame_host()->GetLifecycleState() == - RenderFrameHost::LifecycleState::kPrerendering - ? false - : !(options & EXECUTE_SCRIPT_NO_USER_GESTURE); - std::ostringstream error_stream; - std::unique_ptr<base::Value> response; - if (!execution_target.render_frame_host()->IsRenderFrameLive()) { - error_stream << "Error: EvalJs won't work on an already-crashed frame."; - } else if (!ExecuteScriptHelper(execution_target.render_frame_host(), script, - user_gesture, world_id, &response)) { - error_stream << "Internal Error: ExecuteScriptHelper failed"; - } else if (!response) { - error_stream << "Internal Error: no value"; - } else { - bool is_reply_from_script = - response->is_list() && response->GetListDeprecated().size() == 2 && - response->GetListDeprecated()[0].is_string() && - response->GetListDeprecated()[0].GetString() == token; +// Waits for a response from ExecuteJavaScriptForTests, simulating an +// error if the target renderer is destroyed while executing the script. +class ExecuteJavaScriptForTestsWaiter : public WebContentsObserver { + public: + explicit ExecuteJavaScriptForTestsWaiter(const ToRenderFrameHost& adapter) + : WebContentsObserver( + WebContents::FromRenderFrameHost(adapter.render_frame_host())), + render_frame_host_(adapter.render_frame_host()) {} - bool is_error = - is_reply_from_script && response->GetListDeprecated()[1].is_string(); - bool is_automatic_success_reply = - is_reply_from_script && response->GetListDeprecated()[1].is_list() && - response->GetListDeprecated()[1].GetListDeprecated().size() == 1; - - if (is_error) { - // This is a response generated by the error handler in our runner - // script. This occurs when the script throws an exception, or when - // eval throws a SyntaxError. - // - // Parse the stack trace here, and interleave lines of source code from - // |script| to aid debugging. - std::string error_text = response->GetListDeprecated()[1].GetString(); - - if (base::StartsWith(error_text, - "a JavaScript error:\nEvalError: Refused", - base::CompareCase::SENSITIVE)) { - error_text = - "EvalJs encountered an EvalError, because eval() is blocked by the " - "document's CSP on this page. To test content that is protected by " - "CSP, consider using EvalJs with an isolated world. Details: " + - error_text; - } - - CHECK(!error_text.empty()); - error_stream << AnnotateAndAdjustJsStackTraces(error_text, kSourceURL, - script, 0); - } else if (!use_automatic_reply) { - // When |script| itself calls domAutomationController.send() on success, - // |response| could be anything; so there's no more checking we can do: - // return |response| as success, with an empty error. - return EvalJsResult(std::move(*response), std::string()); - } else if (is_automatic_success_reply) { - // Got a response from the runner script that indicates success (of the - // form [token, [completion_value]]. Return the completion value, with an - // empty error. - return EvalJsResult( - std::move(response->GetListDeprecated()[1].GetListDeprecated()[0]), - std::string()); - } else { - // The response was not well-formed (it failed the token match), so it's - // not from our runner script. Fail with an explanation of the raw - // message. This allows us to reject other calls - // domAutomationController.send(). - error_stream - << "Internal Error: expected a 2-element list of the form " - << "['" << token << "', [result]]; but got instead: " << *response - << " ... This is potentially because a script tried to call " - "domAutomationController.send itself -- that is only allowed " - "when using EXECUTE_SCRIPT_USE_MANUAL_REPLY. When using " - "EvalJs(), result values are just the result of calling eval() on " - "the script -- the completion value is the value of the last " - "executed statement. When using ExecJs(), there is no result " - "value."; - } + blink::mojom::LocalFrame::JavaScriptExecuteRequestForTestsCallback + GetCallback() { + return base::BindOnce(&ExecuteJavaScriptForTestsWaiter::SetValue, + weak_ptr_factory_.GetWeakPtr()); } - // Something went wrong. Return an empty value and a non-empty error. - return EvalJsResult(base::Value(), error_stream.str()); + bool Wait() { + if (!has_value_) + run_loop_.Run(); + return has_value_; + } + + blink::mojom::JavaScriptExecutionResultType GetResultType() { + DCHECK(has_value_); + return type_; + } + + const base::Value& GetResult() { + DCHECK(has_value_); + return value_; + } + + // WebContentsObserver + void PrimaryMainFrameRenderProcessGone( + base::TerminationStatus status) override { + if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION || + status == base::TERMINATION_STATUS_STILL_RUNNING) { + return; + } + RendererTerminated(); + } + void RenderFrameDeleted(RenderFrameHost* render_frame_host) override { + if (render_frame_host_ != render_frame_host) + return; + RendererTerminated(); + } + + private: + void RendererTerminated() { + render_frame_host_ = nullptr; + if (has_value_) + return; + SetValue(blink::mojom::JavaScriptExecutionResultType::kException, + base::Value("Renderer terminated")); + } + + void SetValue(blink::mojom::JavaScriptExecutionResultType type, + base::Value value) { + DCHECK(!has_value_); + has_value_ = true; + type_ = type; + value_ = value.Clone(); + run_loop_.Quit(); + } + + RenderFrameHost* render_frame_host_; + base::RunLoop run_loop_{base::RunLoop::Type::kNestableTasksAllowed}; + bool has_value_ = false; + blink::mojom::JavaScriptExecutionResultType type_; + base::Value value_; + + base::WeakPtrFactory<ExecuteJavaScriptForTestsWaiter> weak_ptr_factory_{this}; +}; + +EvalJsResult EvalJsRunner(const ToRenderFrameHost& execution_target, + const std::string& script, + const std::string& source_url, + int options, + int32_t world_id) { + RenderFrameHostImpl* rfh = + static_cast<RenderFrameHostImpl*>(execution_target.render_frame_host()); + if (!rfh->IsRenderFrameLive()) { + return EvalJsResult( + base::Value(), "Error: EvalJs won't work on an already-crashed frame."); + } + + bool resolve_promises = !(options & EXECUTE_SCRIPT_NO_RESOLVE_PROMISES); + bool user_gesture = rfh->GetLifecycleState() != + RenderFrameHost::LifecycleState::kPrerendering && + !(options & EXECUTE_SCRIPT_NO_USER_GESTURE) && + world_id == ISOLATED_WORLD_ID_GLOBAL; + + DOMMessageQueue dom_message_queue(rfh); + ExecuteJavaScriptForTestsWaiter waiter(rfh); + rfh->ExecuteJavaScriptForTests(base::UTF8ToUTF16(script), user_gesture, + resolve_promises, world_id, + waiter.GetCallback()); + + bool has_value = waiter.Wait(); + if (!has_value) { + return EvalJsResult(base::Value(), + "Timeout waiting for Javascript to execute."); + } + + using blink::mojom::JavaScriptExecutionResultType; + JavaScriptExecutionResultType result_type = waiter.GetResultType(); + const base::Value& result_value = waiter.GetResult(); + + if (result_type == JavaScriptExecutionResultType::kException) { + // Parse the stack trace here, and interleave lines of source code from + // |script| to aid debugging. + CHECK(result_value.is_string() && !result_value.GetString().empty()); + std::string error_text = + "a JavaScript error: \"" + result_value.GetString() + "\""; + return EvalJsResult(base::Value(), AnnotateAndAdjustJsStackTraces( + error_text, source_url, script, 0)); + } else if (options & EXECUTE_SCRIPT_USE_MANUAL_REPLY) { + // Callers that set EXECUTE_SCRIPT_USE_MANUAL_REPLY expect this function to + // block until their JS calls `window.domAutomationController.send`. To + // support this, wait for a message from DOMMessageQueue and parse it as + // JSON. + std::string json; + if (!dom_message_queue.WaitForMessage(&json)) { + return EvalJsResult(base::Value(), + "Cannot communicate with DOMMessageQueue."); + } + + base::JSONReader::ValueWithError parsed_json = + base::JSONReader::ReadAndReturnValueWithError( + json, base::JSON_ALLOW_TRAILING_COMMAS); + if (!parsed_json.value) + return EvalJsResult(base::Value(), parsed_json.error_message); + result_type = JavaScriptExecutionResultType::kSuccess; + return EvalJsResult(parsed_json.value->Clone(), std::string()); + } else if (dom_message_queue.HasMessages()) { + return EvalJsResult(base::Value(), + "Calling domAutomationController.send is only allowed " + "when using EXECUTE_SCRIPT_USE_MANUAL_REPLY. When " + "using EvalJs(), the completion value is the value of " + "the last executed statement. When using ExecJs(), " + "there is no result value."); + } + + return EvalJsResult(result_value.Clone(), std::string()); } } // namespace @@ -1783,64 +1839,20 @@ int options, int32_t world_id) { TRACE_EVENT1("test", "EvalJs", "script", script); + // The sourceURL= parameter provides a string that replaces <anonymous> in // stack traces, if an Error is thrown. 'std::string' is meant to communicate // that this is a dynamic argument originating from C++ code. + // + // Wrapping the script in braces makes it run in a block scope so that + // let/const don't leak outside the code being run, but vars will float to + // the outer scope. const char* kSourceURL = "__const_std::string&_script__"; - std::string modified_script = - base::StringPrintf("%s;\n//# sourceURL=%s", script.c_str(), kSourceURL); + std::string modified_script = base::StringPrintf("{%s\n}\n//# sourceURL=%s", + script.c_str(), kSourceURL); - // An extra eval() indirection is used here to catch syntax errors and return - // them as assertion failures. This eval() operation deliberately occurs in - // the global scope, so 'var' declarations in |script| will persist for later - // script executions. (As an aside: global/local scope for eval depends on - // whether 'eval' is called directly or indirectly; 'window.eval()' is - // indirect). - // - // The call to eval() itself is inside a .then() handler so that syntax errors - // result in Promise rejection. Calling eval() either throws (in the event of - // a SyntaxError) or returns the script's completion value. - // - // The result of eval() (i.e., the statement completion value of |script|) is - // wrapped in an array and passed to a second .then() handler. If eval() - // returned a Promise and the |resolve_promises| option is set, this handler - // calls Promise.all to reply after the returned Promise resolves. - // - // If |script| evaluated successfully, the third.then() handler maps the - // resolved |result| of eval() to a |reply| that is a one-element list - // containing the value (this element can be any JSON-serializable type). If - // the manual reply option is being used, no reply is emitted after successful - // execution -- the script is expected to call send() itself. The call to - // Promise.reject() squelches this reply, and the final .then() handler is not - // called. - // - // If an uncaught error was thrown, or eval() returns a Promise that is - // rejected, the third .then() handler maps the |error| to a |reply| that is - // a string value. - // - // The fourth and final .then() handler passes the |reply| (whether - // successful or unsuccessful) to domAutomationController.send(), so that it's - // transmitted back here in browser process C++ land. A GUID token is also - // included, that protects against |script| directly calling - // domAutomationController.send() itself, which is disallowed in EvalJs. - bool use_automatic_reply = !(options & EXECUTE_SCRIPT_USE_MANUAL_REPLY); - bool resolve_promises = !(options & EXECUTE_SCRIPT_NO_RESOLVE_PROMISES); - - std::string token = "EvalJs-" + base::GenerateGUID(); - std::string runner_script = JsReplace( - R"(Promise.resolve($1) - .then(script => [window.eval(script)]) - .then((result) => $2 ? Promise.all(result) : result ) - .then((result) => $3 ? result : Promise.reject(), - (error) => 'a JavaScript error:' + - (error && error.stack ? '\n' + error.stack - : ' "' + error + '"')) - .then((reply) => window.domAutomationController.send([$4, reply])); - //# sourceURL=EvalJs-runner.js)", - modified_script, resolve_promises, use_automatic_reply, token); - - return EvalRunnerScript(execution_target, runner_script, options, world_id, - token); + return EvalJsRunner(execution_target, modified_script, kSourceURL, options, + world_id); } EvalJsResult EvalJsAfterLifecycleUpdate( @@ -1849,10 +1861,11 @@ const std::string& script, int options, int32_t world_id) { - bool use_automatic_reply = !(options & EXECUTE_SCRIPT_USE_MANUAL_REPLY); - bool resolve_promises = !(options & EXECUTE_SCRIPT_NO_RESOLVE_PROMISES); - std::string token = "EvalJs-" + base::GenerateGUID(); + TRACE_EVENT2("test", "EvalJsAfterLifecycleUpdate", "raf_script", raf_script, + "script", script); + const char* kSourceURL = "__const_std::string&_script__"; + const char* kWrapperURL = "__const_std::string&_EvalJsAfterLifecycleUpdate__"; std::string modified_raf_script; if (raf_script.length()) { modified_raf_script = base::StringPrintf("%s;\n//# sourceURL=%s", @@ -1861,29 +1874,34 @@ std::string modified_script = base::StringPrintf("%s;\n//# sourceURL=%s", script.c_str(), kSourceURL); - // This runner_script is very similar to that used by EvalJs, except that - // this one delays running the argument script until just before + // This runner_script delays running the argument scripts until just before // (|raf_script|) and after (|script|) a rendering update. std::string runner_script = JsReplace( - R"(Promise.all([$1, $2]) - .then(scripts => new Promise((resolve, reject) => { - requestAnimationFrame(() => { - window.eval(scripts[0]); - setTimeout(() => { - resolve([window.eval(scripts[1])]) - }) }) }) ) - .then((result) => $3 ? Promise.all(result) : result ) - .then((result) => $4 ? result : Promise.reject(), - (error) => 'a JavaScript error:' + - (error && error.stack ? '\n' + error.stack - : ' "' + error + '"')) - .then((reply) => window.domAutomationController.send([$5, reply])); - //# sourceURL=EvalJs-runner.js)", - modified_raf_script, modified_script, resolve_promises, - use_automatic_reply, token); + R"(new Promise((resolve, reject) => { + requestAnimationFrame(() => { + try { window.eval($1); } catch (e) { reject(e); } + setTimeout(() => { + try { resolve(window.eval($2)); } catch (e) { reject(e); } + }); + }); + }) + //# sourceURL=$3)", + modified_raf_script, modified_script, kWrapperURL); - return EvalRunnerScript(execution_target, runner_script, options, world_id, - token); + EvalJsResult result = EvalJsRunner(execution_target, runner_script, + kWrapperURL, options, world_id); + + if (base::StartsWith(result.error, "a JavaScript error: \"EvalError: Refused", + base::CompareCase::SENSITIVE)) { + return EvalJsResult( + base::Value(), + "EvalJsAfterLifecycleUpdate encountered an EvalError, because eval() " + "is blocked by the document's CSP on this page. To test content that " + "is protected by CSP, consider using EvalJsAfterLifecycleUpdate in an " + "isolated world. Details: " + + result.error); + } + return result; } namespace { @@ -2683,6 +2701,10 @@ return true; } +bool DOMMessageQueue::HasMessages() { + return !message_queue_.empty(); +} + WebContentsAddedObserver::WebContentsAddedObserver() : web_contents_created_callback_( base::BindRepeating(&WebContentsAddedObserver::WebContentsCreated,
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index 574e640..2d75623 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -1276,6 +1276,9 @@ // true. Otherwise (if the queue is empty), returns false. [[nodiscard]] bool PopMessage(std::string* message); + // Returns true if there are currently any messages in the queue. + bool HasMessages(); + // Overridden NotificationObserver methods. void Observe(int type, const NotificationSource& source,
diff --git a/content/public/test/fake_service_worker_context.cc b/content/public/test/fake_service_worker_context.cc index dc541ba..f568bae9 100644 --- a/content/public/test/fake_service_worker_context.cc +++ b/content/public/test/fake_service_worker_context.cc
@@ -101,6 +101,14 @@ ServiceWorkerContext::StatusCodeCallback failure_callback) { NOTREACHED(); } + +service_manager::InterfaceProvider* +FakeServiceWorkerContext::GetRemoteInterfaces( + int64_t service_worker_version_id) { + NOTREACHED(); + return nullptr; +} + void FakeServiceWorkerContext::StartServiceWorkerForNavigationHint( const GURL& document_url, const blink::StorageKey& key,
diff --git a/content/public/test/fake_service_worker_context.h b/content/public/test/fake_service_worker_context.h index ffecd40..32b9d04 100644 --- a/content/public/test/fake_service_worker_context.h +++ b/content/public/test/fake_service_worker_context.h
@@ -80,6 +80,8 @@ const blink::StorageKey& key, ServiceWorkerContext::StartWorkerCallback info_callback, ServiceWorkerContext::StatusCodeCallback failure_callback) override; + service_manager::InterfaceProvider* GetRemoteInterfaces( + int64_t service_worker_version_id) override; void StartServiceWorkerAndDispatchMessage( const GURL& scope, const blink::StorageKey& key,
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc index aa30f0c..b674a89 100644 --- a/content/public/test/test_renderer_host.cc +++ b/content/public/test/test_renderer_host.cc
@@ -40,9 +40,12 @@ #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "third_party/blink/public/common/input/web_input_event.h" +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) +#include "ui/display/screen.h" +#endif + #if BUILDFLAG(IS_ANDROID) #include "ui/android/dummy_screen_android.h" -#include "ui/display/screen.h" #endif #if BUILDFLAG(IS_WIN) @@ -239,6 +242,10 @@ #if BUILDFLAG(IS_WIN) ole_initializer_ = std::make_unique<ui::ScopedOleInitializer>(); #endif +#if BUILDFLAG(IS_MAC) + screen_ = std::make_unique<display::ScopedNativeScreen>(); +#endif + #if defined(USE_AURA) aura_test_helper_ = std::make_unique<aura::test::AuraTestHelper>( ImageTransportFactory::GetInstance()->GetContextFactory());
diff --git a/content/public/test/test_renderer_host.h b/content/public/test/test_renderer_host.h index a02288f..8741365c 100644 --- a/content/public/test/test_renderer_host.h +++ b/content/public/test/test_renderer_host.h
@@ -43,6 +43,7 @@ namespace display { class Screen; +class ScopedNativeScreen; } namespace net { @@ -325,6 +326,9 @@ #if BUILDFLAG(IS_WIN) std::unique_ptr<ui::ScopedOleInitializer> ole_initializer_; #endif +#if BUILDFLAG(IS_MAC) + std::unique_ptr<display::ScopedNativeScreen> screen_; +#endif #if defined(USE_AURA) std::unique_ptr<aura::test::AuraTestHelper> aura_test_helper_; #endif
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc index f0c8e7e..7e445f5 100644 --- a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc +++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
@@ -93,7 +93,8 @@ std::move(params->renderer_preferences), std::move(params->service_worker_receiver), std::move(params->controller_receiver), std::move(params->instance_host), - std::move(params->provider_info), this, std::move(start_timing), + std::move(params->interface_provider), std::move(params->provider_info), + this, std::move(start_timing), std::move(params->preference_watcher_receiver), std::move(params->subresource_loader_factories), std::move(params->subresource_loader_updater),
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc index cd1cfbd2..a069626 100644 --- a/content/renderer/service_worker/service_worker_context_client.cc +++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -102,6 +102,8 @@ controller_receiver, mojo::PendingAssociatedRemote<blink::mojom::EmbeddedWorkerInstanceHost> instance_host, + mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> + pending_interface_provider_receiver, blink::mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info, EmbeddedWorkerInstanceClientImpl* owner, blink::mojom::EmbeddedWorkerStartTimingPtr start_timing, @@ -125,6 +127,8 @@ proxy_(nullptr), pending_service_worker_receiver_(std::move(service_worker_receiver)), controller_receiver_(std::move(controller_receiver)), + pending_interface_provider_receiver_( + std::move(pending_interface_provider_receiver)), pending_subresource_loader_updater_( std::move(subresource_loader_updater)), owner_(owner), @@ -201,6 +205,13 @@ return *worker_; } +void ServiceWorkerContextClient::GetInterface( + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) { + if (registry_.TryBindInterface(interface_name, &interface_pipe)) + return; +} + void ServiceWorkerContextClient::WorkerReadyForInspectionOnInitiatorThread( blink::CrossVariantMojoRemote<blink::mojom::DevToolsAgentInterfaceBase> devtools_agent_remote, @@ -254,6 +265,10 @@ DCHECK(controller_receiver_.is_valid()); proxy_->BindControllerServiceWorker(std::move(controller_receiver_)); + DCHECK(pending_interface_provider_receiver_.is_valid()); + interface_provider_receiver_.Bind( + std::move(pending_interface_provider_receiver_)); + GetContentClient() ->renderer() ->DidInitializeServiceWorkerContextOnWorkerThread( @@ -320,6 +335,14 @@ v8::Local<v8::Context> context) { DCHECK(worker_task_runner_->RunsTasksInCurrentSequence()); + // After WillDestroyWorkerContext is called, the ServiceWorkerContext + // is destroyed, so destroy InterfaceProvider here and clear the + // BinderRegistry to stop any future interface requests. InterfaceProvider is + // bound on the worker task runner and therefore, should be destroyed on the + // worker task runner. + interface_provider_receiver_.reset(); + registry_.clear(); + // At this point WillStopCurrentWorkerThread is already called, so // worker_task_runner_->RunsTasksInCurrentSequence() returns false // (while we're still on the worker thread).
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h index 188e0ef..b5e0c76 100644 --- a/content/renderer/service_worker/service_worker_context_client.h +++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -23,6 +23,7 @@ #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/shared_associated_remote.h" #include "services/service_manager/public/cpp/binder_registry.h" +#include "services/service_manager/public/mojom/interface_provider.mojom.h" #include "third_party/blink/public/common/service_worker/service_worker_status_code.h" #include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom-forward.h" #include "third_party/blink/public/mojom/payments/payment_app.mojom-forward.h" @@ -71,7 +72,9 @@ // // Unless otherwise noted (here or in base class documentation), all methods // are called on the worker thread. -class ServiceWorkerContextClient : public blink::WebServiceWorkerContextClient { +class ServiceWorkerContextClient + : public blink::WebServiceWorkerContextClient, + public service_manager::mojom::InterfaceProvider { public: // Called on the initiator thread. // - |is_starting_installed_worker| is true if the script is already installed @@ -99,6 +102,8 @@ controller_receiver, mojo::PendingAssociatedRemote<blink::mojom::EmbeddedWorkerInstanceHost> instance_host, + mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> + interface_provider, blink::mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info, EmbeddedWorkerInstanceClientImpl* owner, blink::mojom::EmbeddedWorkerStartTimingPtr start_timing, @@ -133,6 +138,10 @@ // Called on the initiator thread. blink::WebEmbeddedWorker& worker(); + // service_manager::mojom::InterfaceProvider: + void GetInterface(const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) override; + // WebServiceWorkerContextClient overrides. void WorkerReadyForInspectionOnInitiatorThread( blink::CrossVariantMojoRemote<blink::mojom::DevToolsAgentInterfaceBase> @@ -229,6 +238,8 @@ pending_service_worker_receiver_; mojo::PendingReceiver<blink::mojom::ControllerServiceWorker> controller_receiver_; + mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> + pending_interface_provider_receiver_; mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> pending_subresource_loader_updater_; @@ -236,6 +247,12 @@ service_manager::BinderRegistry registry_; std::unique_ptr<BlinkInterfaceRegistryImpl> blink_interface_registry_; + // Receiver for the InterfaceProvider interface which is used by the browser + // to request interfaces that are exposed by the renderer. Bound and destroyed + // on the worker task runner. + mojo::Receiver<service_manager::mojom::InterfaceProvider> + interface_provider_receiver_{this}; + // This is bound on the initiator thread. mojo::SharedAssociatedRemote<blink::mojom::EmbeddedWorkerInstanceHost> instance_host_;
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index 15cbdd3..2ee2fdb 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -310,6 +310,10 @@ deps += [ "//ui/views/linux_ui:linux_ui_factory" ] } + if (is_mac) { + deps += [ "//ui/display:test_support" ] + } + if (is_android) { deps += [ "//components/embedder_support/android:view",
diff --git a/content/shell/browser/shell_platform_data_aura.cc b/content/shell/browser/shell_platform_data_aura.cc index a02a4058..6e2480ed 100644 --- a/content/shell/browser/shell_platform_data_aura.cc +++ b/content/shell/browser/shell_platform_data_aura.cc
@@ -82,12 +82,7 @@ #if defined(USE_OZONE) // Setup global display::Screen singleton. - if (!display::Screen::GetScreen()) { - std::unique_ptr<aura::ScreenOzone> screen_ozone = - std::make_unique<aura::ScreenOzone>(); - screen_ozone.get()->Initialize(); - screen_ = std::move(screen_ozone); - } + screen_ = std::make_unique<aura::ScopedScreenOzone>(); #endif // defined(USE_OZONE) ui::PlatformWindowInitProperties properties;
diff --git a/content/shell/browser/shell_platform_data_aura.h b/content/shell/browser/shell_platform_data_aura.h index 8b58302..345a9d9 100644 --- a/content/shell/browser/shell_platform_data_aura.h +++ b/content/shell/browser/shell_platform_data_aura.h
@@ -20,7 +20,7 @@ #if defined(USE_OZONE) namespace display { -class Screen; +class ScopedNativeScreen; } #endif @@ -46,7 +46,7 @@ private: #if defined(USE_OZONE) - std::unique_ptr<display::Screen> screen_; + std::unique_ptr<display::ScopedNativeScreen> screen_; #endif std::unique_ptr<aura::WindowTreeHost> host_;
diff --git a/content/shell/browser/shell_platform_delegate.h b/content/shell/browser/shell_platform_delegate.h index 32cd23a..9326cb3 100644 --- a/content/shell/browser/shell_platform_delegate.h +++ b/content/shell/browser/shell_platform_delegate.h
@@ -15,6 +15,7 @@ #if BUILDFLAG(IS_MAC) #include "content/public/browser/native_web_keyboard_event.h" +#include "ui/display/screen.h" #endif class GURL; @@ -139,6 +140,9 @@ #endif private: +#if BUILDFLAG(IS_MAC) + std::unique_ptr<display::ScopedNativeScreen> screen_; +#endif // Data held for each Shell instance, since there is one ShellPlatformDelegate // for the whole browser process (shared across Shells). This is defined for // each platform implementation.
diff --git a/content/shell/browser/shell_platform_delegate_mac.mm b/content/shell/browser/shell_platform_delegate_mac.mm index 0868a06..cf91694 100644 --- a/content/shell/browser/shell_platform_delegate_mac.mm +++ b/content/shell/browser/shell_platform_delegate_mac.mm
@@ -134,7 +134,7 @@ ShellPlatformDelegate::~ShellPlatformDelegate() = default; void ShellPlatformDelegate::Initialize(const gfx::Size& default_window_size) { - // |platform_| is unused on this platform. + screen_ = std::make_unique<display::ScopedNativeScreen>(); } void ShellPlatformDelegate::CreatePlatformWindow(
diff --git a/content/shell/browser/shell_platform_delegate_views.cc b/content/shell/browser/shell_platform_delegate_views.cc index f6924fc..0063882 100644 --- a/content/shell/browser/shell_platform_delegate_views.cc +++ b/content/shell/browser/shell_platform_delegate_views.cc
@@ -331,8 +331,9 @@ std::make_unique<wm::WMTestHelper>(default_window_size); #else platform_->wm_state = std::make_unique<wm::WMState>(); - CHECK(!display::Screen::GetScreen()); - platform_->screen = views::CreateDesktopScreen(); + // FakeScreen tests create their own screen. + if (!display::Screen::HasScreen()) + platform_->screen = views::CreateDesktopScreen(); #endif platform_->views_delegate =
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index c547597..f3f13ab 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1621,6 +1621,7 @@ "//ui/base/ime/mojom", "//ui/compositor", "//ui/display", + "//ui/display:test_support", "//ui/events:test_support", "//ui/events/blink:blink", "//ui/gfx",
diff --git a/content/test/browser_test_utils_browsertest.cc b/content/test/browser_test_utils_browsertest.cc index b4aaf66..d259083 100644 --- a/content/test/browser_test_utils_browsertest.cc +++ b/content/test/browser_test_utils_browsertest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/test/scoped_run_loop_timeout.h" #include "content/public/browser/navigation_handle.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -11,9 +12,12 @@ #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest-spi.h" namespace content { +using ::testing::Eq; + class NavigationObserver: public WebContentsObserver { public: explicit NavigationObserver(WebContents* web_contents) @@ -80,9 +84,7 @@ using EvalJsBrowserTest = ContentBrowserTest; -// TODO(mslekova): Re-enable once test expectations are updated, -// see chromium:916975 -IN_PROC_BROWSER_TEST_F(EvalJsBrowserTest, DISABLED_EvalJsErrors) { +IN_PROC_BROWSER_TEST_F(EvalJsBrowserTest, EvalJsErrors) { ASSERT_TRUE(embedded_test_server()->Start()); EXPECT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"))); @@ -98,11 +100,8 @@ EXPECT_FALSE("}}" != result); // As should EXPECT_NE EXPECT_FALSE(nullptr == result); - std::string expected_error = R"(a JavaScript error: -SyntaxError: Unexpected token } - at eval (<anonymous>) - at Promise.resolve.then.script (EvalJs-runner.js:2:34) -)"; + std::string expected_error = + "a JavaScript error: \"SyntaxError: Unexpected token '}'\"\n"; EXPECT_FALSE(expected_error == result); EXPECT_EQ(expected_error, result.error); } @@ -114,13 +113,10 @@ EXPECT_FALSE(1 == result); EXPECT_FALSE("whoops" == result); - std::string expected_error = R"(a JavaScript error: -Error: whoops - at eval (__const_std::string&_script__:1:11): - 55; throw new Error('whoops'); - ^^^^^ - at eval (<anonymous>) - at Promise.resolve.then.script (EvalJs-runner.js:2:34) + std::string expected_error = R"(a JavaScript error: "Error: whoops + at __const_std::string&_script__:1:12): + {55; throw new Error('whoops'); + ^^^^^ )"; EXPECT_FALSE(expected_error == result); EXPECT_EQ(expected_error, result.error); @@ -136,19 +132,72 @@ EXPECT_FALSE(22 == result); EXPECT_FALSE("sweet" == result); - std::string expected_error = R"(a JavaScript error: -ReferenceError: z is not defined - at eval (__const_std::string&_script__:4:13): - var y = z + x; - ^^^^^ - at eval (<anonymous>) - at Promise.resolve.then.script (EvalJs-runner.js:2:34) -)"; + std::string expected_error = + "a JavaScript error: \"ReferenceError: z is not defined\n" + " at __const_std::string&_script__:4:13):\n" + " var y = z + x;\n" + " ^^^^^\n"; EXPECT_FALSE(expected_error == result); EXPECT_EQ(expected_error, result.error); } } +IN_PROC_BROWSER_TEST_F(EvalJsBrowserTest, EvalJsAfterLifecycleUpdateErrors) { + ASSERT_TRUE(embedded_test_server()->Start()); + EXPECT_TRUE( + NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"))); + + { + // Test syntax errors. + auto result = EvalJsAfterLifecycleUpdate(shell(), "}}", "'hi'"); + + EXPECT_TRUE(result.value.is_none()); + EXPECT_THAT( + result.error, + Eq("a JavaScript error: \"SyntaxError: Unexpected token '}'\n" + " at eval (<anonymous>)\n" + " at \"__const_std::string&_EvalJsAfterLifecycleUpdate__\"" + ":3:27\"\n")); + + auto result2 = EvalJsAfterLifecycleUpdate(shell(), "'hi'", "]]"); + + EXPECT_TRUE(result2.value.is_none()); + EXPECT_THAT( + result2.error, + Eq("a JavaScript error: \"SyntaxError: Unexpected token ']'\n" + " at eval (<anonymous>)\n" + " at \"__const_std::string&_EvalJsAfterLifecycleUpdate__\"" + ":5:37\"\n")); + } + + { + // Test throwing exceptions. + auto result = EvalJsAfterLifecycleUpdate( + shell(), "55; throw new Error('whoops');", "'hi'"); + + EXPECT_TRUE(result.value.is_none()); + EXPECT_THAT( + result.error, + Eq("a JavaScript error: \"Error: whoops\n" + " at eval (__const_std::string&_script__:1:11)\n" + " at eval (<anonymous>)\n" + " at \"__const_std::string&_EvalJsAfterLifecycleUpdate__\"" + ":3:27\"\n")); + + auto result2 = EvalJsAfterLifecycleUpdate( + shell(), "'hi'", "55; throw new Error('whoopsie');"); + + EXPECT_TRUE(result2.value.is_none()); + EXPECT_THAT( + result2.error, + Eq("a JavaScript error: \"Error: whoopsie\n" + " at eval (__const_std::string&_script__:1:11)\n" + " at eval (<anonymous>)\n" + " at \"__const_std::string&_EvalJsAfterLifecycleUpdate__\"" + ":5:37\"\n")); + } +} + IN_PROC_BROWSER_TEST_F(EvalJsBrowserTest, EvalJsWithManualReply) { ASSERT_TRUE(embedded_test_server()->Start()); EXPECT_TRUE( @@ -165,18 +214,58 @@ EXPECT_FALSE(20 == result); EXPECT_FALSE("hi" == result); EXPECT_THAT(result.error, - ::testing::StartsWith( - "Internal Error: expected a 2-element list of the form ")); + ::testing::EndsWith( + "Calling domAutomationController.send is only allowed " + "when using EXECUTE_SCRIPT_USE_MANUAL_REPLY. When " + "using EvalJs(), the completion value is the value of " + "the last executed statement. When using ExecJs(), " + "there is no result value.")); +} + +IN_PROC_BROWSER_TEST_F(EvalJsBrowserTest, EvalJsTimeout) { + ASSERT_TRUE(embedded_test_server()->Start()); + EXPECT_TRUE( + NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"))); + + base::test::ScopedRunLoopTimeout scoped_run_timeout(FROM_HERE, + base::Milliseconds(1)); + + // Store the promise resolve function so it doesn't get GC'd. + static std::string script = "new Promise(resolve => {window.r = resolve})"; + static std::string error; + static Shell* shell_ptr = shell(); + EXPECT_FATAL_FAILURE(error = EvalJs(shell_ptr, script).error, + "RunLoop::Run() timed out."); + + EXPECT_THAT(error, Eq("Timeout waiting for Javascript to execute.")); +} + +IN_PROC_BROWSER_TEST_F(EvalJsBrowserTest, EvalJsNotBlockedByCSP) { + ASSERT_TRUE(embedded_test_server()->Start()); + EXPECT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL( + "/set-header?Content-Security-Policy: script-src 'self'"))); + + auto result = EvalJs(shell(), "'hi'"); + EXPECT_EQ("hi", result); +} + +IN_PROC_BROWSER_TEST_F(EvalJsBrowserTest, + EvalJsAfterLifecycleUpdateBlockedByCSP) { + ASSERT_TRUE(embedded_test_server()->Start()); + EXPECT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL( + "/set-header?Content-Security-Policy: script-src 'self'"))); + + auto result = EvalJsAfterLifecycleUpdate(shell(), "'hi'", ""); + EXPECT_TRUE(result.value.is_none()); EXPECT_THAT( result.error, - ::testing::EndsWith("This is potentially because a script tried to call " - "domAutomationController.send itself -- that is only " - "allowed when using " - "EXECUTE_SCRIPT_USE_MANUAL_REPLY. When using " - "EvalJs(), result values are just the result of " - "calling eval() on the script -- the completion " - "value is the value of the last executed statement. " - "When using ExecJs(), there is no result value.")); + ::testing::StartsWith( + "EvalJsAfterLifecycleUpdate encountered an EvalError, because eval() " + "is blocked by the document's CSP on this page. To test content that " + "is protected by CSP, consider using EvalJsAfterLifecycleUpdate in " + "an isolated world. Details:")); } } // namespace content
diff --git a/content/test/gpu/gpu_tests/context_lost_integration_test.py b/content/test/gpu/gpu_tests/context_lost_integration_test.py index 2133193..5cec51e7 100644 --- a/content/test/gpu/gpu_tests/context_lost_integration_test.py +++ b/content/test/gpu/gpu_tests/context_lost_integration_test.py
@@ -57,11 +57,12 @@ feature_query_script = """ function GetFeatureStatus(feature_name, for_hardware_gpu) { let query_result; + const infoView = document.querySelector('info-view'); if (for_hardware_gpu) { - query_result = document.querySelector( + query_result = infoView.shadowRoot.querySelector( '.feature-status-for-hardware-gpu-list'); } else { - query_result = document.querySelector('.feature-status-list'); + query_result = infoView.shadowRoot.querySelector('.feature-status-list'); } for (let i = 0; i < query_result.childElementCount; i++) { let feature_status = query_result.children[i].textContent.split(': '); @@ -75,17 +76,20 @@ vendor_id_query_script = """ function GetActiveVendorId(for_hardware_gpu) { let div; + const infoView = document.querySelector('info-view'); if (for_hardware_gpu) { - div = document.querySelector('.basic-info-for-hardware-gpu-div'); + div = infoView.shadowRoot.querySelector( + '.basic-info-for-hardware-gpu-div'); } else { - div = document.querySelector('#basic-info'); + div = infoView.shadowRoot.querySelector('#basic-info'); } - let trs = div.getElementsByTagName('tr'); + const table = div.querySelector('info-view-table'); + let trs = table.shadowRoot.querySelectorAll('info-view-table-row'); let vendor_id = 0; // The first four rows are "Initialization time", "In-process GPU", // "Passthrough Command Decoder", and "Sandboxed". for (let i = 4; i < trs.length; i++) { - let tds = trs[i].getElementsByTagName('td'); + let tds = trs[i].shadowRoot.querySelectorAll('div'); let token = tds[0].textContent.trim(); if (!token.startsWith('GPU')) break;
diff --git a/content/test/gpu/gpu_tests/gpu_process_integration_test.py b/content/test/gpu/gpu_tests/gpu_process_integration_test.py index fc7bde7..1d09c233 100644 --- a/content/test/gpu/gpu_tests/gpu_process_integration_test.py +++ b/content/test/gpu/gpu_tests/gpu_process_integration_test.py
@@ -38,7 +38,8 @@ window.domAutomationController = domAutomationController; function GetDriverBugWorkarounds() { - var query_result = document.querySelector('.workarounds-list'); + var query_result = document.querySelector('info-view').shadowRoot + .querySelector('.workarounds-list'); var browser_list = [] for (var i=0; i < query_result.childElementCount; i++) browser_list.push(query_result.children[i].textContent);
diff --git a/content/test/gpu/gpu_tests/hardware_accelerated_feature_integration_test.py b/content/test/gpu/gpu_tests/hardware_accelerated_feature_integration_test.py index e68c93e..35e8e9a 100644 --- a/content/test/gpu/gpu_tests/hardware_accelerated_feature_integration_test.py +++ b/content/test/gpu/gpu_tests/hardware_accelerated_feature_integration_test.py
@@ -15,7 +15,8 @@ test_harness_script = r""" function VerifyHardwareAccelerated(feature) { feature += ': ' - var list = document.querySelector('.feature-status-list'); + var list = document.querySelector('info-view').shadowRoot.querySelector( + '.feature-status-list'); for (var i=0; i < list.childElementCount; i++) { var span_list = list.children[i].getElementsByTagName('span'); var feature_str = span_list[0].textContent;
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 9947f97..800b97413 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -423,7 +423,8 @@ # Intel OpenGL driver issue, fixed in 27.20.100.9126 crbug.com/angleproject/5543 [ win intel angle-opengl passthrough ] conformance/extensions/webgl-compressed-texture-s3tc-srgb.html [ Failure ] -# Note that the following test seems to pass, but it may still be flaky. +# Consistent failures in functions.control_flow.return_in_nested_loop_vertex and functions.control_flow.return_in_nested_loop_fragment +# Possible HLSL compiler bug. crbug.com/478572 [ win angle-d3d9 passthrough ] deqp/data/gles2/shaders/functions.html [ Failure ] # Win / AMD D3D11 (default) failures
diff --git a/content/web_test/BUILD.gn b/content/web_test/BUILD.gn index 7aab966..00cce83 100644 --- a/content/web_test/BUILD.gn +++ b/content/web_test/BUILD.gn
@@ -208,6 +208,14 @@ "//ppapi:blink_test_plugin", ] } + + if (is_mac) { + deps += [ "//ui/display:test_support" ] + } + + if (use_aura) { + deps += [ "//ui/aura:test_support" ] + } } static_library("web_test_renderer") {
diff --git a/device/bluetooth/floss/bluetooth_adapter_floss.cc b/device/bluetooth/floss/bluetooth_adapter_floss.cc index a07af06..0651298 100644 --- a/device/bluetooth/floss/bluetooth_adapter_floss.cc +++ b/device/bluetooth/floss/bluetooth_adapter_floss.cc
@@ -122,7 +122,7 @@ if (!FlossDBusManager::Get()->HasActiveAdapter()) return; - devices_.clear(); + ClearAllDevices(); // Remove adapter by switching to an invalid adapter (cleans up DBus clients) // and then emitting |AdapterPresentChanged| to observers. @@ -136,6 +136,19 @@ weak_ptr_factory_.GetWeakPtr())); } +void BluetoothAdapterFloss::ClearAllDevices() { + // Move all elements of the original devices list to a new list here, + // leaving the original list empty so that when we send DeviceRemoved(), + // GetDevices() returns no devices. + DevicesMap devices_swapped; + devices_swapped.swap(devices_); + + for (auto& iter : devices_swapped) { + for (auto& observer : observers_) + observer.DeviceRemoved(this, iter.second.get()); + } +} + void BluetoothAdapterFloss::Init() { // If dbus is shutdown or ObjectManager isn't supported, we just return // without initializing anything. @@ -511,7 +524,7 @@ if (enabled) { PopulateInitialDevices(); } else { - devices_.clear(); + ClearAllDevices(); } NotifyAdapterPoweredChanged(enabled);
diff --git a/device/bluetooth/floss/bluetooth_adapter_floss.h b/device/bluetooth/floss/bluetooth_adapter_floss.h index 930b32d..d107b11 100644 --- a/device/bluetooth/floss/bluetooth_adapter_floss.h +++ b/device/bluetooth/floss/bluetooth_adapter_floss.h
@@ -183,6 +183,7 @@ void RemoveAdapter(); void PopulateInitialDevices(); + void ClearAllDevices(); // floss::FlossAdapterClient::Observer override. void DiscoverableChanged(bool discoverable) override;
diff --git a/docs/updater/functional_spec.md b/docs/updater/functional_spec.md index 11e58079..2cec12ca 100644 --- a/docs/updater/functional_spec.md +++ b/docs/updater/functional_spec.md
@@ -9,10 +9,12 @@ [TOC] ## Metainstaller -The metainstaller (UpdaterSetup) is a thin executable that contains a compressed -copy of the updater as a resource, extracts it, and triggers installation of the -updater / an app. The metainstaller is downloaded by the user and can be run -from any directory. +The metainstaller (UpdaterSetup) is a small executable that contains a +compressed copy of the updater as a resource, extracts it, and triggers +installation of the updater / an app. The metainstaller is downloaded by the +user and can be run from any directory. + +The size of the metainstaller is less than 1500KiB. The metainstaller may have a tag attached to it. The tag is a piece of unsigned data from which the metainstaller extracts the ID of the application to be @@ -31,25 +33,37 @@ preferred language on the current system. Every string shown in the UI is translated. -## Standalone Installer -TODO(crbug.com/1035895): Document the standalone installer. +## Bundle Installer +The bundle installer allows installation of more than one application. The +bundle installer is typically used in software distribution scenarios. TODO(crbug.com/1035895): Document bundled installers. + +## Standalone Installer +TODO(crbug.com/1035895): Document the standalone installer, including building +a standalone installer for a given application. + Applications on macOS frequently install via "drag-install", and then install the updater using a standalone installer on the application's first-run. The updater app can be embedded in a macOS application bundle as a helper and then invoked with appropriate command line arguments to install itself. +## MSI Wrapper +TODO(crbug.com/1327497) - document. + + ## Updater The updater is installed at: -* (Windows, User): `%LOCAL_APP_DATA%\{COMPANY}\{UPDATERNAME}\{VERSION}\updater.exe` -* (Windows, System): `%PROGRAM_FILES%\{COMPANY}\{UPDATERNAME}\{VERSION}\updater.exe` -* (macOS, User): `~/Library/{COMPANY}/{UPDATERNAME}/{VERSION}/{UPDATERNAME}.app` -* (macOS, System): `/Library/{COMPANY}/{UPDATERNAME}/{VERSION}/{UPDATERNAME}.app` + +* (Windows, User): `%LOCAL_APP_DATA%\{COMPANY}\{UPDATERNAME}\{VERSION}\updater.exe` +* (Windows, System): `%PROGRAM_FILES%\{COMPANY}\{UPDATERNAME}\{VERSION}\updater.exe` +* (macOS, User): `~/Library/{COMPANY}/{UPDATERNAME}/{VERSION}/{UPDATERNAME}.app` +* (macOS, System): `/Library/{COMPANY}/{UPDATERNAME}/{VERSION}/{UPDATERNAME}.app` The updater's functionality is split between several processes. The mode of a process is determined by command-line arguments: + * --install [--app-id=...] * Install and activate this version of the updater if there is no active updater. @@ -137,9 +151,80 @@ * The updater operates in system scope if and only if this switch is present. +### Protocol +The updater communicates with update servers using the +[Omaha Protocol](protocol_3_1.md). + +### Update Formats +The updater accepts updates packaged as CRX₃ files. All files must be signed +with a publisher key. The corresponding public key is hardcoded into the +updater. + ### Installation + +The updater must handle the installation of new applications. The updater can +download, install, and update an applications when the application is running. + +One or more applications can be installed at once, as a bundle. + +Before installing, the integrity of the payload if verified. The payloads are +stored in secure locations of the file system for per-system installs. + + +Considering network connectivity, there are two scenarios for installing an +application: + +1. Online +2. Offline + +#### Online Installs + +An online install is done with a [metainstaller](#Metainstaller). Every time an +online installer is run, it sends an install event ping. The update check and +the install event ping have the same session id. The install ping is lost if the +network is unreachable for any reason, or the program has crashed. + +#### Standalone/Offline Installs + +This type of installs is done with a [standalone/offline installer] +(#Standalone-Installer). This is an installer which embeds all data required to +install the application, including the payload and various configuration data +needed by the application setup. Such an install must be able to complete when +a network connection is not available. + +There are a couple of scenarios where the standalone/offline installer is used: + +1. when an interactive user experience is not needed, such as automated +deployments in the enterprise. +2. when downloading the application payload is not desirable for any reason. +3. OEM installs. + +[installdataindex](#installdataindex) provides a mechanism to specify +configuration data which is passed to the application installer. + +#### User Interface TODO(crbug.com/1035895): Document UI/UX +* The install flow can be stopped before the payload finished downloading. +* The user interface is localized in the following languages: TBD. +* Has a silent mode where the UI is not displayed at all. + +##### Help Button +If the installation fails, the updater shows an error message with a "Help" +button. Clicking the help button opens a web page in the user's default browser. +The page is opened with a query string: +`?product={AppId}&errorcode={ErrorCode}`. + +#### OEM Installs. + +TODO(crbug.com/1139014): Document OEM. + +#### Install Source + +The `installsource` identifies the originator of an install. It is provided on +the command line of the metainstaller. +TODO(crbug.com/1327491) - is this needed? If yes, document the algorithm. + #### Installer APIs As part of installing or updating an application, the updater will execute the application's installer. The API for the application installer is platform- @@ -239,15 +324,6 @@ Refer to chrome/updater/protos/omaha\_settings.proto for more details. -#### UI -TODO(crbug.com/1035895): Document UI. - -##### Help Button -If the installation fails, the updater shows an error message with a "Help" -button. Clicking the help button opens a web page in the user's default browser. -The page is opened with a query string: -`?product={AppId}&errorcode={ErrorCode}`. - #### Dynamic Install Parameters ##### `needsadmin` @@ -422,13 +498,6 @@ part of pings to the update server. ## Updates -The updater communicates with update servers using the -[Omaha Protocol](protocol_3_1.md). - -### Update Formats -The updater accepts updates packaged as CRX₃ files. All files must be signed -with a publisher key. The corresponding public key is hardcoded into the -updater. ### Differential Updates TODO(crbug.com/1035895): Document differential updates.
diff --git a/extensions/browser/api/system_display/display_info_provider.cc b/extensions/browser/api/system_display/display_info_provider.cc index 1b979ee..9097b1b 100644 --- a/extensions/browser/api/system_display/display_info_provider.cc +++ b/extensions/browser/api/system_display/display_info_provider.cc
@@ -37,7 +37,11 @@ } // namespace -DisplayInfoProvider::DisplayInfoProvider() = default; +DisplayInfoProvider::DisplayInfoProvider(display::Screen* screen) + : screen_(screen ? screen : display::Screen::GetScreen()) { + // Do not use/call on the screen object in this constructor yet because a + // subclass may pass not-yet-initialized screen instance. +} DisplayInfoProvider::~DisplayInfoProvider() = default; @@ -111,9 +115,8 @@ void DisplayInfoProvider::GetAllDisplaysInfo( bool /* single_unified*/, base::OnceCallback<void(DisplayUnitInfoList result)> callback) { - display::Screen* screen = display::Screen::GetScreen(); - int64_t primary_id = screen->GetPrimaryDisplay().id(); - std::vector<display::Display> displays = screen->GetAllDisplays(); + int64_t primary_id = screen_->GetPrimaryDisplay().id(); + std::vector<display::Display> displays = screen_->GetAllDisplays(); DisplayUnitInfoList all_displays; for (const display::Display& display : displays) { api::system_display::DisplayUnitInfo unit =
diff --git a/extensions/browser/api/system_display/display_info_provider.h b/extensions/browser/api/system_display/display_info_provider.h index 2d0d26bf..d060ff4 100644 --- a/extensions/browser/api/system_display/display_info_provider.h +++ b/extensions/browser/api/system_display/display_info_provider.h
@@ -17,6 +17,7 @@ namespace display { class Display; +class Screen; } namespace extensions { @@ -118,7 +119,7 @@ ErrorCallback callback); protected: - DisplayInfoProvider(); + explicit DisplayInfoProvider(display::Screen* screen = nullptr); // Trigger OnDisplayChangedEvent void DispatchOnDisplayChangedEvent(); @@ -142,6 +143,8 @@ void OnDisplayMetricsChanged(const display::Display& display, uint32_t metrics) override; + display::Screen* const screen_; + absl::optional<display::ScopedDisplayObserver> display_observer_; };
diff --git a/extensions/browser/api/system_display/system_display_apitest.cc b/extensions/browser/api/system_display/system_display_apitest.cc index 970ee75..b4ccfd1 100644 --- a/extensions/browser/api/system_display/system_display_apitest.cc +++ b/extensions/browser/api/system_display/system_display_apitest.cc
@@ -13,24 +13,17 @@ #include "extensions/browser/api/system_display/system_display_api.h" #include "extensions/browser/api_test_utils.h" #include "extensions/browser/mock_display_info_provider.h" -#include "extensions/browser/mock_screen.h" #include "extensions/common/api/system_display.h" #include "extensions/common/extension_builder.h" #include "extensions/shell/test/shell_apitest.h" #include "extensions/test/result_catcher.h" -#include "ui/display/display.h" #include "ui/display/screen.h" -#include "ui/display/test/scoped_screen_override.h" namespace extensions { -using display::Screen; -using display::test::ScopedScreenOverride; - class SystemDisplayApiTest : public ShellApiTest { public: - SystemDisplayApiTest() - : provider_(new MockDisplayInfoProvider), screen_(new MockScreen) {} + SystemDisplayApiTest() : provider_(new MockDisplayInfoProvider) {} SystemDisplayApiTest(const SystemDisplayApiTest&) = delete; SystemDisplayApiTest& operator=(const SystemDisplayApiTest&) = delete; @@ -39,17 +32,9 @@ void SetUpOnMainThread() override { ShellApiTest::SetUpOnMainThread(); - ANNOTATE_LEAKING_OBJECT_PTR(Screen::GetScreen()); - scoped_screen_override_ = - std::make_unique<ScopedScreenOverride>(screen_.get()); DisplayInfoProvider::InitializeForTesting(provider_.get()); } - void TearDownOnMainThread() override { - ShellApiTest::TearDownOnMainThread(); - scoped_screen_override_.reset(); - } - protected: void SetInfo(const std::string& display_id, const api::system_display::DisplayProperties& properties) { @@ -58,8 +43,6 @@ base::BindOnce([](absl::optional<std::string>) {})); } std::unique_ptr<MockDisplayInfoProvider> provider_; - std::unique_ptr<Screen> screen_; - std::unique_ptr<ScopedScreenOverride> scoped_screen_override_; }; #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/extensions/browser/mock_display_info_provider.cc b/extensions/browser/mock_display_info_provider.cc index 56ae05d..0ce2110 100644 --- a/extensions/browser/mock_display_info_provider.cc +++ b/extensions/browser/mock_display_info_provider.cc
@@ -16,7 +16,8 @@ namespace extensions { -MockDisplayInfoProvider::MockDisplayInfoProvider() = default; +MockDisplayInfoProvider::MockDisplayInfoProvider() + : DisplayInfoProvider(&screen_) {} MockDisplayInfoProvider::~MockDisplayInfoProvider() = default;
diff --git a/extensions/browser/mock_display_info_provider.h b/extensions/browser/mock_display_info_provider.h index 4e6fba2..f173f59 100644 --- a/extensions/browser/mock_display_info_provider.h +++ b/extensions/browser/mock_display_info_provider.h
@@ -13,6 +13,7 @@ #include "base/values.h" #include "extensions/browser/api/system_display/display_info_provider.h" +#include "extensions/browser/mock_screen.h" #include "extensions/common/api/system_display.h" namespace extensions { @@ -85,6 +86,8 @@ bool native_touch_calibration_success_ = false; + MockScreen screen_; + api::system_display::MirrorMode mirror_mode_ = api::system_display::MIRROR_MODE_OFF; };
diff --git a/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc b/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc index aac03851..204c58e 100644 --- a/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc +++ b/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc
@@ -54,9 +54,7 @@ ~ShellDesktopControllerAuraTest() override = default; void SetUp() override { - ShellTestBaseAura::SetUp(); - - // Set up a screen with 2 displays. + // Set up a screen with 2 displays before `ShellTestBaseAura::SetUp()` screen_ = std::make_unique<display::ScreenBase>(); screen_->display_list().AddDisplay( display::Display(100, gfx::Rect(0, 0, 1920, 1080)), @@ -66,6 +64,7 @@ display::DisplayList::Type::NOT_PRIMARY); screen_override_ = std::make_unique<display::test::ScopedScreenOverride>(screen_.get()); + ShellTestBaseAura::SetUp(); #if BUILDFLAG(IS_CHROMEOS_ASH) chromeos::PowerManagerClient::InitializeFake(); @@ -80,9 +79,9 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) chromeos::PowerManagerClient::Shutdown(); #endif + ShellTestBaseAura::TearDown(); screen_override_.reset(); screen_.reset(); - ShellTestBaseAura::TearDown(); } protected:
diff --git a/extensions/shell/browser/shell_desktop_controller_mac.h b/extensions/shell/browser/shell_desktop_controller_mac.h index e78005f2..d3ba91d 100644 --- a/extensions/shell/browser/shell_desktop_controller_mac.h +++ b/extensions/shell/browser/shell_desktop_controller_mac.h
@@ -8,6 +8,7 @@ #include <memory> #include "extensions/shell/browser/desktop_controller.h" +#include "ui/display/screen.h" namespace extensions { @@ -36,6 +37,8 @@ // The desktop only supports a single app window. // TODO(yoz): Support multiple app windows, as we do in Aura. AppWindow* app_window_; // NativeAppWindow::Close() deletes this. + + display::ScopedNativeScreen screen_; }; } // namespace extensions
diff --git a/fuchsia/engine/browser/web_engine_browser_main_parts.cc b/fuchsia/engine/browser/web_engine_browser_main_parts.cc index 38aa87c..1d9425f 100644 --- a/fuchsia/engine/browser/web_engine_browser_main_parts.cc +++ b/fuchsia/engine/browser/web_engine_browser_main_parts.cc
@@ -55,6 +55,7 @@ #include "third_party/widevine/cdm/widevine_cdm_common.h" #include "ui/aura/screen_ozone.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/display/screen.h" #include "ui/gfx/switches.h" #include "ui/ozone/public/ozone_platform.h" #include "ui/ozone/public/ozone_switches.h" @@ -167,9 +168,7 @@ content::ContentBrowserClient* browser_client) : browser_client_(browser_client) {} -WebEngineBrowserMainParts::~WebEngineBrowserMainParts() { - display::Screen::SetScreenInstance(nullptr); -} +WebEngineBrowserMainParts::~WebEngineBrowserMainParts() = default; std::vector<content::BrowserContext*> WebEngineBrowserMainParts::browser_contexts() const { @@ -190,7 +189,6 @@ } int WebEngineBrowserMainParts::PreMainMessageLoopRun() { - DCHECK(!screen_); DCHECK_EQ(context_bindings_.size(), 0u); // Initialize the |component_inspector_| to allow diagnostics to be published. @@ -251,11 +249,7 @@ base::Unretained(this))); // Configure Ozone with an Aura implementation of the Screen abstraction. - std::unique_ptr<aura::ScreenOzone> screen_ozone = - std::make_unique<aura::ScreenOzone>(); - screen_ozone.get()->Initialize(); - screen_ = std::move(screen_ozone); - display::Screen::SetScreenInstance(screen_.get()); + screen_ = std::make_unique<aura::ScopedScreenOzone>(); // Create the FuchsiaCdmManager at startup rather than on-demand, to allow it // to perform potentially expensive startup work in the background. @@ -312,7 +306,6 @@ // that they may post cleanup tasks during teardown. // NOTE: Objects are destroyed in the reverse order of their creation. legacy_metrics_client_.reset(); - screen_.reset(); intl_profile_watcher_.reset(); base::ImportantFileWriterCleaner::GetInstance().Stop();
diff --git a/fuchsia/engine/browser/web_engine_browser_main_parts.h b/fuchsia/engine/browser/web_engine_browser_main_parts.h index 91bd530..e878565 100644 --- a/fuchsia/engine/browser/web_engine_browser_main_parts.h +++ b/fuchsia/engine/browser/web_engine_browser_main_parts.h
@@ -22,7 +22,7 @@ } namespace display { -class Screen; +class ScopedNativeScreen; } namespace content { @@ -120,7 +120,7 @@ content::ContentBrowserClient* const browser_client_; - std::unique_ptr<display::Screen> screen_; + std::unique_ptr<display::ScopedNativeScreen> screen_; // Used to publish diagnostics including the active Contexts and FrameHosts. std::unique_ptr<sys::ComponentInspector> component_inspector_;
diff --git a/headless/lib/browser/headless_browser_impl.h b/headless/lib/browser/headless_browser_impl.h index 7be22a33..7f4ac86 100644 --- a/headless/lib/browser/headless_browser_impl.h +++ b/headless/lib/browser/headless_browser_impl.h
@@ -14,6 +14,7 @@ #include "base/memory/weak_ptr.h" #include "base/task/single_thread_task_runner.h" +#include "build/build_config.h" #include "headless/lib/browser/headless_devtools_manager_delegate.h" #include "headless/public/headless_devtools_target.h" #include "headless/public/headless_export.h" @@ -28,6 +29,10 @@ } // namespace policy #endif +#if BUILDFLAG(IS_MAC) +#include "ui/display/screen.h" +#endif + namespace ui { class Compositor; } // namespace ui @@ -117,6 +122,10 @@ #endif protected: +#if BUILDFLAG(IS_MAC) + std::unique_ptr<display::ScopedNativeScreen> screen_; +#endif + base::OnceCallback<void(HeadlessBrowser*)> on_start_callback_; HeadlessBrowser::Options options_; raw_ptr<HeadlessBrowserMainParts> browser_main_parts_; // Not owned.
diff --git a/headless/lib/browser/headless_browser_impl_mac.mm b/headless/lib/browser/headless_browser_impl_mac.mm index 812572a..da3dee43 100644 --- a/headless/lib/browser/headless_browser_impl_mac.mm +++ b/headless/lib/browser/headless_browser_impl_mac.mm
@@ -65,6 +65,7 @@ } // namespace void HeadlessBrowserImpl::PlatformInitialize() { + screen_ = std::make_unique<display::ScopedNativeScreen>(); HeadlessPopUpMethods::Init(); }
diff --git a/infra/config/generated/builders/ci/android-12-x64-rel/properties.json b/infra/config/generated/builders/ci/android-12-x64-rel/properties.json index d954e2f..2d5fdd59 100644 --- a/infra/config/generated/builders/ci/android-12-x64-rel/properties.json +++ b/infra/config/generated/builders/ci/android-12-x64-rel/properties.json
@@ -1,4 +1,56 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "android-12-x64-rel", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "x64_builder" + }, + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "android-12-x64-rel", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android-12-x64-rel", + "group": "tryserver.chromium.android" + } + ] + } + }, "$build/reclient": { "instance": "rbe-chromium-trusted", "jobs": 500,
diff --git a/infra/config/generated/builders/ci/ios14-beta-simulator/properties.json b/infra/config/generated/builders/ci/ios14-beta-simulator/properties.json deleted file mode 100644 index c18caf9e..0000000 --- a/infra/config/generated/builders/ci/ios14-beta-simulator/properties.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org", - "use_luci_auth": true - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "chromium.fyi", - "recipe": "chromium", - "xcode_build_version": "13c100" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios14-sdk-simulator/properties.json b/infra/config/generated/builders/ci/ios14-sdk-simulator/properties.json deleted file mode 100644 index c18caf9e..0000000 --- a/infra/config/generated/builders/ci/ios14-sdk-simulator/properties.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org", - "use_luci_auth": true - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "chromium.fyi", - "recipe": "chromium", - "xcode_build_version": "13c100" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios16-beta-simulator/properties.json b/infra/config/generated/builders/ci/ios16-beta-simulator/properties.json new file mode 100644 index 0000000..40047b4 --- /dev/null +++ b/infra/config/generated/builders/ci/ios16-beta-simulator/properties.json
@@ -0,0 +1,63 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "ios16-beta-simulator", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-fyi-archive", + "builder_group": "chromium.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb", + "mac_toolchain" + ], + "build_config": "Debug", + "config": "chromium", + "target_bits": 64, + "target_platform": "ios" + }, + "legacy_gclient_config": { + "config": "ios" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "ios16-beta-simulator", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "ios16-beta-simulator", + "group": "tryserver.chromium.mac" + } + ] + } + }, + "$build/goma": { + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org", + "use_luci_auth": true + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "chromium.fyi", + "recipe": "chromium", + "xcode_build_version": "13c100" +} \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios16-sdk-simulator/properties.json b/infra/config/generated/builders/ci/ios16-sdk-simulator/properties.json new file mode 100644 index 0000000..1e7df42 --- /dev/null +++ b/infra/config/generated/builders/ci/ios16-sdk-simulator/properties.json
@@ -0,0 +1,63 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "ios16-sdk-simulator", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-fyi-archive", + "builder_group": "chromium.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb", + "mac_toolchain" + ], + "build_config": "Debug", + "config": "chromium", + "target_bits": 64, + "target_platform": "ios" + }, + "legacy_gclient_config": { + "config": "ios" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "ios16-sdk-simulator", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "ios16-sdk-simulator", + "group": "tryserver.chromium.mac" + } + ] + } + }, + "$build/goma": { + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org", + "use_luci_auth": true + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "chromium.fyi", + "recipe": "chromium", + "xcode_build_version": "13c100" +} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-12-x64-rel-compilator/properties.json b/infra/config/generated/builders/try/android-12-x64-rel-compilator/properties.json index dc7af2f..011e6b4 100644 --- a/infra/config/generated/builders/try/android-12-x64-rel-compilator/properties.json +++ b/infra/config/generated/builders/try/android-12-x64-rel-compilator/properties.json
@@ -1,4 +1,50 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "android-12-x64-rel", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "x64_builder" + }, + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "android-12-x64-rel", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "jobs": 300,
diff --git a/infra/config/generated/builders/try/android-12-x64-rel/properties.json b/infra/config/generated/builders/try/android-12-x64-rel/properties.json index 4205c5c..b04e2972 100644 --- a/infra/config/generated/builders/try/android-12-x64-rel/properties.json +++ b/infra/config/generated/builders/try/android-12-x64-rel/properties.json
@@ -3,6 +3,52 @@ "compilator": "android-12-x64-rel-compilator", "compilator_watcher_git_revision": "7809a690bbd935bcb3b4d922e24cabe168aaabc8" }, + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "android-12-x64-rel", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "x64_builder" + }, + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "android-12-x64-rel", + "project": "chromium" + } + ] + } + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/ios14-beta-simulator/properties.json b/infra/config/generated/builders/try/ios14-beta-simulator/properties.json deleted file mode 100644 index b9041d6..0000000 --- a/infra/config/generated/builders/try/ios14-beta-simulator/properties.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org", - "use_luci_auth": true - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.chromium.mac", - "recipe": "chromium_trybot", - "xcode_build_version": "13c100" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios14-sdk-simulator/properties.json b/infra/config/generated/builders/try/ios14-sdk-simulator/properties.json deleted file mode 100644 index b9041d6..0000000 --- a/infra/config/generated/builders/try/ios14-sdk-simulator/properties.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org", - "use_luci_auth": true - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.chromium.mac", - "recipe": "chromium_trybot", - "xcode_build_version": "13c100" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios16-beta-simulator/properties.json b/infra/config/generated/builders/try/ios16-beta-simulator/properties.json new file mode 100644 index 0000000..d39f3de --- /dev/null +++ b/infra/config/generated/builders/try/ios16-beta-simulator/properties.json
@@ -0,0 +1,57 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "ios16-beta-simulator", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-fyi-archive", + "builder_group": "chromium.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb", + "mac_toolchain" + ], + "build_config": "Debug", + "config": "chromium", + "target_bits": 64, + "target_platform": "ios" + }, + "legacy_gclient_config": { + "config": "ios" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "ios16-beta-simulator", + "project": "chromium" + } + ] + } + }, + "$build/goma": { + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org", + "use_luci_auth": true + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "tryserver.chromium.mac", + "recipe": "chromium_trybot", + "xcode_build_version": "13c100" +} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios16-sdk-simulator/properties.json b/infra/config/generated/builders/try/ios16-sdk-simulator/properties.json new file mode 100644 index 0000000..25ca46bb --- /dev/null +++ b/infra/config/generated/builders/try/ios16-sdk-simulator/properties.json
@@ -0,0 +1,57 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "ios16-sdk-simulator", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-fyi-archive", + "builder_group": "chromium.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb", + "mac_toolchain" + ], + "build_config": "Debug", + "config": "chromium", + "target_bits": 64, + "target_platform": "ios" + }, + "legacy_gclient_config": { + "config": "ios" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "ios16-sdk-simulator", + "project": "chromium" + } + ] + } + }, + "$build/goma": { + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org", + "use_luci_auth": true + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "tryserver.chromium.mac", + "recipe": "chromium_trybot", + "xcode_build_version": "13c100" +} \ No newline at end of file
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg index f032209..0f11399 100644 --- a/infra/config/generated/luci/commit-queue.cfg +++ b/infra/config/generated/luci/commit-queue.cfg
@@ -1150,14 +1150,6 @@ includable_only: true } builders { - name: "chromium/try/ios14-beta-simulator" - includable_only: true - } - builders { - name: "chromium/try/ios14-sdk-simulator" - includable_only: true - } - builders { name: "chromium/try/ios15-beta-simulator" includable_only: true } @@ -1166,6 +1158,14 @@ includable_only: true } builders { + name: "chromium/try/ios16-beta-simulator" + includable_only: true + } + builders { + name: "chromium/try/ios16-sdk-simulator" + includable_only: true + } + builders { name: "chromium/try/lacros-amd64-generic-rel" location_regexp: ".*" location_regexp_exclude: ".+/[+]/docs/.+"
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 574d45c..ede95d6 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -30573,168 +30573,6 @@ } } builders { - name: "ios14-beta-simulator" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:ios14-beta-simulator" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-11" - dimensions: "pool:luci.chromium.ci" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/ci/ios14-beta-simulator/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "chromium.fyi",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium"' - '}' - execution_timeout_secs: 36000 - caches { - name: "xcode_ios_13c100" - path: "xcode_ios_13c100.app" - } - build_numbers: YES - service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "ci_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_ci_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_ci_test_results" - test_results { - predicate { - test_id_regexp: "ninja://[^/]*blink_web_tests/.+" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - } - builders { - name: "ios14-sdk-simulator" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:ios14-sdk-simulator" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-11" - dimensions: "pool:luci.chromium.ci" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/ci/ios14-sdk-simulator/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "chromium.fyi",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium"' - '}' - execution_timeout_secs: 36000 - caches { - name: "xcode_ios_13c100" - path: "xcode_ios_13c100.app" - } - build_numbers: YES - service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "ci_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_ci_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_ci_test_results" - test_results { - predicate { - test_id_regexp: "ninja://[^/]*blink_web_tests/.+" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - } - builders { name: "ios15-beta-simulator" swarming_host: "chromium-swarm.appspot.com" dimensions: "builder:ios15-beta-simulator" @@ -30978,6 +30816,168 @@ } } builders { + name: "ios16-beta-simulator" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builder:ios16-beta-simulator" + dimensions: "cpu:x86-64" + dimensions: "os:Mac-11" + dimensions: "pool:luci.chromium.ci" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/ci/ios16-beta-simulator/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "chromium.fyi",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium"' + '}' + execution_timeout_secs: 36000 + caches { + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" + } + build_numbers: YES + service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_ci_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_ci_test_results" + test_results { + predicate { + test_id_regexp: "ninja://[^/]*blink_web_tests/.+" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { + name: "ios16-sdk-simulator" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builder:ios16-sdk-simulator" + dimensions: "cpu:x86-64" + dimensions: "os:Mac-11" + dimensions: "pool:luci.chromium.ci" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/ci/ios16-sdk-simulator/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "chromium.fyi",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium"' + '}' + execution_timeout_secs: 36000 + caches { + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" + } + build_numbers: YES + service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_ci_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_ci_test_results" + test_results { + predicate { + test_id_regexp: "ninja://[^/]*blink_web_tests/.+" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "lacros-amd64-generic-binary-size-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" @@ -61141,190 +61141,6 @@ } } builders { - name: "ios14-beta-simulator" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:ios14-beta-simulator" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-11" - dimensions: "pool:luci.chromium.try" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/ios14-beta-simulator/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.chromium.mac",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium_trybot"' - '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - caches { - name: "win_toolchain" - path: "win_toolchain" - } - caches { - name: "xcode_ios_13c100" - path: "xcode_ios_13c100.app" - } - build_numbers: YES - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - task_template_canary_percentage { - value: 5 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://[^/]*blink_web_tests/.+" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - } - builders { - name: "ios14-sdk-simulator" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:ios14-sdk-simulator" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-11" - dimensions: "pool:luci.chromium.try" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/ios14-sdk-simulator/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.chromium.mac",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium_trybot"' - '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - caches { - name: "win_toolchain" - path: "win_toolchain" - } - caches { - name: "xcode_ios_13c100" - path: "xcode_ios_13c100.app" - } - build_numbers: YES - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - task_template_canary_percentage { - value: 5 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://[^/]*blink_web_tests/.+" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - } - builders { name: "ios15-beta-simulator" swarming_host: "chromium-swarm.appspot.com" dimensions: "builder:ios15-beta-simulator" @@ -61509,6 +61325,190 @@ } } builders { + name: "ios16-beta-simulator" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builder:ios16-beta-simulator" + dimensions: "cpu:x86-64" + dimensions: "os:Mac-11" + dimensions: "pool:luci.chromium.try" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/try/ios16-beta-simulator/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "tryserver.chromium.mac",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium_trybot"' + '}' + execution_timeout_secs: 14400 + expiration_secs: 7200 + grace_period { + seconds: 120 + } + caches { + name: "win_toolchain" + path: "win_toolchain" + } + caches { + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" + } + build_numbers: YES + service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" + task_template_canary_percentage { + value: 5 + } + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "try_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_try_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_try_test_results" + test_results { + predicate { + test_id_regexp: "ninja://[^/]*blink_web_tests/.+" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { + name: "ios16-sdk-simulator" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builder:ios16-sdk-simulator" + dimensions: "cpu:x86-64" + dimensions: "os:Mac-11" + dimensions: "pool:luci.chromium.try" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/try/ios16-sdk-simulator/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "tryserver.chromium.mac",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium_trybot"' + '}' + execution_timeout_secs: 14400 + expiration_secs: 7200 + grace_period { + seconds: 120 + } + caches { + name: "win_toolchain" + path: "win_toolchain" + } + caches { + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" + } + build_numbers: YES + service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" + task_template_canary_percentage { + value: 5 + } + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "try_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_try_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_try_test_results" + test_results { + predicate { + test_id_regexp: "ninja://[^/]*blink_web_tests/.+" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "lacros-amd64-generic-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builder:lacros-amd64-generic-rel"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index f3c1d73..238d045 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -7707,16 +7707,6 @@ short_name: "wk" } builders { - name: "buildbucket/luci.chromium.ci/ios14-beta-simulator" - category: "iOS|iOS14" - short_name: "ios14" - } - builders { - name: "buildbucket/luci.chromium.ci/ios14-sdk-simulator" - category: "iOS|iOS14" - short_name: "sdk14" - } - builders { name: "buildbucket/luci.chromium.ci/ios15-sdk-device" category: "iOS|iOS15" short_name: "dev" @@ -7732,6 +7722,16 @@ short_name: "sdk15" } builders { + name: "buildbucket/luci.chromium.ci/ios16-beta-simulator" + category: "iOS|iOS16" + short_name: "ios16" + } + builders { + name: "buildbucket/luci.chromium.ci/ios16-sdk-simulator" + category: "iOS|iOS16" + short_name: "sdk16" + } + builders { name: "buildbucket/luci.chromium.ci/ios-m1-simulator" category: "iOS|iOSM1" short_name: "iosM1" @@ -16043,18 +16043,18 @@ name: "buildbucket/luci.chromium.try/ios-simulator-rts" } builders { - name: "buildbucket/luci.chromium.try/ios14-beta-simulator" - } - builders { - name: "buildbucket/luci.chromium.try/ios14-sdk-simulator" - } - builders { name: "buildbucket/luci.chromium.try/ios15-beta-simulator" } builders { name: "buildbucket/luci.chromium.try/ios15-sdk-simulator" } builders { + name: "buildbucket/luci.chromium.try/ios16-beta-simulator" + } + builders { + name: "buildbucket/luci.chromium.try/ios16-sdk-simulator" + } + builders { name: "buildbucket/luci.chromium.try/lacros-amd64-generic-rel" } builders { @@ -17425,18 +17425,18 @@ name: "buildbucket/luci.chromium.try/ios-simulator-rts" } builders { - name: "buildbucket/luci.chromium.try/ios14-beta-simulator" - } - builders { - name: "buildbucket/luci.chromium.try/ios14-sdk-simulator" - } - builders { name: "buildbucket/luci.chromium.try/ios15-beta-simulator" } builders { name: "buildbucket/luci.chromium.try/ios15-sdk-simulator" } builders { + name: "buildbucket/luci.chromium.try/ios16-beta-simulator" + } + builders { + name: "buildbucket/luci.chromium.try/ios16-sdk-simulator" + } + builders { name: "buildbucket/luci.chromium.try/mac-arm64-on-arm64-rel" } builders {
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg index b41d55a..dfbb3a8 100644 --- a/infra/config/generated/luci/luci-scheduler.cfg +++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -5169,28 +5169,6 @@ } } job { - id: "ios14-beta-simulator" - realm: "ci" - schedule: "0 0,4,8,12,16,20 * * *" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "ci" - builder: "ios14-beta-simulator" - } -} -job { - id: "ios14-sdk-simulator" - realm: "ci" - schedule: "0 2,6,10,14,18,22 * * *" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "ci" - builder: "ios14-sdk-simulator" - } -} -job { id: "ios15-beta-simulator" realm: "ci" acl_sets: "ci" @@ -5221,6 +5199,28 @@ } } job { + id: "ios16-beta-simulator" + realm: "ci" + schedule: "0 0,4,8,12,16,20 * * *" + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "ios16-beta-simulator" + } +} +job { + id: "ios16-sdk-simulator" + realm: "ci" + schedule: "0 2,6,10,14,18,22 * * *" + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "ios16-sdk-simulator" + } +} +job { id: "lacros-amd64-generic-binary-size-rel" realm: "ci" acl_sets: "ci"
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.star b/infra/config/subprojects/chromium/ci/chromium.android.star index f2864ac..71e1d142 100644 --- a/infra/config/subprojects/chromium/ci/chromium.android.star +++ b/infra/config/subprojects/chromium/ci/chromium.android.star
@@ -1152,6 +1152,28 @@ ci.builder( name = "android-12-x64-rel", + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + "enable_reclient", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "mb", + ], + build_config = builder_config.build_config.RELEASE, + target_bits = 64, + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "x64_builder", + ), + build_gs_bucket = "chromium-android-archive", + ), console_view_entry = consoles.console_view_entry( category = "builder_tester|x64", short_name = "12",
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star index 68dc731..5f1213c 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -1330,28 +1330,6 @@ ) fyi_ios_builder( - name = "ios14-beta-simulator", - console_view_entry = consoles.console_view_entry( - category = "iOS|iOS14", - short_name = "ios14", - ), - os = os.MAC_11, - schedule = "0 0,4,8,12,16,20 * * *", - triggered_by = [], -) - -fyi_ios_builder( - name = "ios14-sdk-simulator", - console_view_entry = consoles.console_view_entry( - category = "iOS|iOS14", - short_name = "sdk14", - ), - os = os.MAC_11, - schedule = "0 2,6,10,14,18,22 * * *", - triggered_by = [], -) - -fyi_ios_builder( name = "ios15-beta-simulator", console_view_entry = [ consoles.console_view_entry( @@ -1386,6 +1364,60 @@ xcode = xcode.x13betabots, ) +fyi_ios_builder( + name = "ios16-beta-simulator", + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "ios", + ), + chromium_config = builder_config.chromium_config( + config = "chromium", + apply_configs = [ + "mb", + "mac_toolchain", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.IOS, + ), + build_gs_bucket = "chromium-fyi-archive", + ), + console_view_entry = consoles.console_view_entry( + category = "iOS|iOS16", + short_name = "ios16", + ), + os = os.MAC_11, + schedule = "0 0,4,8,12,16,20 * * *", + triggered_by = [], +) + +fyi_ios_builder( + name = "ios16-sdk-simulator", + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "ios", + ), + chromium_config = builder_config.chromium_config( + config = "chromium", + apply_configs = [ + "mb", + "mac_toolchain", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.IOS, + ), + build_gs_bucket = "chromium-fyi-archive", + ), + console_view_entry = consoles.console_view_entry( + category = "iOS|iOS16", + short_name = "sdk16", + ), + os = os.MAC_11, + schedule = "0 2,6,10,14,18,22 * * *", + triggered_by = [], +) + ci.builder( # An FYI version of the following builders that runs on Focal: # https://ci.chromium.org/p/chromium/builders/ci/Linux%20MSan%20Builder
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star index c88469d..0be076f9 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
@@ -48,6 +48,9 @@ try_.orchestrator_builder( name = "android-12-x64-rel", compilator = "android-12-x64-rel-compilator", + mirrors = [ + "ci/android-12-x64-rel", + ], # TODO(crbug.com/1225851): Enable it on branch after running on CQ # branch_selector = branches.STANDARD_MILESTONE, main_list_view = "try",
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star index c79a1b8..abeb5a0 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
@@ -374,16 +374,6 @@ ) ios_builder( - name = "ios14-beta-simulator", - os = os.MAC_11, -) - -ios_builder( - name = "ios14-sdk-simulator", - os = os.MAC_11, -) - -ios_builder( name = "ios15-beta-simulator", ) @@ -393,6 +383,22 @@ os = os.MAC_12, ) +ios_builder( + name = "ios16-beta-simulator", + os = os.MAC_11, + mirrors = [ + "ci/ios16-beta-simulator", + ], +) + +ios_builder( + name = "ios16-sdk-simulator", + os = os.MAC_11, + mirrors = [ + "ci/ios16-sdk-simulator", + ], +) + try_.gpu.optional_tests_builder( name = "mac_optional_gpu_tests_rel", branch_selector = branches.DESKTOP_EXTENDED_STABLE_MILESTONE,
diff --git a/ios/build/bots/scripts/test_apps.py b/ios/build/bots/scripts/test_apps.py index 355d322..9752c0d 100644 --- a/ios/build/bots/scripts/test_apps.py +++ b/ios/build/bots/scripts/test_apps.py
@@ -131,6 +131,11 @@ self.host_app_path = kwargs.get('host_app_path') self.inserted_libs = kwargs.get('inserted_libs') or [] + def remove_gtest_sharding_env_vars(self): + """Removes sharding related env vars from self.env_vars.""" + for env_var_key in ['GTEST_SHARD_INDEX', 'GTEST_TOTAL_SHARDS']: + self.env_vars.pop(env_var_key, None) + def fill_xctest_run(self, out_dir): """Fills xctestrun file by egtests.
diff --git a/ios/build/bots/scripts/test_apps_test.py b/ios/build/bots/scripts/test_apps_test.py index 40a4d8f9e..77a6505a 100755 --- a/ios/build/bots/scripts/test_apps_test.py +++ b/ios/build/bots/scripts/test_apps_test.py
@@ -228,6 +228,27 @@ '_module']['CommandLineArguments'] self.assertTrue('--gtest_repeat=2' in cmd_args) + @mock.patch('test_apps.get_bundle_id', return_value=_BUNDLE_ID) + @mock.patch('os.path.exists', return_value=True) + def test_remove_gtest_sharding_env_vars(self, _1, _2): + gtests_app = test_apps.GTestsApp( + 'app_path', env_vars=['GTEST_SHARD_INDEX=1', 'GTEST_TOTAL_SHARDS=2']) + assert all(key in gtests_app.env_vars + for key in ['GTEST_SHARD_INDEX', 'GTEST_TOTAL_SHARDS']) + gtests_app.remove_gtest_sharding_env_vars() + assert not any(key in gtests_app.env_vars + for key in ['GTEST_SHARD_INDEX', 'GTEST_TOTAL_SHARDS']) + + @mock.patch('test_apps.get_bundle_id', return_value=_BUNDLE_ID) + @mock.patch('os.path.exists', return_value=True) + def test_remove_gtest_sharding_env_vars_non_exist(self, _1, _2): + gtests_app = test_apps.GTestsApp('app_path') + assert not any(key in gtests_app.env_vars + for key in ['GTEST_SHARD_INDEX', 'GTEST_TOTAL_SHARDS']) + gtests_app.remove_gtest_sharding_env_vars() + assert not any(key in gtests_app.env_vars + for key in ['GTEST_SHARD_INDEX', 'GTEST_TOTAL_SHARDS']) + class EgtestsAppTest(test_runner_test.TestCase): """Tests to test methods of EgTestsApp."""
diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py index 54802e22..69f382d 100644 --- a/ios/build/bots/scripts/test_runner.py +++ b/ios/build/bots/scripts/test_runner.py
@@ -596,6 +596,11 @@ LOGGER.warning('Crashed during %s, resuming...\n', list(result.crashed_tests())) test_app.excluded_tests = list(overall_result.all_test_names()) + # Changing test filter will change selected gtests in this shard. + # Thus, sharding env vars have to be cleared to ensure needed tests + # are run. This means there might be duplicate same tests across + # the shards. + test_app.remove_gtest_sharding_env_vars() retry_out_dir = os.path.join( self.out_dir, 'retry_after_crash_%d' % int(time.time())) result = self._run( @@ -622,6 +627,10 @@ for test in tests_to_retry: LOGGER.info('Retry #%s for %s.\n', i + 1, test) test_app.included_tests = [test] + # Changing test filter will change selected gtests in this shard. + # Thus, sharding env vars have to be cleared to ensure the test + # runs when it's the only test in gtest_filter. + test_app.remove_gtest_sharding_env_vars() test_retry_sub_dir = '%s_retry_%d' % (test.replace('/', '_'), i) retry_out_dir = os.path.join(self.out_dir, test_retry_sub_dir) retry_result = self._run(
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 2d80583..e69dcd5 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -265,6 +265,7 @@ "//rlz/buildflags", "//services/network:network_service", "//ui/base", + "//ui/display", ] if (enable_rlz) {
diff --git a/ios/chrome/browser/ios_chrome_main_parts.mm b/ios/chrome/browser/ios_chrome_main_parts.mm index c43c354..733a7d65 100644 --- a/ios/chrome/browser/ios_chrome_main_parts.mm +++ b/ios/chrome/browser/ios_chrome_main_parts.mm
@@ -85,6 +85,10 @@ #include "base/allocator/allocator_shim.h" #endif +#if DCHECK_IS_ON() +#include "ui/display/screen_base.h" +#endif + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif @@ -125,7 +129,15 @@ net::URLRequest::SetDefaultCookiePolicyToBlock(); } -IOSChromeMainParts::~IOSChromeMainParts() {} +IOSChromeMainParts::~IOSChromeMainParts() { +#if DCHECK_IS_ON() + // The screen object is never deleted on IOS. Make sure that all display + // observers are removed at the end. + display::ScreenBase* screen = + static_cast<display::ScreenBase*>(display::Screen::GetScreen()); + DCHECK(!screen->HasDisplayObservers()); +#endif +} void IOSChromeMainParts::PreEarlyInitialization() { #if BUILDFLAG(USE_ALLOCATOR_SHIM)
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index 1516de0..98aff0c 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -4fc130573215e902c5e556c32ab73d3c3c2bcb69 \ No newline at end of file +da2bc8b39be83996a338bb4533e039086c8f3d5f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index e80387b..110b71f 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -d7348369bb2fecda767b13d0ca52c826c171037a \ No newline at end of file +f9680a08f5d364609cc7088c952d424e2223d15e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index d22f654..782f0403 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -4131c1b7045b3a92a99ad185d8a59ebed63ca312 \ No newline at end of file +189045ce9b6ab6e0de583c3f3f6f1bd33d3c666f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index 67ce3a2..088eb003 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -cc79400827a328fa806ac182b630e97f0fe57136 \ No newline at end of file +fbd2678c6e85d3d9bc3c052f8cee4a48aed0de5e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 index c6c59cb..f3891da5 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -9d8f9a4af3f683ae32be49858c4a521b9415b86c \ No newline at end of file +bcd9e458d866505d51b404592dea764e5c2c5c87 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 index c3adbfeef..235e1f34 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -7ca2d0b55fbaf6554beedc7ebdd658e96671602c \ No newline at end of file +821ab244e45baa91893f2776299d31a67f615bd1 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index 2b9511f..f29c684 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -0668c5faa00ce98b0c1b2c042306d9789fcd02f0 \ No newline at end of file +11aa14dc070b66c701f5018d46a77b5e6cec4770 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index 4fc19228..2426973 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -5b70c584e649ed18839a48020c655d907e5e65f3 \ No newline at end of file +c3c3d96709d8be611c3d4c59ea8fdd9dbae589b7 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index 35fdba5d..d597f911 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -4fe41dd5965d0790dcb833866198f3c9ec00cf39 \ No newline at end of file +2b1890856f2febe5baf4f1e867f07fc62300b9d4 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index 16e1f69..0ec5d9e4 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -bec973c5da4b0f03a6b496ad263e0d99c4e572fc \ No newline at end of file +24b33584539f5882723b77d6722db91e06bcec09 \ No newline at end of file
diff --git a/ios/testing/earl_grey/BUILD.gn b/ios/testing/earl_grey/BUILD.gn index 6f5935bb..a5b4ab0 100644 --- a/ios/testing/earl_grey/BUILD.gn +++ b/ios/testing/earl_grey/BUILD.gn
@@ -63,5 +63,6 @@ "//ios/third_party/edo", "//ios/web/common", "//testing/gtest:gtest", + "//ui/display", ] }
diff --git a/ios/testing/earl_grey/DEPS b/ios/testing/earl_grey/DEPS new file mode 100644 index 0000000..e5069168 --- /dev/null +++ b/ios/testing/earl_grey/DEPS
@@ -0,0 +1,5 @@ +specific_include_rules = { + "base_earl_grey_test_case.mm": [ + "+ui/display" + ] +}
diff --git a/ios/testing/earl_grey/base_earl_grey_test_case.mm b/ios/testing/earl_grey/base_earl_grey_test_case.mm index da86c76c..5440688 100644 --- a/ios/testing/earl_grey/base_earl_grey_test_case.mm +++ b/ios/testing/earl_grey/base_earl_grey_test_case.mm
@@ -16,6 +16,10 @@ #import "ios/testing/earl_grey/coverage_utils.h" #import "ios/testing/earl_grey/earl_grey_test.h" +#if DCHECK_IS_ON() +#include "ui/display/screen_base.h" +#endif + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif @@ -72,6 +76,14 @@ } + (void)tearDown { +#if DCHECK_IS_ON() + // The same screen object is shared across multiple test runs on IOS build. + // Make sure that all display observers are removed at the end of each + // test. + display::ScreenBase* screen = + static_cast<display::ScreenBase*>(display::Screen::GetScreen()); + DCHECK(!screen->HasDisplayObservers()); +#endif if ([[AppLaunchManager sharedManager] appIsLaunched]) { [CoverageUtils writeClangCoverageProfile]; [CoverageUtils resetCoverageProfileCounters];
diff --git a/ios/web/shell/BUILD.gn b/ios/web/shell/BUILD.gn index bdf5d2c9..a35ad69 100644 --- a/ios/web/shell/BUILD.gn +++ b/ios/web/shell/BUILD.gn
@@ -63,6 +63,7 @@ "//net", "//net:extras", "//ui/base", + "//ui/display", ] frameworks = [
diff --git a/ios/web/shell/shell_web_main_parts.mm b/ios/web/shell/shell_web_main_parts.mm index 9833401f..0e9bbbf 100644 --- a/ios/web/shell/shell_web_main_parts.mm +++ b/ios/web/shell/shell_web_main_parts.mm
@@ -6,6 +6,10 @@ #include "ios/web/shell/shell_browser_state.h" +#if DCHECK_IS_ON() +#include "ui/display/screen_base.h" +#endif + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif @@ -16,6 +20,13 @@ } ShellWebMainParts::~ShellWebMainParts() { +#if DCHECK_IS_ON() + // The screen object is never deleted on IOS. Make sure that all display + // observers are removed at the end. + display::ScreenBase* screen = + static_cast<display::ScreenBase*>(display::Screen::GetScreen()); + DCHECK(!screen->HasDisplayObservers()); +#endif } void ShellWebMainParts::PreMainMessageLoopRun() {
diff --git a/ios/web/test/BUILD.gn b/ios/web/test/BUILD.gn index 60324ccc8..fe065aa6 100644 --- a/ios/web/test/BUILD.gn +++ b/ios/web/test/BUILD.gn
@@ -71,6 +71,7 @@ "//net", "//third_party/ocmock", "//ui/base", + "//ui/display", ] sources = [
diff --git a/ios/web/test/web_int_test.mm b/ios/web/test/web_int_test.mm index ad4cca2..896a5add 100644 --- a/ios/web/test/web_int_test.mm +++ b/ios/web/test/web_int_test.mm
@@ -15,6 +15,10 @@ #import "ios/web/public/test/web_view_interaction_test_util.h" #include "ios/web/public/web_state_observer.h" +#if DCHECK_IS_ON() +#include "ui/display/screen_base.h" +#endif + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif @@ -81,6 +85,15 @@ [WKWebsiteDataStore allWebsiteDataTypes]); WebTest::TearDown(); + +#if DCHECK_IS_ON() + // The same screen object is shared across multiple test runs on IOS build. + // Make sure that all display observers are removed at the end of each + // test. + display::ScreenBase* screen = + static_cast<display::ScreenBase*>(display::Screen::GetScreen()); + DCHECK(!screen->HasDisplayObservers()); +#endif } bool WebIntTest::ExecuteBlockAndWaitForLoad(const GURL& url,
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn index 55a16746..3a9fd83 100644 --- a/ios/web_view/BUILD.gn +++ b/ios/web_view/BUILD.gn
@@ -371,6 +371,7 @@ "//services/network:network_service", "//third_party/abseil-cpp:absl", "//ui/base", + "//ui/display", "//url", ]
diff --git a/ios/web_view/internal/DEPS b/ios/web_view/internal/DEPS index 3d26b42b..271ac1bb 100644 --- a/ios/web_view/internal/DEPS +++ b/ios/web_view/internal/DEPS
@@ -69,3 +69,9 @@ "+ui/base", "+ui/gfx", ] + +specific_include_rules = { + "web_view_web_main_parts.mm": [ + "+ui/display" + ] +}
diff --git a/ios/web_view/internal/web_view_web_main_parts.mm b/ios/web_view/internal/web_view_web_main_parts.mm index f6a80877..534632d7 100644 --- a/ios/web_view/internal/web_view_web_main_parts.mm +++ b/ios/web_view/internal/web_view_web_main_parts.mm
@@ -24,6 +24,10 @@ #include "ui/base/l10n/l10n_util_mac.h" #include "ui/base/resource/resource_bundle.h" +#if DCHECK_IS_ON() +#include "ui/display/screen_base.h" +#endif + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif @@ -33,7 +37,15 @@ WebViewWebMainParts::WebViewWebMainParts() : field_trial_list_(/*entropy_provider=*/nullptr) {} -WebViewWebMainParts::~WebViewWebMainParts() = default; +WebViewWebMainParts::~WebViewWebMainParts() { +#if DCHECK_IS_ON() + // The screen object is never deleted on IOS. Make sure that all display + // observers are removed at the end. + display::ScreenBase* screen = + static_cast<display::ScreenBase*>(display::Screen::GetScreen()); + DCHECK(!screen->HasDisplayObservers()); +#endif +} void WebViewWebMainParts::PreCreateMainMessageLoop() { l10n_util::OverrideLocaleWithCocoaLocale();
diff --git a/media/base/callback_registry.h b/media/base/callback_registry.h index b89be2c..faf5504 100644 --- a/media/base/callback_registry.h +++ b/media/base/callback_registry.h
@@ -70,8 +70,8 @@ void Notify(Args&&... args) { DVLOG(1) << __func__; base::AutoLock lock(lock_); - for (auto const& entry : callbacks_) - entry.second.Run(std::forward<Args>(args)...); + for (auto const& [key_id, callback] : callbacks_) + callback.Run(std::forward<Args>(args)...); } private:
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 31f3dbe..7ae312d8 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h
@@ -108,6 +108,7 @@ void(const std::vector<MediaTrack::Id>&, base::OnceClosure)); MOCK_METHOD2(OnSelectedVideoTrackChanged, void(absl::optional<MediaTrack::Id>, base::OnceClosure)); + MOCK_METHOD0(OnExternalVideoFrameRequest, void()); // TODO(sandersd): This should automatically return true between Start() and // Stop(). (Or better, remove it from the interface entirely.)
diff --git a/media/base/pipeline.h b/media/base/pipeline.h index 556d62c..f1c6ac1 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h
@@ -151,6 +151,10 @@ absl::optional<MediaTrack::Id> selected_track_id, base::OnceClosure change_completed_cb) = 0; + // Signal to the pipeline that there has been a client request to access + // video frame data. + virtual void OnExternalVideoFrameRequest() = 0; + // Stops the pipeline. This is a blocking function. // If the pipeline is started, it must be stopped before destroying it. // It it permissible to call Stop() at any point during the lifetime of the
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index 93f4e72..23f06c44 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc
@@ -100,6 +100,8 @@ absl::optional<MediaTrack::Id> selected_track_id, base::OnceClosure change_completed_cb); + void OnExternalVideoFrameRequest(); + private: // Contains state shared between main and media thread. On the media thread // each member can be read without locking, but writing requires locking. On @@ -756,6 +758,27 @@ std::move(change_completed_cb))); } +void PipelineImpl::OnExternalVideoFrameRequest() { + // This function is currently a no-op unless we're on a Windows build with + // Media Foundation for Clear running. + DCHECK(thread_checker_.CalledOnValidThread()); + if (!external_video_frame_request_signaled_) { + external_video_frame_request_signaled_ = true; + media_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&RendererWrapper::OnExternalVideoFrameRequest, + base::Unretained(renderer_wrapper_.get()))); + } +} + +void PipelineImpl::RendererWrapper::OnExternalVideoFrameRequest() { + DCHECK(media_task_runner_->BelongsToCurrentThread()); + if (!shared_state_.renderer) { + return; + } + + shared_state_.renderer->OnExternalVideoFrameRequest(); +} + void PipelineImpl::RendererWrapper::OnDemuxerCompletedTrackChange( base::OnceClosure change_completed_cb, DemuxerStream::Type stream_type, @@ -1242,6 +1265,7 @@ seek_cb_ = std::move(seek_cb); last_media_time_ = base::TimeDelta(); seek_time_ = kNoTimestamp; + external_video_frame_request_signaled_ = false; // By default, create a default renderer to avoid additional start-to-play // latency caused by asynchronous Renderer creation. When |start_type| is @@ -1335,6 +1359,7 @@ seek_cb_ = std::move(seek_cb); seek_time_ = time; last_media_time_ = base::TimeDelta(); + external_video_frame_request_signaled_ = false; // Always create a default renderer for Resume(). auto default_renderer = create_renderer_cb_.Run(absl::nullopt);
diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index 6262fa9..0a930d0 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h
@@ -130,6 +130,8 @@ absl::optional<MediaTrack::Id> selected_track_id, base::OnceClosure change_completed_cb) override; + void OnExternalVideoFrameRequest() override; + private: friend class MediaLog; class RendererWrapper; @@ -219,6 +221,13 @@ // Cached suspension state for the RendererWrapper. bool is_suspended_; + // 'external_video_frame_request_signaled_' tracks whether we've called + // OnExternalVideoFrameRequest on the current renderer. Calls which may + // create a new renderer in the RendererWrapper (Start, Resume, SetCdm) will + // reset this member. There is no guarantee to the client that + // OnExternalVideoFrameRequest will be called only once. + bool external_video_frame_request_signaled_ = false; + base::ThreadChecker thread_checker_; base::WeakPtrFactory<PipelineImpl> weak_factory_{this}; };
diff --git a/media/base/renderer.cc b/media/base/renderer.cc index c83cf95e..e2cb8d3 100644 --- a/media/base/renderer.cc +++ b/media/base/renderer.cc
@@ -39,4 +39,8 @@ // Not supported by most renderers. } +void Renderer::OnExternalVideoFrameRequest() { + // Default implementation of OnExternalVideoFrameRequest is to no-op. +} + } // namespace media
diff --git a/media/base/renderer.h b/media/base/renderer.h index 8b26b864..b7738604f 100644 --- a/media/base/renderer.h +++ b/media/base/renderer.h
@@ -92,6 +92,17 @@ virtual void OnEnabledAudioTracksChanged( const std::vector<DemuxerStream*>& enabled_tracks, base::OnceClosure change_completed_cb); + + // Signal to the renderer that there has been a client request to access a + // VideoFrame. This signal may be used by the renderer to ensure it is + // operating in a mode which produces a VideoFrame usable by the client. + // E.g., the MediaFoundationRendererClient on Windows has two modes + // of operation: Frame Server & Direct Composition. Direct Composition mode + // does not produce a VideoFrame with an accessible 'data' buffer, so clients + // cannot access the underlying image data. In order for + // MediaFoundationRendererClient to produce a VideoFrame with 'data' + // accessible by the client it must switch to operate in Frame Server mode. + virtual void OnExternalVideoFrameRequest(); }; } // namespace media
diff --git a/media/capabilities/webrtc_video_stats_db_impl.cc b/media/capabilities/webrtc_video_stats_db_impl.cc index fefbc7b7..dd524f5 100644 --- a/media/capabilities/webrtc_video_stats_db_impl.cc +++ b/media/capabilities/webrtc_video_stats_db_impl.cc
@@ -413,10 +413,10 @@ collection.emplace(); const base::TimeDelta max_time_to_keep_stats = GetMaxTimeToKeepStats(); - for (auto const& stats_proto : *stats_proto_collection) { - if (AreStatsValid(&stats_proto.second)) { + for (auto const& [pixel_key, video_stats_entry] : *stats_proto_collection) { + if (AreStatsValid(&video_stats_entry)) { VideoStatsEntry entry; - for (auto const& stats : stats_proto.second.stats()) { + for (auto const& stats : video_stats_entry.stats()) { if (wall_clock_->Now() - base::Time::FromJsTime(stats.timestamp()) <= max_time_to_keep_stats) { entry.emplace_back(stats.timestamp(), stats.frames_processed(), @@ -427,7 +427,7 @@ if (!entry.empty()) { absl::optional<int> pixels = - VideoDescKey::ParsePixelsFromKey(stats_proto.first); + VideoDescKey::ParsePixelsFromKey(pixel_key); if (pixels) { collection->insert({*pixels, std::move(entry)}); }
diff --git a/media/capture/video/linux/fake_v4l2_impl.cc b/media/capture/video/linux/fake_v4l2_impl.cc index 40b22bb..94e9af7 100644 --- a/media/capture/video/linux/fake_v4l2_impl.cc +++ b/media/capture/video/linux/fake_v4l2_impl.cc
@@ -80,6 +80,8 @@ timeperframe_.denominator = kDefaultFrameInternvalDenominator; } + ~OpenedDevice() { DCHECK(!frame_production_thread_.IsRunning()); } + const std::string& device_id() const { return config_.descriptor.device_id; } int open_flags() const { return open_flags_; }
diff --git a/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc b/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc index 8fe2587..38b9519 100644 --- a/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc +++ b/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc
@@ -35,6 +35,8 @@ std::move(fake_device_provider)); } + void TearDown() override { task_environment_.RunUntilIdle(); } + base::test::TaskEnvironment task_environment_; FakeV4L2Impl* fake_v4l2_; FakeDeviceProvider* fake_device_provider_;
diff --git a/media/capture/video/linux/video_capture_device_linux.cc b/media/capture/video/linux/video_capture_device_linux.cc index b4dfd14..3f2848a 100644 --- a/media/capture/video/linux/video_capture_device_linux.cc +++ b/media/capture/video/linux/video_capture_device_linux.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/task/single_thread_task_runner.h" +#include "base/task/thread_pool.h" #include "build/build_config.h" #include "media/capture/video/linux/v4l2_capture_delegate.h" @@ -56,15 +57,16 @@ const VideoCaptureDeviceDescriptor& device_descriptor) : device_descriptor_(device_descriptor), v4l2_(std::move(v4l2)), - v4l2_thread_("V4L2CaptureThread"), + task_runner_(base::ThreadPool::CreateSingleThreadTaskRunner( + {base::TaskPriority::USER_BLOCKING, base::MayBlock(), + base::WithBaseSyncPrimitives()}, + base::SingleThreadTaskRunnerThreadMode::DEDICATED)), rotation_(0) {} VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Check if the thread is running. - // This means that the device has not been StopAndDeAllocate()d properly. - DCHECK(!v4l2_thread_.IsRunning()); - v4l2_thread_.Stop(); + DCHECK(!capture_impl_) + << "StopAndDeAllocate() must be called before destruction."; } void VideoCaptureDeviceLinux::AllocateAndStart( @@ -72,97 +74,74 @@ std::unique_ptr<VideoCaptureDevice::Client> client) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!capture_impl_); - if (v4l2_thread_.IsRunning()) - return; // Wrong state. - v4l2_thread_.Start(); const int line_frequency = TranslatePowerLineFrequencyToV4L2(GetPowerLineFrequency(params)); capture_impl_ = std::make_unique<V4L2CaptureDelegate>( - v4l2_.get(), device_descriptor_, v4l2_thread_.task_runner(), - line_frequency, rotation_); + v4l2_.get(), device_descriptor_, task_runner_, line_frequency, rotation_); if (!capture_impl_) { client->OnError(VideoCaptureError:: kDeviceCaptureLinuxFailedToCreateVideoCaptureDelegate, FROM_HERE, "Failed to create VideoCaptureDelegate"); return; } - v4l2_thread_.task_runner()->PostTask( + task_runner_->PostTask( FROM_HERE, base::BindOnce(&V4L2CaptureDelegate::AllocateAndStart, capture_impl_->GetWeakPtr(), params.requested_format.frame_size.width(), params.requested_format.frame_size.height(), params.requested_format.frame_rate, std::move(client))); - - for (auto& request : photo_requests_queue_) - v4l2_thread_.task_runner()->PostTask(FROM_HERE, std::move(request)); - photo_requests_queue_.clear(); } void VideoCaptureDeviceLinux::StopAndDeAllocate() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!v4l2_thread_.IsRunning()) + if (!capture_impl_) return; // Wrong state. - v4l2_thread_.task_runner()->PostTask( - FROM_HERE, base::BindOnce(&V4L2CaptureDelegate::StopAndDeAllocate, - capture_impl_->GetWeakPtr())); - v4l2_thread_.task_runner()->DeleteSoon(FROM_HERE, capture_impl_.release()); - v4l2_thread_.Stop(); + task_runner_->PostTask(FROM_HERE, + base::BindOnce(&V4L2CaptureDelegate::StopAndDeAllocate, + capture_impl_->GetWeakPtr())); + task_runner_->DeleteSoon(FROM_HERE, std::move(capture_impl_)); capture_impl_ = nullptr; } void VideoCaptureDeviceLinux::TakePhoto(TakePhotoCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(capture_impl_); - auto functor = + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&V4L2CaptureDelegate::TakePhoto, - capture_impl_->GetWeakPtr(), std::move(callback)); - if (!v4l2_thread_.IsRunning()) { - // We have to wait until we get the device AllocateAndStart()ed. - photo_requests_queue_.push_back(std::move(functor)); - return; - } - v4l2_thread_.task_runner()->PostTask(FROM_HERE, std::move(functor)); + capture_impl_->GetWeakPtr(), std::move(callback))); } void VideoCaptureDeviceLinux::GetPhotoState(GetPhotoStateCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto functor = + DCHECK(capture_impl_); + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&V4L2CaptureDelegate::GetPhotoState, - capture_impl_->GetWeakPtr(), std::move(callback)); - if (!v4l2_thread_.IsRunning()) { - // We have to wait until we get the device AllocateAndStart()ed. - photo_requests_queue_.push_back(std::move(functor)); - return; - } - v4l2_thread_.task_runner()->PostTask(FROM_HERE, std::move(functor)); + capture_impl_->GetWeakPtr(), std::move(callback))); } void VideoCaptureDeviceLinux::SetPhotoOptions( mojom::PhotoSettingsPtr settings, SetPhotoOptionsCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto functor = base::BindOnce(&V4L2CaptureDelegate::SetPhotoOptions, + DCHECK(capture_impl_); + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&V4L2CaptureDelegate::SetPhotoOptions, capture_impl_->GetWeakPtr(), - std::move(settings), std::move(callback)); - if (!v4l2_thread_.IsRunning()) { - // We have to wait until we get the device AllocateAndStart()ed. - photo_requests_queue_.push_back(std::move(functor)); - return; - } - v4l2_thread_.task_runner()->PostTask(FROM_HERE, std::move(functor)); + std::move(settings), std::move(callback))); } void VideoCaptureDeviceLinux::SetRotation(int rotation) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(capture_impl_); rotation_ = rotation; - if (v4l2_thread_.IsRunning()) { - v4l2_thread_.task_runner()->PostTask( - FROM_HERE, base::BindOnce(&V4L2CaptureDelegate::SetRotation, - capture_impl_->GetWeakPtr(), rotation)); - } + task_runner_->PostTask(FROM_HERE, + base::BindOnce(&V4L2CaptureDelegate::SetRotation, + capture_impl_->GetWeakPtr(), rotation)); } } // namespace media
diff --git a/media/capture/video/linux/video_capture_device_linux.h b/media/capture/video/linux/video_capture_device_linux.h index 08de3f0..0d2d413b 100644 --- a/media/capture/video/linux/video_capture_device_linux.h +++ b/media/capture/video/linux/video_capture_device_linux.h
@@ -13,11 +13,7 @@ #include <stdint.h> #include <memory> -#include <vector> -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/threading/thread.h" #include "media/capture/video/linux/v4l2_capture_device_impl.h" #include "media/capture/video/video_capture_device.h" #include "media/capture/video_capture_types.h" @@ -66,10 +62,7 @@ // |v4l2_thread_|. std::unique_ptr<V4L2CaptureDelegate> capture_impl_; - // Photo-related requests waiting for |v4l2_thread_| to be active. - std::vector<base::OnceClosure> photo_requests_queue_; - - base::Thread v4l2_thread_; // Thread used for reading data from the device. + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; // SetRotation() may get called even when the device is not started. When that // is the case we remember the value here and use it as soon as the device
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc index 674e15c..fb75b04 100644 --- a/media/capture/video/video_capture_device_unittest.cc +++ b/media/capture/video/video_capture_device_unittest.cc
@@ -236,16 +236,16 @@ mojom::PhotoStatePtr state_; }; -base::test::SingleThreadTaskEnvironment::MainThreadType kMainThreadType = +constexpr auto kMainThreadType = #if BUILDFLAG(IS_MAC) // Video capture code on MacOSX must run on a CFRunLoop enabled thread // for interaction with AVFoundation. - base::test::SingleThreadTaskEnvironment::MainThreadType::UI; + base::test::TaskEnvironment::MainThreadType::UI; #elif BUILDFLAG(IS_FUCHSIA) // FIDL APIs on Fuchsia requires IO thread. - base::test::SingleThreadTaskEnvironment::MainThreadType::IO; + base::test::TaskEnvironment::MainThreadType::IO; #else - base::test::SingleThreadTaskEnvironment::MainThreadType::DEFAULT; + base::test::TaskEnvironment::MainThreadType::DEFAULT; #endif } // namespace @@ -320,6 +320,7 @@ } void TearDown() override { + task_environment_.RunUntilIdle(); #if BUILDFLAG(IS_CHROMEOS_ASH) chromeos::PowerManagerClient::Shutdown(); #endif @@ -469,7 +470,7 @@ #if BUILDFLAG(IS_WIN) base::win::ScopedCOMInitializer initialize_com_; #endif - base::test::SingleThreadTaskEnvironment task_environment_; + base::test::TaskEnvironment task_environment_; std::vector<VideoCaptureDeviceInfo> devices_info_; std::unique_ptr<base::RunLoop> run_loop_; scoped_refptr<base::TaskRunner> main_thread_task_runner_;
diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc index b67fb512..92bf8ff 100644 --- a/media/filters/decoder_stream.cc +++ b/media/filters/decoder_stream.cc
@@ -453,22 +453,35 @@ // We don't know if the decoder will error out on first decode yet. Save the // buffer to feed it to the fallback decoder later if needed. - if (!decoder_produced_a_frame_) + if (!decoder_produced_a_frame_) { pending_buffers_.push_back(buffer); + } // It's possible for a buffer to arrive from the demuxer right after the // fallback decoder successfully completed its initialization. At this point // |pending_buffers_| has already been copied to |fallback_buffers_| and we // need to append it ourselves. - if (!fallback_buffers_.empty()) { - fallback_buffers_.push_back(buffer); + if (!fallback_buffers_.empty() || fallback_buffers_being_decoded_ > 0) { + fallback_buffers_.push_back(std::exchange(buffer, nullptr)); - scoped_refptr<DecoderBuffer> temp = std::move(fallback_buffers_.front()); - fallback_buffers_.pop_front(); - DecodeInternal(std::move(temp)); - } else { - DecodeInternal(std::move(buffer)); + // There may already be a pending buffer being decoded after decoder + // change. Since decoders can have different max decode requests, we need to + // make sure we can actually decode more buffers here. + if (!CanDecodeMore()) { + return; + } } + + // TODO(https://crbug.com/1324732): We should DCHECK(CanDecodeMore()) here, + // but this breaks a number of tests. + + if (!fallback_buffers_.empty()) { + buffer = std::move(fallback_buffers_.front()); + fallback_buffers_.pop_front(); + ++fallback_buffers_being_decoded_; + } + + DecodeInternal(std::move(buffer)); } template <DemuxerStream::Type StreamType> @@ -562,6 +575,10 @@ if (buffer_size > 0) traits_->ReportStatistics(statistics_cb_, buffer_size); + if (fallback_buffers_being_decoded_ > 0) { + --fallback_buffers_being_decoded_; + } + if (state_ == STATE_NORMAL) { if (end_of_stream) { state_ = STATE_END_OF_STREAM; @@ -671,6 +688,7 @@ if (!fallback_buffers_.empty()) { scoped_refptr<DecoderBuffer> buffer = std::move(fallback_buffers_.front()); fallback_buffers_.pop_front(); + ++fallback_buffers_being_decoded_; // Decode the buffer without re-appending it to |pending_buffers_|. DecodeInternal(std::move(buffer)); @@ -714,7 +732,7 @@ switch (status) { case DemuxerStream::kOk: // Save valid buffers to be consumed by the new decoder. - // |pending_buffers_| is copied to |fallback_buffers| in + // |pending_buffers_| is copied to |fallback_buffers_| in // OnDecoderSelected(). pending_buffers_.push_back(std::move(buffer)); break; @@ -918,6 +936,7 @@ // Make sure we read directly from the demuxer after a reset. fallback_buffers_.clear(); pending_buffers_.clear(); + fallback_buffers_being_decoded_ = 0; if (state_ != STATE_FLUSHING_DECODER) { state_ = STATE_NORMAL;
diff --git a/media/filters/decoder_stream.h b/media/filters/decoder_stream.h index 8a39210..894949c 100644 --- a/media/filters/decoder_stream.h +++ b/media/filters/decoder_stream.h
@@ -301,6 +301,8 @@ bool encryption_type_reported_ = false; + int fallback_buffers_being_decoded_ = 0; + // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory<DecoderStream<StreamType>> weak_factory_{this};
diff --git a/media/filters/pipeline_controller.cc b/media/filters/pipeline_controller.cc index 7ea76b5..26074c0 100644 --- a/media/filters/pipeline_controller.cc +++ b/media/filters/pipeline_controller.cc
@@ -443,6 +443,11 @@ Dispatch(); } +void PipelineController::OnExternalVideoFrameRequest() { + DCHECK(thread_checker_.CalledOnValidThread()); + pipeline_->OnExternalVideoFrameRequest(); +} + void PipelineController::FireOnTrackChangeCompleteForTesting(State set_to) { previous_track_change_state_ = set_to; OnTrackChangeComplete();
diff --git a/media/filters/pipeline_controller.h b/media/filters/pipeline_controller.h index 425b1e1..116cae1 100644 --- a/media/filters/pipeline_controller.h +++ b/media/filters/pipeline_controller.h
@@ -148,6 +148,7 @@ const std::vector<MediaTrack::Id>& enabled_track_ids); void OnSelectedVideoTrackChanged( absl::optional<MediaTrack::Id> selected_track_id); + void OnExternalVideoFrameRequest(); // Used to fire the OnTrackChangeComplete function which is captured in a // OnceCallback, and doesn't play nicely with gmock.
diff --git a/media/formats/hls/media_playlist.cc b/media/formats/hls/media_playlist.cc index 08771b8..442df42 100644 --- a/media/formats/hls/media_playlist.cc +++ b/media/formats/hls/media_playlist.cc
@@ -60,8 +60,11 @@ absl::optional<XEndListTag> end_list_tag; absl::optional<XIFramesOnlyTag> i_frames_only_tag; absl::optional<XMediaSequenceTag> media_sequence_tag; + absl::optional<XDiscontinuitySequenceTag> discontinuity_sequence_tag; std::vector<MediaSegment> segments; + types::DecimalInteger discontinuity_sequence_number = 0; + // If this media playlist was found through a multivariant playlist, it may // import variables from that playlist. if (parent_playlist) { @@ -122,10 +125,19 @@ break; } case MediaPlaylistTagName::kXDiscontinuity: { - auto error = ParseUniqueTag(*tag, discontinuity_tag); - if (error.has_value()) { - return std::move(error).value(); + // Multiple occurrences of `EXT-X-DISCONTINUITY` per media segment are + // allowed, and each increments the segment's discontinuity sequence + // number by 1. The spec doesn't explicitly forbid this, and this + // seems to be how other HLS clients handle this scenario. + auto result = XDiscontinuityTag::Parse(*tag); + if (result.has_error()) { + return std::move(result).error(); } + + // Even if there was a previous discontinuity tag, overwrite the value + // and increment the discontinuity sequence number by 1. + discontinuity_tag = std::move(result).value(); + discontinuity_sequence_number += 1; break; } case MediaPlaylistTagName::kXGap: { @@ -168,6 +180,25 @@ } break; } + case MediaPlaylistTagName::kXDiscontinuitySequence: { + auto error = ParseUniqueTag(*tag, discontinuity_sequence_tag); + if (error.has_value()) { + return std::move(error).value(); + } + + // This tag must appear before any media segment or + // EXT-X-DISCONTINUITY tag. + if (!segments.empty()) { + return ParseStatusCode::kMediaSegmentBeforeDiscontinuitySequenceTag; + } + if (discontinuity_sequence_number != 0) { + return ParseStatusCode:: + kDiscontinuityTagBeforeDiscontinuitySequenceTag; + } + + discontinuity_sequence_number = discontinuity_sequence_tag->number; + break; + } } continue; @@ -198,8 +229,8 @@ (media_sequence_tag ? media_sequence_tag->number : 0) + segments.size(); segments.emplace_back(inf_tag->duration, media_sequence_number, - std::move(segment_uri), discontinuity_tag.has_value(), - gap_tag.has_value()); + discontinuity_sequence_number, std::move(segment_uri), + discontinuity_tag.has_value(), gap_tag.has_value()); // Reset per-segment tags inf_tag.reset();
diff --git a/media/formats/hls/media_playlist_test_builder.h b/media/formats/hls/media_playlist_test_builder.h index cc8bae56..245d228 100644 --- a/media/formats/hls/media_playlist_test_builder.h +++ b/media/formats/hls/media_playlist_test_builder.h
@@ -119,6 +119,15 @@ EXPECT_EQ(segment.GetMediaSequenceNumber(), number) << from.ToString(); } +// Checks that the latest media segment has the given discontinuity sequence +// number. +inline void HasDiscontinuitySequenceNumber(types::DecimalInteger number, + const base::Location& from, + const MediaSegment& segment) { + EXPECT_EQ(segment.GetDiscontinuitySequenceNumber(), number) + << from.ToString(); +} + // Checks that the latest media segment has the given URI. inline void HasUri(GURL uri, const base::Location& from,
diff --git a/media/formats/hls/media_playlist_unittest.cc b/media/formats/hls/media_playlist_unittest.cc index be1a525..774427b 100644 --- a/media/formats/hls/media_playlist_unittest.cc +++ b/media/formats/hls/media_playlist_unittest.cc
@@ -50,30 +50,30 @@ builder.AppendLine("video.ts"); builder.ExpectAdditionalSegment(); builder.ExpectSegment(HasDiscontinuity, false); + builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0); builder.AppendLine("#EXT-X-DISCONTINUITY"); builder.AppendLine("#EXTINF:9.9,\t"); builder.AppendLine("video.ts"); builder.ExpectAdditionalSegment(); builder.ExpectSegment(HasDiscontinuity, true); + builder.ExpectSegment(HasDiscontinuitySequenceNumber, 1); // The discontinuity tag does not apply to subsequent segments builder.AppendLine("#EXTINF:9.9,\t"); builder.AppendLine("video.ts"); builder.ExpectAdditionalSegment(); builder.ExpectSegment(HasDiscontinuity, false); + builder.ExpectSegment(HasDiscontinuitySequenceNumber, 1); - // The discontinuity tag may only appear once per segment - { - auto fork = builder; - fork.AppendLine("#EXT-X-DISCONTINUITY"); - fork.AppendLine("#EXT-X-DISCONTINUITY"); - fork.AppendLine("#EXTINF:9.9,\t"); - fork.AppendLine("video.ts"); - fork.ExpectAdditionalSegment(); - fork.ExpectSegment(HasDiscontinuity, true); - fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags); - } + // The discontinuity tag may appear multiple times per segment + builder.AppendLine("#EXT-X-DISCONTINUITY"); + builder.AppendLine("#EXT-X-DISCONTINUITY"); + builder.AppendLine("#EXTINF:9.9,\t"); + builder.AppendLine("video.ts"); + builder.ExpectAdditionalSegment(); + builder.ExpectSegment(HasDiscontinuity, true); + builder.ExpectSegment(HasDiscontinuitySequenceNumber, 3); builder.ExpectOk(); } @@ -573,16 +573,19 @@ builder.ExpectAdditionalSegment(); builder.ExpectSegment(HasUri, GURL("http://localhost/segment0.ts")); builder.ExpectSegment(HasMediaSequenceNumber, first_sequence_number); + builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0); builder.AppendLine("#EXTINF:9.8,\t"); builder.AppendLine("segment1.ts"); builder.ExpectAdditionalSegment(); builder.ExpectSegment(HasMediaSequenceNumber, first_sequence_number + 1); + builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0); builder.AppendLine("#EXTINF:9.8,\t"); builder.AppendLine("segment2.ts"); builder.ExpectAdditionalSegment(); builder.ExpectSegment(HasMediaSequenceNumber, first_sequence_number + 2); + builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0); }; // If the playlist does not contain the EXT-X-MEDIA-SEQUENCE tag, the default @@ -613,4 +616,135 @@ fork.ExpectOk(); } +TEST(HlsMediaPlaylistTest, XDiscontinuitySequenceTag) { + MediaPlaylistTestBuilder builder; + builder.AppendLine("#EXTM3U"); + builder.AppendLine("#EXT-X-TARGETDURATION:10"); + + // The EXT-X-DISCONTINUITY-SEQUENCE tag must be a valid DecimalInteger + { + for (const base::StringPiece x : {"", ":-1", ":{$foo}", ":1.5", ":one"}) { + auto fork = builder; + fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE", x); + fork.ExpectError(ParseStatusCode::kMalformedTag); + } + } + // The EXT-X-DISCONTINUITY-SEQUENCE tag may not appear twice + { + auto fork = builder; + fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:1"); + fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:1"); + fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags); + } + { + auto fork = builder; + fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:0"); + fork.AppendLine("#EXT-X-DISCONTINUITY"); + fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:1"); + fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags); + } + // The EXT-X-DISCONTINUITY-SEQUENCE tag must appear before any media segment + { + auto fork = builder; + fork.AppendLine("#EXTINF:9.8,\t"); + fork.AppendLine("segment0.ts"); + fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:0"); + fork.ExpectError( + ParseStatusCode::kMediaSegmentBeforeDiscontinuitySequenceTag); + } + // The EXT-X-DISCONTINUITY-SEQUENCE tag must appear before any + // EXT-X-DISCONTINUITY tag + { + auto fork = builder; + fork.AppendLine("#EXT-X-DISCONTINUITY"); + fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:0"); + fork.AppendLine("#EXTINF:9.8,\t"); + fork.AppendLine("segment0.ts"); + fork.ExpectError( + ParseStatusCode::kDiscontinuityTagBeforeDiscontinuitySequenceTag); + } + + const auto fill_playlist = [](auto& builder, auto first_media_sequence_number, + auto first_discontinuity_sequence_number) { + builder.AppendLine("#EXTINF:9.8,\t"); + builder.AppendLine("segment0.ts"); + builder.ExpectAdditionalSegment(); + builder.ExpectSegment(HasUri, GURL("http://localhost/segment0.ts")); + builder.ExpectSegment(HasDiscontinuity, false); + builder.ExpectSegment(HasMediaSequenceNumber, first_media_sequence_number); + builder.ExpectSegment(HasDiscontinuitySequenceNumber, + first_discontinuity_sequence_number); + + builder.AppendLine("#EXT-X-DISCONTINUITY"); + builder.AppendLine("#EXTINF:9.8,\t"); + builder.AppendLine("segment1.ts"); + builder.ExpectAdditionalSegment(); + builder.ExpectSegment(HasDiscontinuity, true); + builder.ExpectSegment(HasMediaSequenceNumber, + first_media_sequence_number + 1); + builder.ExpectSegment(HasDiscontinuitySequenceNumber, + first_discontinuity_sequence_number + 1); + + builder.AppendLine("#EXTINF:9.8,\t"); + builder.AppendLine("segment2.ts"); + builder.ExpectAdditionalSegment(); + builder.ExpectSegment(HasDiscontinuity, false); + builder.ExpectSegment(HasMediaSequenceNumber, + first_media_sequence_number + 2); + builder.ExpectSegment(HasDiscontinuitySequenceNumber, + first_discontinuity_sequence_number + 1); + }; + + // If the playlist does not contain the EXT-X-DISCONTINUITY-SEQUENCE tag, the + // default starting value is 0. + auto fork = builder; + fill_playlist(fork, 0, 0); + fork.ExpectOk(); + + fork = builder; + fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10"); + fill_playlist(fork, 10, 0); + fork.ExpectOk(); + + // If the playlist has the EXT-X-DISCONTINUITY-SEQUENCE tag, it specifies the + // starting value. + fork = builder; + fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:5"); + fill_playlist(fork, 0, 5); + fork.ExpectOk(); + + fork = builder; + fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10"); + fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:5"); + fill_playlist(fork, 10, 5); + fork.ExpectOk(); + + // If the very first segment is a discontinuity, it should still have a + // subsequent discontinuity sequence number. + fork = builder; + fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10"); + fork.AppendLine("#EXT-X-DISCONTINUITY"); + fork.AppendLine("#EXTINF:9.2,\t"); + fork.AppendLine("segment.ts"); + fork.ExpectAdditionalSegment(); + fork.ExpectSegment(HasDiscontinuity, true); + fork.ExpectSegment(HasMediaSequenceNumber, 10); + fork.ExpectSegment(HasDiscontinuitySequenceNumber, 1); + fill_playlist(fork, 11, 1); + fork.ExpectOk(); + + fork = builder; + fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10"); + fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:5"); + fork.AppendLine("#EXT-X-DISCONTINUITY"); + fork.AppendLine("#EXTINF:9.2,\t"); + fork.AppendLine("segment.ts"); + fork.ExpectAdditionalSegment(); + fork.ExpectSegment(HasDiscontinuity, true); + fork.ExpectSegment(HasMediaSequenceNumber, 10); + fork.ExpectSegment(HasDiscontinuitySequenceNumber, 6); + fill_playlist(fork, 11, 6); + fork.ExpectOk(); +} + } // namespace media::hls
diff --git a/media/formats/hls/media_segment.cc b/media/formats/hls/media_segment.cc index 50e0f04..9aa8416 100644 --- a/media/formats/hls/media_segment.cc +++ b/media/formats/hls/media_segment.cc
@@ -11,11 +11,13 @@ MediaSegment::MediaSegment(types::DecimalFloatingPoint duration, types::DecimalInteger media_sequence_number, + types::DecimalInteger discontinuity_sequence_number, GURL uri, bool has_discontinuity, bool is_gap) : duration_(duration), media_sequence_number_(media_sequence_number), + discontinuity_sequence_number_(discontinuity_sequence_number), uri_(std::move(uri)), has_discontinuity_(has_discontinuity), is_gap_(is_gap) {}
diff --git a/media/formats/hls/media_segment.h b/media/formats/hls/media_segment.h index d3031eb5..b97815fe 100644 --- a/media/formats/hls/media_segment.h +++ b/media/formats/hls/media_segment.h
@@ -15,6 +15,7 @@ public: MediaSegment(types::DecimalFloatingPoint duration, types::DecimalInteger media_sequence_number, + types::DecimalInteger discontinuity_sequence_number, GURL uri, bool has_discontinuity, bool is_gap); @@ -32,6 +33,11 @@ return media_sequence_number_; } + // Returns the discontinuity sequence number of this media segment. + types::DecimalInteger GetDiscontinuitySequenceNumber() const { + return discontinuity_sequence_number_; + } + // The URI of the media resource. This will have already been resolved against // the playlist URI. This is guaranteed to be valid and non-empty, unless // `gap` is true, in which case this URI should not be used. @@ -48,6 +54,7 @@ private: types::DecimalFloatingPoint duration_; types::DecimalInteger media_sequence_number_; + types::DecimalInteger discontinuity_sequence_number_; GURL uri_; bool has_discontinuity_; bool is_gap_;
diff --git a/media/formats/hls/parse_status.cc b/media/formats/hls/parse_status.cc index 0f10a2e..01f21b3 100644 --- a/media/formats/hls/parse_status.cc +++ b/media/formats/hls/parse_status.cc
@@ -44,6 +44,8 @@ PARSE_STATUS_CODE_CASE(kXStreamInfTagNotFollowedByUri); PARSE_STATUS_CODE_CASE(kVariantMissingStreamInfTag); PARSE_STATUS_CODE_CASE(kMediaSegmentBeforeMediaSequenceTag); + PARSE_STATUS_CODE_CASE(kMediaSegmentBeforeDiscontinuitySequenceTag); + PARSE_STATUS_CODE_CASE(kDiscontinuityTagBeforeDiscontinuitySequenceTag); } NOTREACHED();
diff --git a/media/formats/hls/parse_status.h b/media/formats/hls/parse_status.h index ad974c93..77c8f8d 100644 --- a/media/formats/hls/parse_status.h +++ b/media/formats/hls/parse_status.h
@@ -41,6 +41,8 @@ kXStreamInfTagNotFollowedByUri, kVariantMissingStreamInfTag, kMediaSegmentBeforeMediaSequenceTag, + kMediaSegmentBeforeDiscontinuitySequenceTag, + kDiscontinuityTagBeforeDiscontinuitySequenceTag, }; struct ParseStatusTraits {
diff --git a/media/formats/hls/tag_name.cc b/media/formats/hls/tag_name.cc index 8c819f00..fb4283c 100644 --- a/media/formats/hls/tag_name.cc +++ b/media/formats/hls/tag_name.cc
@@ -54,6 +54,8 @@ MultivariantPlaylistTagName::kXContentSteering), TagNameEntry("EXT-X-DEFINE", CommonTagName::kXDefine), TagNameEntry("EXT-X-DISCONTINUITY", MediaPlaylistTagName::kXDiscontinuity), + TagNameEntry("EXT-X-DISCONTINUITY-SEQUENCE", + MediaPlaylistTagName::kXDiscontinuitySequence), TagNameEntry("EXT-X-ENDLIST", MediaPlaylistTagName::kXEndList), TagNameEntry("EXT-X-GAP", MediaPlaylistTagName::kXGap), TagNameEntry("EXT-X-I-FRAME-STREAM-INF",
diff --git a/media/formats/hls/tag_name.h b/media/formats/hls/tag_name.h index 65db1d1..a89fee3d 100644 --- a/media/formats/hls/tag_name.h +++ b/media/formats/hls/tag_name.h
@@ -58,7 +58,8 @@ kXGap, kXPlaylistType, kXMediaSequence, - kMaxValue = kXMediaSequence, + kXDiscontinuitySequence, + kMaxValue = kXDiscontinuitySequence, }; constexpr TagKind GetTagKind(CommonTagName) {
diff --git a/media/formats/hls/tags.cc b/media/formats/hls/tags.cc index a040c1af..67b05c7a 100644 --- a/media/formats/hls/tags.cc +++ b/media/formats/hls/tags.cc
@@ -449,4 +449,9 @@ return ParseDecimalIntegerTag(tag, &XMediaSequenceTag::number); } +ParseStatus::Or<XDiscontinuitySequenceTag> XDiscontinuitySequenceTag::Parse( + TagItem tag) { + return ParseDecimalIntegerTag(tag, &XDiscontinuitySequenceTag::number); +} + } // namespace media::hls
diff --git a/media/formats/hls/tags.h b/media/formats/hls/tags.h index ebed023..44ec810 100644 --- a/media/formats/hls/tags.h +++ b/media/formats/hls/tags.h
@@ -178,6 +178,17 @@ types::DecimalInteger number; }; +// Represents the contents of the #EXT-X-DISCONTINUITY-SEQUENCE tag. +struct MEDIA_EXPORT XDiscontinuitySequenceTag { + static constexpr auto kName = MediaPlaylistTagName::kXDiscontinuitySequence; + static ParseStatus::Or<XDiscontinuitySequenceTag> Parse(TagItem); + + // Indicates the discontinuity sequence number to assign to the first media + // segment in this playlist. These numbers are useful for synchronizing + // between variant stream timelines. + types::DecimalInteger number; +}; + } // namespace media::hls #endif // MEDIA_FORMATS_HLS_TAGS_H_
diff --git a/media/formats/hls/tags_unittest.cc b/media/formats/hls/tags_unittest.cc index 28e030c..3eebae59 100644 --- a/media/formats/hls/tags_unittest.cc +++ b/media/formats/hls/tags_unittest.cc
@@ -4,7 +4,6 @@ #include "media/formats/hls/tags.h" -#include <functional> #include <utility> #include "base/location.h" @@ -114,8 +113,8 @@ // There are a couple of tags that are defined simply as `#EXT-X-TAG:n` where // `n` must be a valid DecimalInteger. This helper provides coverage for those // tags. -template <typename T, typename Fn> -void RunDecimalIntegerTagTest(Fn getter_fn) { +template <typename T> +void RunDecimalIntegerTagTest(types::DecimalInteger T::*field) { // Content is required ErrorTest<T>(absl::nullopt, ParseStatusCode::kMalformedTag); ErrorTest<T>("", ParseStatusCode::kMalformedTag); @@ -133,15 +132,15 @@ ErrorTest<T>("{$X}", ParseStatusCode::kMalformedTag); auto tag = OkTest<T>("0"); - EXPECT_EQ(getter_fn(tag), 0u); + EXPECT_EQ(tag.*field, 0u); tag = OkTest<T>("1"); - EXPECT_EQ(getter_fn(tag), 1u); + EXPECT_EQ(tag.*field, 1u); tag = OkTest<T>("10"); - EXPECT_EQ(getter_fn(tag), 10u); + EXPECT_EQ(tag.*field, 10u); tag = OkTest<T>("14"); - EXPECT_EQ(getter_fn(tag), 14u); + EXPECT_EQ(tag.*field, 14u); tag = OkTest<T>("999999999999999999"); - EXPECT_EQ(getter_fn(tag), 999999999999999999u); + EXPECT_EQ(tag.*field, 999999999999999999u); } VariableDictionary CreateBasicDictionary( @@ -462,14 +461,18 @@ TEST(HlsTagsTest, ParseXTargetDurationTag) { RunTagIdenficationTest<XTargetDurationTag>("#EXT-X-TARGETDURATION:10\n", "10"); - RunDecimalIntegerTagTest<XTargetDurationTag>( - std::mem_fn(&XTargetDurationTag::duration)); + RunDecimalIntegerTagTest(&XTargetDurationTag::duration); } TEST(HlsTagsTest, ParseXMediaSequenceTag) { RunTagIdenficationTest<XMediaSequenceTag>("#EXT-X-MEDIA-SEQUENCE:3\n", "3"); - RunDecimalIntegerTagTest<XMediaSequenceTag>( - std::mem_fn(&XMediaSequenceTag::number)); + RunDecimalIntegerTagTest(&XMediaSequenceTag::number); +} + +TEST(HlsTagsTest, ParseXDiscontinuitySequenceTag) { + RunTagIdenficationTest<XDiscontinuitySequenceTag>( + "#EXT-X-DISCONTINUITY-SEQUENCE:3\n", "3"); + RunDecimalIntegerTagTest(&XDiscontinuitySequenceTag::number); } } // namespace media::hls
diff --git a/media/learning/common/target_histogram.h b/media/learning/common/target_histogram.h index 6b99ad4..b173f44b 100644 --- a/media/learning/common/target_histogram.h +++ b/media/learning/common/target_histogram.h
@@ -27,6 +27,11 @@ struct COMPONENT_EXPORT(LEARNING_COMMON) TargetHistogramPair { TargetValue target_value; double count; + + TargetHistogramPair() = default; + + TargetHistogramPair(const TargetValue& value, double count) + : target_value(value), count(count) {} }; // Histogram of target values that allows fractional counts.
diff --git a/media/learning/mojo/public/cpp/learning_mojom_traits.h b/media/learning/mojo/public/cpp/learning_mojom_traits.h index 9203334..262a6f1 100644 --- a/media/learning/mojo/public/cpp/learning_mojom_traits.h +++ b/media/learning/mojo/public/cpp/learning_mojom_traits.h
@@ -93,8 +93,8 @@ static std::vector<media::learning::TargetHistogramPair> pairs( const media::learning::TargetHistogram& e) { std::vector<media::learning::TargetHistogramPair> pairs; - for (auto const& entry : e.counts_) { - pairs.push_back({entry.first, entry.second}); + for (auto const& [target_val, count] : e.counts_) { + pairs.emplace_back(target_val, count); } return pairs;
diff --git a/media/mojo/clients/win/media_foundation_renderer_client.cc b/media/mojo/clients/win/media_foundation_renderer_client.cc index 22547623..74e33e7 100644 --- a/media/mojo/clients/win/media_foundation_renderer_client.cc +++ b/media/mojo/clients/win/media_foundation_renderer_client.cc
@@ -9,7 +9,6 @@ #include "base/callback_helpers.h" #include "base/task/bind_post_task.h" #include "media/base/media_log.h" -#include "media/base/media_switches.h" #include "media/base/win/mf_feature_checks.h" #include "media/base/win/mf_helpers.h" #include "media/mojo/mojom/speech_recognition_service.mojom.h" @@ -87,9 +86,9 @@ // protected content then start in Direct Composition mode, else start in // Frame Server mode. This behavior must match the logic in // MediaFoundationRenderer::Initialize. - auto rendering_strategy = kMediaFoundationClearRenderingStrategyParam.Get(); + rendering_strategy_ = kMediaFoundationClearRenderingStrategyParam.Get(); rendering_mode_ = - rendering_strategy == + rendering_strategy_ == MediaFoundationClearRenderingStrategy::kDirectComposition ? MediaFoundationRenderingMode::DirectComposition : MediaFoundationRenderingMode::FrameServer; @@ -257,6 +256,16 @@ std::move(change_completed_cb).Run(); } +void MediaFoundationRendererClient::OnExternalVideoFrameRequest() { + // A frame read back signal is currently treated as a permanent signal for + // the session so we only need to handle it the first time it is encountered. + if (!has_frame_read_back_signal_) { + has_frame_read_back_signal_ = true; + MEDIA_LOG(INFO, media_log_) << "Frame read back signal"; + UpdateRenderMode(); + } +} + // RendererClient implementation. void MediaFoundationRendererClient::OnError(PipelineStatus status) { @@ -569,10 +578,28 @@ const gpu::Mailbox& mailbox, bool promoted) { DCHECK(media_task_runner_->BelongsToCurrentThread()); - MEDIA_LOG(INFO, media_log_) << "Overlay State promoted = " << promoted; + promoted_to_overlay_signal_ = promoted; + MEDIA_LOG(INFO, media_log_) + << "Overlay state signal, promoted = " << promoted; + UpdateRenderMode(); +} - if (promoted && - rendering_mode_ != MediaFoundationRenderingMode::DirectComposition) { +void MediaFoundationRendererClient::UpdateRenderMode() { + // We only change modes if we're using the dynamic rendering strategy and + // presenting clear content, so return early otherwise. + if (rendering_strategy_ != MediaFoundationClearRenderingStrategy::kDynamic || + cdm_context_) { + return; + } + + // Frame Server mode is required if we are not promoted to an overlay or if + // frame readback is required. + bool needs_frame_server = + has_frame_read_back_signal_ || !promoted_to_overlay_signal_; + + if (!needs_frame_server && IsFrameServerMode()) { + MEDIA_LOG(INFO, media_log_) << "Switching to Direct Composition."; + // Switch to Frame Server Mode // Switch to Direct Composition mode. rendering_mode_ = MediaFoundationRenderingMode::DirectComposition; renderer_extension_->SetMediaFoundationRenderingMode(rendering_mode_); @@ -586,17 +613,14 @@ } else { sink_->PaintSingleFrame(dcomp_video_frame_, true); } - } else if (!promoted && - rendering_mode_ != MediaFoundationRenderingMode::FrameServer) { + } else if (needs_frame_server && !IsFrameServerMode()) { // Switch to Frame Server mode. + MEDIA_LOG(INFO, media_log_) << "Switching to Frame Server."; rendering_mode_ = MediaFoundationRenderingMode::FrameServer; renderer_extension_->SetMediaFoundationRenderingMode(rendering_mode_); if (is_playing_) { sink_->Start(this); } - } else { - MEDIA_LOG(INFO, media_log_) - << "Overlay State Changed but there was no mode change."; } } @@ -606,8 +630,7 @@ // respond to promotion changes. If the rendering strategy is Direct // Composition or Frame Server then we do not need to listen & respond to // overlay state changes. - auto rendering_strategy = kMediaFoundationClearRenderingStrategyParam.Get(); - if (rendering_strategy == MediaFoundationClearRenderingStrategy::kDynamic) { + if (rendering_strategy_ == MediaFoundationClearRenderingStrategy::kDynamic) { mailbox_ = mailbox; // 'observe_overlay_state_cb_' creates a content::OverlayStateObserver to // subscribe to overlay state information for the given 'mailbox' from the
diff --git a/media/mojo/clients/win/media_foundation_renderer_client.h b/media/mojo/clients/win/media_foundation_renderer_client.h index bb68f92..8bbe617e 100644 --- a/media/mojo/clients/win/media_foundation_renderer_client.h +++ b/media/mojo/clients/win/media_foundation_renderer_client.h
@@ -12,6 +12,7 @@ #include "base/time/time.h" #include "gpu/ipc/common/gpu_channel.mojom.h" #include "media/base/media_resource.h" +#include "media/base/media_switches.h" #include "media/base/renderer.h" #include "media/base/renderer_client.h" #include "media/base/video_renderer_sink.h" @@ -88,6 +89,7 @@ void OnSelectedVideoTracksChanged( const std::vector<DemuxerStream*>& enabled_tracks, base::OnceClosure change_completed_cb) override; + void OnExternalVideoFrameRequest() override; // RendererClient implementation. void OnError(PipelineStatus status) override; @@ -135,6 +137,7 @@ void SignalMediaPlayingStateChange(bool is_playing); void ObserveMailboxForOverlayState(const gpu::Mailbox& mailbox); void OnOverlayStateChanged(const gpu::Mailbox& mailbox, bool promoted); + void UpdateRenderMode(); // This class is constructed on the main thread and used exclusively on the // media thread. Hence we store PendingRemotes so we can bind the Remotes @@ -163,6 +166,8 @@ bool output_size_updated_ = false; bool is_playing_ = false; bool has_video_ = false; + bool has_frame_read_back_signal_ = false; + bool promoted_to_overlay_signal_ = false; scoped_refptr<VideoFrame> dcomp_video_frame_; scoped_refptr<VideoFrame> next_video_frame_; gpu::Mailbox mailbox_; @@ -171,6 +176,12 @@ MediaFoundationRenderingMode rendering_mode_ = MediaFoundationRenderingMode::DirectComposition; + // Rendering strategy informs whether we enforce a rendering mode or allow + // dynamic transitions for Clear content. (Note: Protected content will always + // use Direct Composition mode). + MediaFoundationClearRenderingStrategy rendering_strategy_ = + MediaFoundationClearRenderingStrategy::kDirectComposition; + PipelineStatusCallback init_cb_; raw_ptr<CdmContext> cdm_context_ = nullptr; CdmAttachedCB cdm_attached_cb_;
diff --git a/media/mojo/clients/win/media_foundation_renderer_client_factory.cc b/media/mojo/clients/win/media_foundation_renderer_client_factory.cc index 5c15a834..0f3e560 100644 --- a/media/mojo/clients/win/media_foundation_renderer_client_factory.cc +++ b/media/mojo/clients/win/media_foundation_renderer_client_factory.cc
@@ -100,7 +100,7 @@ media_task_runner, media_log_->Clone(), std::move(mojo_renderer), std::move(renderer_extension_remote), std::move(client_extension_receiver), std::move(dcomp_texture_wrapper), - std::move(observe_overlay_state_cb_), video_renderer_sink, + observe_overlay_state_cb_, video_renderer_sink, std::move(media_foundation_renderer_observer_remote)); }
diff --git a/media/mojo/services/webrtc_video_perf_history.cc b/media/mojo/services/webrtc_video_perf_history.cc index f8c6cc1..ab5f84db2 100644 --- a/media/mojo/services/webrtc_video_perf_history.cc +++ b/media/mojo/services/webrtc_video_perf_history.cc
@@ -313,16 +313,16 @@ // inserted as a placeholder. std::vector<absl::optional<bool>> smooth_per_pixel; absl::optional<size_t> specific_key_index; - for (auto const& stats : *stats_collection) { - if (stats.first >= video_key.pixels && !specific_key_index) { + for (auto const& [key_index, video_stats_entry] : *stats_collection) { + if (key_index >= video_key.pixels && !specific_key_index) { specific_key_index = smooth_per_pixel.size(); - if (stats.first > video_key.pixels) { + if (key_index > video_key.pixels) { // No exact match found, insert a nullopt. smooth_per_pixel.push_back(absl::nullopt); } } smooth_per_pixel.push_back(PredictSmooth( - video_key.is_decode_stats, stats.second, frames_per_second)); + video_key.is_decode_stats, video_stats_entry, frames_per_second)); } if (!specific_key_index) { // Pixels for the specific key is higher than any pixels number that
diff --git a/media/mojo/services/webrtc_video_perf_history_unittest.cc b/media/mojo/services/webrtc_video_perf_history_unittest.cc index 89833cb..5fc59d6 100644 --- a/media/mojo/services/webrtc_video_perf_history_unittest.cc +++ b/media/mojo/services/webrtc_video_perf_history_unittest.cc
@@ -118,12 +118,11 @@ WebrtcVideoStatsDB::VideoStatsCollection collection; std::string key_filter = key.SerializeWithoutPixels(); - for (auto const& entry : entries_) { - if (entry.first.rfind(key_filter, 0) == 0) { - absl::optional<int> pixels = - VideoDescKey::ParsePixelsFromKey(entry.first); + for (auto const& [str, video_stats_entry] : entries_) { + if (str.rfind(key_filter, 0) == 0) { + absl::optional<int> pixels = VideoDescKey::ParsePixelsFromKey(str); if (pixels) { - collection.insert({*pixels, std::move(entry.second)}); + collection.insert({*pixels, std::move(video_stats_entry)}); } } }
diff --git a/media/renderers/video_frame_rgba_to_yuva_converter.cc b/media/renderers/video_frame_rgba_to_yuva_converter.cc index 9eecb98..80fa9431 100644 --- a/media/renderers/video_frame_rgba_to_yuva_converter.cc +++ b/media/renderers/video_frame_rgba_to_yuva_converter.cc
@@ -118,8 +118,7 @@ const gfx::ColorSpace& src_color_space, GrSurfaceOrigin src_surface_origin, const gpu::MailboxHolder& src_mailbox_holder, - VideoFrame* dst_video_frame, - gpu::SyncToken& completion_sync_token) { + VideoFrame* dst_video_frame) { DCHECK_EQ(dst_video_frame->format(), PIXEL_FORMAT_NV12); auto* ri = provider->RasterInterface(); @@ -218,12 +217,11 @@ ri->WaitSyncTokenCHROMIUM(copy_to_gmb_done_sync_token.GetData()); #endif // BUILDFLAG(IS_WIN) - // Set `completion_sync_token` to mark the completion of the copy. - ri->GenSyncTokenCHROMIUM(completion_sync_token.GetData()); - // Make access to the `dst_video_frame` wait on copy completion. We also // update the ReleaseSyncToken here since it's used when the underlying // GpuMemoryBuffer and SharedImage resources are returned to the pool. + gpu::SyncToken completion_sync_token; + ri->GenSyncTokenCHROMIUM(completion_sync_token.GetData()); SimpleSyncTokenClient simple_client(completion_sync_token); for (size_t plane = 0; plane < num_planes; ++plane) dst_video_frame->UpdateMailboxHolderSyncToken(plane, &simple_client);
diff --git a/media/renderers/video_frame_rgba_to_yuva_converter.h b/media/renderers/video_frame_rgba_to_yuva_converter.h index 5ae5a30..3e04b99 100644 --- a/media/renderers/video_frame_rgba_to_yuva_converter.h +++ b/media/renderers/video_frame_rgba_to_yuva_converter.h
@@ -16,7 +16,6 @@ namespace gpu { struct MailboxHolder; -struct SyncToken; } // namespace gpu namespace viz { @@ -39,8 +38,7 @@ const gfx::ColorSpace& src_color_space, GrSurfaceOrigin src_surface_origin, const gpu::MailboxHolder& src_mailbox_holder, - media::VideoFrame* dst_video_frame, - gpu::SyncToken& completion_sync_token); + media::VideoFrame* dst_video_frame); } // namespace media
diff --git a/net/network_error_logging/network_error_logging_service.cc b/net/network_error_logging/network_error_logging_service.cc index e6e06a40..524eddd 100644 --- a/net/network_error_logging/network_error_logging_service.cc +++ b/net/network_error_logging/network_error_logging_service.cc
@@ -690,7 +690,9 @@ auto iter_and_result = policies_.insert(std::make_pair(policy.key, std::move(policy))); - DCHECK(iter_and_result.second); + // TODO(crbug.com/1326282): Change this to a DCHECK when we're sure the bug + // is fixed. + CHECK(iter_and_result.second); const NelPolicy& inserted_policy = iter_and_result.first->second; MaybeAddWildcardPolicy(inserted_policy.key, &inserted_policy); @@ -873,7 +875,9 @@ // TODO(chlily): Toss any expired policies we encounter. for (NelPolicy& policy : loaded_policies) { - AddPolicy(std::move(policy)); + if (policies_.find(policy.key) == policies_.end()) { + AddPolicy(std::move(policy)); + } } initialized_ = true; ExecuteBacklog();
diff --git a/net/network_error_logging/network_error_logging_service_unittest.cc b/net/network_error_logging/network_error_logging_service_unittest.cc index cb634132..c9c0686d 100644 --- a/net/network_error_logging/network_error_logging_service_unittest.cc +++ b/net/network_error_logging/network_error_logging_service_unittest.cc
@@ -1513,6 +1513,25 @@ EXPECT_TRUE(store()->VerifyCommands(expected_commands)); } +TEST_P(NetworkErrorLoggingServiceTest, DuplicateEntriesInStore) { + if (!store()) + return; + + NetworkErrorLoggingService::NelPolicy policy1 = MakePolicy(kNik_, kOrigin_); + NetworkErrorLoggingService::NelPolicy policy2 = policy1; + std::vector<NetworkErrorLoggingService::NelPolicy> prestored_policies = { + policy1, policy2}; + store()->SetPrestoredPolicies(std::move(prestored_policies)); + + // The first call to any of the public methods triggers a load. + service()->OnHeader(kNik_, kOrigin_, kServerIP_, kHeader_); + EXPECT_TRUE(store()->VerifyCommands( + {MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES})); + FinishLoading(/*load_success=*/true); + + EXPECT_EQ(service()->GetPolicyKeysForTesting().size(), 1u); +} + // Same as the above test, except that all the tasks are queued until loading // is complete. TEST_P(NetworkErrorLoggingServiceTest, SendsCommandsToStoreDeferred) {
diff --git a/remoting/host/base/screen_controls.h b/remoting/host/base/screen_controls.h index f6cd62a..5c67390f 100644 --- a/remoting/host/base/screen_controls.h +++ b/remoting/host/base/screen_controls.h
@@ -5,6 +5,9 @@ #ifndef REMOTING_HOST_BASE_SCREEN_CONTROLS_H_ #define REMOTING_HOST_BASE_SCREEN_CONTROLS_H_ +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h" + namespace remoting { class ScreenResolution; @@ -14,10 +17,20 @@ public: virtual ~ScreenControls() = default; - // If |resolution| is not empty, attempts to set new screen resolution in the - // session. If |resolution| is empty, attempts to restore the original screen - // resolution. - virtual void SetScreenResolution(const ScreenResolution& resolution) = 0; + // If |resolution| is not empty, attempts to set new screen resolution for + // the monitor |screen_id|. If |resolution| is empty, attempts to restore the + // original resolution of |screen_id|. Resizing a monitor may cause other + // monitors to be repositioned to accommodate the new size. + // + // If |screen_id| is not provided: + // If there is only 1 monitor, the monitor should be resized to |resolution| + // or restored if |resolution| is empty. If there is more than 1 monitor, the + // implementation should fall back to the behavior of older hosts (for + // example, the request may be ignored, or only the primary display may be + // resized). + virtual void SetScreenResolution( + const ScreenResolution& resolution, + absl::optional<webrtc::ScreenId> screen_id) = 0; }; } // namespace remoting
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc index 83554f4a..b1d9d8a 100644 --- a/remoting/host/client_session.cc +++ b/remoting/host/client_session.cc
@@ -153,8 +153,12 @@ // Try to match the client's resolution. // TODO(sergeyu): Pass clients DPI to the resizer. - screen_controls_->SetScreenResolution(ScreenResolution( - client_size, webrtc::DesktopVector(kDefaultDpi, kDefaultDpi))); + ScreenResolution screen_resolution( + client_size, webrtc::DesktopVector(kDefaultDpi, kDefaultDpi)); + absl::optional<webrtc::ScreenId> screen_id; + if (resolution.has_screen_id()) + screen_id = resolution.screen_id(); + screen_controls_->SetScreenResolution(screen_resolution, screen_id); } void ClientSession::ControlVideo(const protocol::VideoControl& video_control) {
diff --git a/remoting/host/desktop_session_agent.cc b/remoting/host/desktop_session_agent.cc index 9c7a70fd..6a97d6ef 100644 --- a/remoting/host/desktop_session_agent.cc +++ b/remoting/host/desktop_session_agent.cc
@@ -770,7 +770,7 @@ CHECK(started_); if (screen_controls_) - screen_controls_->SetScreenResolution(resolution); + screen_controls_->SetScreenResolution(resolution, absl::nullopt); } void DesktopSessionAgent::SendToNetwork(std::unique_ptr<IPC::Message> message) {
diff --git a/remoting/host/fake_desktop_environment.cc b/remoting/host/fake_desktop_environment.cc index 4c668553..d2c0a98 100644 --- a/remoting/host/fake_desktop_environment.cc +++ b/remoting/host/fake_desktop_environment.cc
@@ -58,8 +58,8 @@ FakeScreenControls::~FakeScreenControls() = default; void FakeScreenControls::SetScreenResolution( - const ScreenResolution& resolution) { -} + const ScreenResolution& resolution, + absl::optional<webrtc::ScreenId> screen_id) {} FakeDesktopEnvironment::FakeDesktopEnvironment( scoped_refptr<base::SingleThreadTaskRunner> capture_thread,
diff --git a/remoting/host/fake_desktop_environment.h b/remoting/host/fake_desktop_environment.h index 5f67fa7..0dda378 100644 --- a/remoting/host/fake_desktop_environment.h +++ b/remoting/host/fake_desktop_environment.h
@@ -74,7 +74,8 @@ ~FakeScreenControls() override; // ScreenControls implementation. - void SetScreenResolution(const ScreenResolution& resolution) override; + void SetScreenResolution(const ScreenResolution& resolution, + absl::optional<webrtc::ScreenId> screen_id) override; }; class FakeDesktopEnvironment : public DesktopEnvironment {
diff --git a/remoting/host/ipc_desktop_environment_unittest.cc b/remoting/host/ipc_desktop_environment_unittest.cc index b4c4c52..511c28e 100644 --- a/remoting/host/ipc_desktop_environment_unittest.cc +++ b/remoting/host/ipc_desktop_environment_unittest.cc
@@ -805,9 +805,10 @@ this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment)); // Change the desktop resolution. - screen_controls_->SetScreenResolution(ScreenResolution( - webrtc::DesktopSize(100, 100), - webrtc::DesktopVector(96, 96))); + screen_controls_->SetScreenResolution( + ScreenResolution(webrtc::DesktopSize(100, 100), + webrtc::DesktopVector(96, 96)), + absl::nullopt); } TEST_F(IpcDesktopEnvironmentTest, CheckUrlForwarderState) {
diff --git a/remoting/host/ipc_screen_controls.cc b/remoting/host/ipc_screen_controls.cc index 0b27eec..93e6127 100644 --- a/remoting/host/ipc_screen_controls.cc +++ b/remoting/host/ipc_screen_controls.cc
@@ -16,7 +16,9 @@ IpcScreenControls::~IpcScreenControls() = default; void IpcScreenControls::SetScreenResolution( - const ScreenResolution& resolution) { + const ScreenResolution& resolution, + absl::optional<webrtc::ScreenId> screen_id) { + // TODO(crbug.com/1326339): Pass |screen_id| over IPC. desktop_session_proxy_->SetScreenResolution(resolution); }
diff --git a/remoting/host/ipc_screen_controls.h b/remoting/host/ipc_screen_controls.h index 0e32807..473bf01 100644 --- a/remoting/host/ipc_screen_controls.h +++ b/remoting/host/ipc_screen_controls.h
@@ -23,8 +23,9 @@ ~IpcScreenControls() override; - // SessionController interface. - void SetScreenResolution(const ScreenResolution& resolution) override; + // ScreenControls interface. + void SetScreenResolution(const ScreenResolution& resolution, + absl::optional<webrtc::ScreenId> screen_id) override; private: // Wraps the IPC channel to the desktop session agent.
diff --git a/remoting/host/resizing_host_observer.cc b/remoting/host/resizing_host_observer.cc index 60d87df1..131db069 100644 --- a/remoting/host/resizing_host_observer.cc +++ b/remoting/host/resizing_host_observer.cc
@@ -133,7 +133,8 @@ } void ResizingHostObserver::SetScreenResolution( - const ScreenResolution& resolution) { + const ScreenResolution& resolution, + absl::optional<webrtc::ScreenId> screen_id) { // Get the current time. This function is called exactly once for each call // to SetScreenResolution to simplify the implementation of unit-tests. base::TimeTicks now = clock_->NowTicks(); @@ -152,7 +153,7 @@ deferred_resize_timer_.Start( FROM_HERE, next_allowed_resize - now, base::BindOnce(&ResizingHostObserver::SetScreenResolution, - weak_factory_.GetWeakPtr(), resolution)); + weak_factory_.GetWeakPtr(), resolution, screen_id)); return; }
diff --git a/remoting/host/resizing_host_observer.h b/remoting/host/resizing_host_observer.h index 4a1b8d1..80515e7a1 100644 --- a/remoting/host/resizing_host_observer.h +++ b/remoting/host/resizing_host_observer.h
@@ -42,7 +42,8 @@ ~ResizingHostObserver() override; // ScreenControls interface. - void SetScreenResolution(const ScreenResolution& resolution) override; + void SetScreenResolution(const ScreenResolution& resolution, + absl::optional<webrtc::ScreenId> screen_id) override; // Provide a replacement for base::TimeTicks::Now so that this class can be // unit-tested in a timely manner. This function will be called exactly
diff --git a/remoting/host/resizing_host_observer_unittest.cc b/remoting/host/resizing_host_observer_unittest.cc index 55a44c9..d5b49b25 100644 --- a/remoting/host/resizing_host_observer_unittest.cc +++ b/remoting/host/resizing_host_observer_unittest.cc
@@ -114,7 +114,7 @@ } void SetScreenResolution(const ScreenResolution& client_size) { - resizing_host_observer_->SetScreenResolution(client_size); + resizing_host_observer_->SetScreenResolution(client_size, absl::nullopt); if (auto_advance_clock_) clock_.Advance(base::Seconds(1)); }
diff --git a/remoting/ios/DEPS b/remoting/ios/DEPS index 3b6691ff..1ef6988 100644 --- a/remoting/ios/DEPS +++ b/remoting/ios/DEPS
@@ -15,4 +15,5 @@ "+third_party/ocmock", "+third_party/protobuf/src", "+services/network/public/cpp", + "+ui/display", ]
diff --git a/remoting/ios/facade/BUILD.gn b/remoting/ios/facade/BUILD.gn index 9ae2b2b..1ed965e 100644 --- a/remoting/ios/facade/BUILD.gn +++ b/remoting/ios/facade/BUILD.gn
@@ -56,6 +56,7 @@ "//testing/gtest", "//third_party/ocmock", "//ui/base", + "//ui/display", ] configs += [ "//build/config/compiler:enable_arc" ]
diff --git a/remoting/ios/facade/host_list_service_unittest.mm b/remoting/ios/facade/host_list_service_unittest.mm index d8304324..e0412c93 100644 --- a/remoting/ios/facade/host_list_service_unittest.mm +++ b/remoting/ios/facade/host_list_service_unittest.mm
@@ -29,6 +29,7 @@ #include "testing/platform_test.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/display/screen.h" #define EXPECT_HOST_LIST_STATE(expected) \ EXPECT_EQ(expected, host_list_service_.state()) @@ -83,6 +84,7 @@ private: base::CallbackListSubscription host_list_state_subscription_; base::CallbackListSubscription fetch_failure_subscription_; + display::ScopedNativeScreen screen_; }; HostListServiceTest::HostListServiceTest()
diff --git a/services/service_manager/public/cpp/binder_registry.h b/services/service_manager/public/cpp/binder_registry.h index 330eb42..16954a1c 100644 --- a/services/service_manager/public/cpp/binder_registry.h +++ b/services/service_manager/public/cpp/binder_registry.h
@@ -73,6 +73,9 @@ binders_.erase(it); } + // Removes all the binders from the registry. + void clear() { binders_.clear(); } + // Returns true if an InterfaceBinder is registered for |interface_name|. bool CanBindInterface(const std::string& interface_name) const { auto it = binders_.find(interface_name);
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 46559937..c293a25 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -8240,15 +8240,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -8274,7 +8274,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.67" + "revision": "version:102.0.5005.68" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -8750,15 +8750,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--test-expectations", - "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--implementation-outdir", "../../weblayer_instrumentation_test_M102/out/Release", + "--test-expectations", + "../../weblayer/browser/android/javatests/skew/expectations.txt", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -8784,7 +8784,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.67" + "revision": "version:102.0.5005.68" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index c2c0f1e9..9af9dce 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -46214,15 +46214,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -46248,7 +46248,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.67" + "revision": "version:102.0.5005.68" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -46724,15 +46724,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--test-expectations", - "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--implementation-outdir", "../../weblayer_instrumentation_test_M102/out/Release", + "--test-expectations", + "../../weblayer/browser/android/javatests/skew/expectations.txt", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -46758,7 +46758,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.67" + "revision": "version:102.0.5005.68" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -47238,15 +47238,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47272,7 +47272,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.67" + "revision": "version:102.0.5005.68" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -47748,15 +47748,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--test-expectations", - "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--implementation-outdir", "../../weblayer_instrumentation_test_M102/out/Release", + "--test-expectations", + "../../weblayer/browser/android/javatests/skew/expectations.txt", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47782,7 +47782,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.67" + "revision": "version:102.0.5005.68" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -48330,15 +48330,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48364,7 +48364,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.67" + "revision": "version:102.0.5005.68" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -48840,15 +48840,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--test-expectations", - "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", "--implementation-outdir", "../../weblayer_instrumentation_test_M102/out/Release", + "--test-expectations", + "../../weblayer/browser/android/javatests/skew/expectations.txt", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48874,7 +48874,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.67" + "revision": "version:102.0.5005.68" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -49422,15 +49422,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -49456,7 +49456,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.67" + "revision": "version:102.0.5005.68" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -49932,15 +49932,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--test-expectations", - "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", "--implementation-outdir", "../../weblayer_instrumentation_test_M102/out/Release", + "--test-expectations", + "../../weblayer/browser/android/javatests/skew/expectations.txt", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -49966,7 +49966,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.67" + "revision": "version:102.0.5005.68" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index c97ae0b..ac23e5e6 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -57268,4231 +57268,6 @@ } ] }, - "ios14-beta-simulator": { - "additional_compile_targets": [ - "all" - ], - "isolated_scripts": [ - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "absl_hardening_tests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "absl_hardening_tests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad Air 2", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "base_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "base_unittests iPad Air 2 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://base:base_unittests/", - "variant_id": "iPad Air 2 14.5" - }, - { - "args": [ - "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "base_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "base_unittests iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://base:base_unittests/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "base_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "base_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://base:base_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "boringssl_crypto_tests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "boringssl_crypto_tests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "boringssl_ssl_tests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "boringssl_ssl_tests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad Air 2", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "components_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "components_unittests iPad Air 2 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://components:components_unittests/", - "variant_id": "iPad Air 2 14.5" - }, - { - "args": [ - "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "components_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "components_unittests iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://components:components_unittests/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "components_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "components_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://components:components_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "crashpad_tests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "crashpad_tests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "crypto_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "crypto_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://crypto:crypto_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad Air 2", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "gfx_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "gfx_unittests iPad Air 2 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", - "variant_id": "iPad Air 2 14.5" - }, - { - "args": [ - "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "gfx_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "gfx_unittests iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "gfx_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "gfx_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "google_apis_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "google_apis_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://google_apis:google_apis_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad (6th generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_bookmarks_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_bookmarks_eg2tests_module iPad (6th generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", - "variant_id": "iPad (6th generation) 14.5" - }, - { - "args": [ - "--platform", - "iPad Air (3rd generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_bookmarks_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_bookmarks_eg2tests_module iPad Air (3rd generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", - "variant_id": "iPad Air (3rd generation) 14.5" - }, - { - "args": [ - "--platform", - "iPhone 7", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_bookmarks_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_bookmarks_eg2tests_module iPhone 7 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", - "variant_id": "iPhone 7 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_bookmarks_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_bookmarks_eg2tests_module iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad (6th generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_integration_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_integration_eg2tests_module iPad (6th generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 8 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", - "variant_id": "iPad (6th generation) 14.5" - }, - { - "args": [ - "--platform", - "iPad Pro (12.9-inch) (2nd generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_integration_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_integration_eg2tests_module iPad Pro (12.9-inch) (2nd generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 8 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", - "variant_id": "iPad Pro (12.9-inch) (2nd generation) 14.5" - }, - { - "args": [ - "--platform", - "iPhone 7", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_integration_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_integration_eg2tests_module iPhone 7 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 8 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", - "variant_id": "iPhone 7 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_integration_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_integration_eg2tests_module iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 8 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad (6th generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_settings_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_settings_eg2tests_module iPad (6th generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 3 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", - "variant_id": "iPad (6th generation) 14.5" - }, - { - "args": [ - "--platform", - "iPad Air (3rd generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_settings_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_settings_eg2tests_module iPad Air (3rd generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 3 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", - "variant_id": "iPad Air (3rd generation) 14.5" - }, - { - "args": [ - "--platform", - "iPhone 7", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_settings_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_settings_eg2tests_module iPhone 7 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 3 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", - "variant_id": "iPhone 7 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_settings_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_settings_eg2tests_module iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 3 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad (6th generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_signin_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_signin_eg2tests_module iPad (6th generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 5 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", - "variant_id": "iPad (6th generation) 14.5" - }, - { - "args": [ - "--platform", - "iPad Pro (12.9-inch) (2nd generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_signin_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_signin_eg2tests_module iPad Pro (12.9-inch) (2nd generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 5 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", - "variant_id": "iPad Pro (12.9-inch) (2nd generation) 14.5" - }, - { - "args": [ - "--platform", - "iPhone 7", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_signin_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_signin_eg2tests_module iPhone 7 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 5 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", - "variant_id": "iPhone 7 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_signin_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_signin_eg2tests_module iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 5 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad (6th generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_smoke_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_smoke_eg2tests_module iPad (6th generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", - "variant_id": "iPad (6th generation) 14.5" - }, - { - "args": [ - "--platform", - "iPad Air (3rd generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_smoke_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_smoke_eg2tests_module iPad Air (3rd generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", - "variant_id": "iPad Air (3rd generation) 14.5" - }, - { - "args": [ - "--platform", - "iPhone 7", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_smoke_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_smoke_eg2tests_module iPhone 7 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", - "variant_id": "iPhone 7 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_smoke_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_smoke_eg2tests_module iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad (6th generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_ui_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_ui_eg2tests_module iPad (6th generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 12 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", - "variant_id": "iPad (6th generation) 14.5" - }, - { - "args": [ - "--platform", - "iPad Pro (12.9-inch) (2nd generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_ui_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_ui_eg2tests_module iPad Pro (12.9-inch) (2nd generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 12 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", - "variant_id": "iPad Pro (12.9-inch) (2nd generation) 14.5" - }, - { - "args": [ - "--platform", - "iPhone 7", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_ui_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_ui_eg2tests_module iPhone 7 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 12 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", - "variant_id": "iPhone 7 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_ui_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_ui_eg2tests_module iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 12 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad Air 2", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_chrome_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_unittests iPad Air 2 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", - "variant_id": "iPad Air 2 14.5" - }, - { - "args": [ - "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_chrome_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_unittests iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_chrome_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad (6th generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_web_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_web_eg2tests_module iPad (6th generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", - "variant_id": "iPad (6th generation) 14.5" - }, - { - "args": [ - "--platform", - "iPad Air (3rd generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_web_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_web_eg2tests_module iPad Air (3rd generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", - "variant_id": "iPad Air (3rd generation) 14.5" - }, - { - "args": [ - "--platform", - "iPhone 7", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_web_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_web_eg2tests_module iPhone 7 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", - "variant_id": "iPhone 7 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_web_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_web_eg2tests_module iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_components_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_components_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/components:ios_components_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_net_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_net_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 3 - }, - "test_id_prefix": "ninja://ios/net:ios_net_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_remoting_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_remoting_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://remoting/ios:ios_remoting_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad (6th generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_showcase_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_showcase_eg2tests_module iPad (6th generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", - "variant_id": "iPad (6th generation) 14.5" - }, - { - "args": [ - "--platform", - "iPad Air (3rd generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_showcase_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_showcase_eg2tests_module iPad Air (3rd generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", - "variant_id": "iPad Air (3rd generation) 14.5" - }, - { - "args": [ - "--platform", - "iPhone 7", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_showcase_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_showcase_eg2tests_module iPhone 7 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", - "variant_id": "iPhone 7 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_showcase_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_showcase_eg2tests_module iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_testing_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_testing_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/testing:ios_testing_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad Air 2", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_inttests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_inttests iPad Air 2 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web:ios_web_inttests/", - "variant_id": "iPad Air 2 14.5" - }, - { - "args": [ - "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_inttests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_inttests iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web:ios_web_inttests/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_inttests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_inttests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web:ios_web_inttests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad (6th generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_web_shell_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_shell_eg2tests_module iPad (6th generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", - "variant_id": "iPad (6th generation) 14.5" - }, - { - "args": [ - "--platform", - "iPad Pro (12.9-inch) (2nd generation)", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_web_shell_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_shell_eg2tests_module iPad Pro (12.9-inch) (2nd generation) 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", - "variant_id": "iPad Pro (12.9-inch) (2nd generation) 14.5" - }, - { - "args": [ - "--platform", - "iPhone 7", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_web_shell_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_shell_eg2tests_module iPhone 7 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", - "variant_id": "iPhone 7 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_web_shell_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_shell_eg2tests_module iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad Air 2", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_unittests iPad Air 2 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web:ios_web_unittests/", - "variant_id": "iPad Air 2 14.5" - }, - { - "args": [ - "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_unittests iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web:ios_web_unittests/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web:ios_web_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad Air 2", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_view_inttests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_view_inttests iPad Air 2 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", - "variant_id": "iPad Air 2 14.5" - }, - { - "args": [ - "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_view_inttests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_view_inttests iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_view_inttests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_view_inttests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad Air 2", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_view_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_view_unittests iPad Air 2 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", - "variant_id": "iPad Air 2 14.5" - }, - { - "args": [ - "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_view_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_view_unittests iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ios_web_view_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_web_view_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "net_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "net_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://net:net_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "services_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "services_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://services:services_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad Air 2", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "skia_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "skia_unittests iPad Air 2 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://skia:skia_unittests/", - "variant_id": "iPad Air 2 14.5" - }, - { - "args": [ - "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "skia_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "skia_unittests iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://skia:skia_unittests/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "skia_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "skia_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://skia:skia_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "sql_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "sql_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://sql:sql_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPad Air 2", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ui_base_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ui_base_unittests iPad Air 2 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ui/base:ui_base_unittests/", - "variant_id": "iPad Air 2 14.5" - }, - { - "args": [ - "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ui_base_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ui_base_unittests iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ui/base:ui_base_unittests/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "ui_base_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ui_base_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://ui/base:ui_base_unittests/", - "variant_id": "iPhone X 14.5" - }, - { - "args": [ - "--platform", - "iPhone X", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "13c100", - "--xctest" - ], - "isolate_name": "url_unittests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "url_unittests iPhone X 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-11|Mac-10.16" - } - ], - "named_caches": [ - { - "name": "xcode_ios_13c100", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://url:url_unittests/", - "variant_id": "iPhone X 14.5" - } - ] - }, - "ios14-sdk-simulator": { - "additional_compile_targets": [ - "all" - ] - }, "ios15-beta-simulator": { "additional_compile_targets": [ "all" @@ -78626,6 +74401,4231 @@ } ] }, + "ios16-beta-simulator": { + "additional_compile_targets": [ + "all" + ], + "isolated_scripts": [ + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "absl_hardening_tests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "absl_hardening_tests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad Air 2", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "base_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "base_unittests iPad Air 2 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://base:base_unittests/", + "variant_id": "iPad Air 2 14.5" + }, + { + "args": [ + "--platform", + "iPhone 6s Plus", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "base_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "base_unittests iPhone 6s Plus 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://base:base_unittests/", + "variant_id": "iPhone 6s Plus 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "base_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "base_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://base:base_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "boringssl_crypto_tests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "boringssl_crypto_tests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "boringssl_ssl_tests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "boringssl_ssl_tests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad Air 2", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "components_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "components_unittests iPad Air 2 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://components:components_unittests/", + "variant_id": "iPad Air 2 14.5" + }, + { + "args": [ + "--platform", + "iPhone 6s Plus", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "components_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "components_unittests iPhone 6s Plus 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://components:components_unittests/", + "variant_id": "iPhone 6s Plus 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "components_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "components_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://components:components_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "crashpad_tests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "crashpad_tests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "crypto_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "crypto_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://crypto:crypto_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad Air 2", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "gfx_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "gfx_unittests iPad Air 2 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", + "variant_id": "iPad Air 2 14.5" + }, + { + "args": [ + "--platform", + "iPhone 6s Plus", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "gfx_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "gfx_unittests iPhone 6s Plus 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", + "variant_id": "iPhone 6s Plus 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "gfx_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "gfx_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "google_apis_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "google_apis_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://google_apis:google_apis_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad (6th generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_bookmarks_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_bookmarks_eg2tests_module iPad (6th generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", + "variant_id": "iPad (6th generation) 14.5" + }, + { + "args": [ + "--platform", + "iPad Air (3rd generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_bookmarks_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_bookmarks_eg2tests_module iPad Air (3rd generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", + "variant_id": "iPad Air (3rd generation) 14.5" + }, + { + "args": [ + "--platform", + "iPhone 7", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_bookmarks_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_bookmarks_eg2tests_module iPhone 7 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", + "variant_id": "iPhone 7 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_bookmarks_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_bookmarks_eg2tests_module iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad (6th generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_integration_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_integration_eg2tests_module iPad (6th generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 8 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", + "variant_id": "iPad (6th generation) 14.5" + }, + { + "args": [ + "--platform", + "iPad Pro (12.9-inch) (2nd generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_integration_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_integration_eg2tests_module iPad Pro (12.9-inch) (2nd generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 8 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", + "variant_id": "iPad Pro (12.9-inch) (2nd generation) 14.5" + }, + { + "args": [ + "--platform", + "iPhone 7", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_integration_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_integration_eg2tests_module iPhone 7 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 8 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", + "variant_id": "iPhone 7 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_integration_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_integration_eg2tests_module iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 8 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad (6th generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_settings_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_settings_eg2tests_module iPad (6th generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", + "variant_id": "iPad (6th generation) 14.5" + }, + { + "args": [ + "--platform", + "iPad Air (3rd generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_settings_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_settings_eg2tests_module iPad Air (3rd generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", + "variant_id": "iPad Air (3rd generation) 14.5" + }, + { + "args": [ + "--platform", + "iPhone 7", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_settings_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_settings_eg2tests_module iPhone 7 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", + "variant_id": "iPhone 7 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_settings_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_settings_eg2tests_module iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad (6th generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_signin_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_signin_eg2tests_module iPad (6th generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 5 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", + "variant_id": "iPad (6th generation) 14.5" + }, + { + "args": [ + "--platform", + "iPad Pro (12.9-inch) (2nd generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_signin_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_signin_eg2tests_module iPad Pro (12.9-inch) (2nd generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 5 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", + "variant_id": "iPad Pro (12.9-inch) (2nd generation) 14.5" + }, + { + "args": [ + "--platform", + "iPhone 7", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_signin_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_signin_eg2tests_module iPhone 7 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 5 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", + "variant_id": "iPhone 7 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_signin_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_signin_eg2tests_module iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 5 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad (6th generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_smoke_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_smoke_eg2tests_module iPad (6th generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", + "variant_id": "iPad (6th generation) 14.5" + }, + { + "args": [ + "--platform", + "iPad Air (3rd generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_smoke_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_smoke_eg2tests_module iPad Air (3rd generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", + "variant_id": "iPad Air (3rd generation) 14.5" + }, + { + "args": [ + "--platform", + "iPhone 7", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_smoke_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_smoke_eg2tests_module iPhone 7 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", + "variant_id": "iPhone 7 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_smoke_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_smoke_eg2tests_module iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad (6th generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_ui_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_ui_eg2tests_module iPad (6th generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", + "variant_id": "iPad (6th generation) 14.5" + }, + { + "args": [ + "--platform", + "iPad Pro (12.9-inch) (2nd generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_ui_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_ui_eg2tests_module iPad Pro (12.9-inch) (2nd generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", + "variant_id": "iPad Pro (12.9-inch) (2nd generation) 14.5" + }, + { + "args": [ + "--platform", + "iPhone 7", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_ui_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_ui_eg2tests_module iPhone 7 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", + "variant_id": "iPhone 7 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_ui_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_ui_eg2tests_module iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad Air 2", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_chrome_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_unittests iPad Air 2 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", + "variant_id": "iPad Air 2 14.5" + }, + { + "args": [ + "--platform", + "iPhone 6s Plus", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_chrome_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_unittests iPhone 6s Plus 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", + "variant_id": "iPhone 6s Plus 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_chrome_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad (6th generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_web_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_web_eg2tests_module iPad (6th generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", + "variant_id": "iPad (6th generation) 14.5" + }, + { + "args": [ + "--platform", + "iPad Air (3rd generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_web_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_web_eg2tests_module iPad Air (3rd generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", + "variant_id": "iPad Air (3rd generation) 14.5" + }, + { + "args": [ + "--platform", + "iPhone 7", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_web_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_web_eg2tests_module iPhone 7 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", + "variant_id": "iPhone 7 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_web_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_web_eg2tests_module iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_components_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_components_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/components:ios_components_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_net_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_net_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test_id_prefix": "ninja://ios/net:ios_net_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_remoting_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_remoting_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://remoting/ios:ios_remoting_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad (6th generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_showcase_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_showcase_eg2tests_module iPad (6th generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", + "variant_id": "iPad (6th generation) 14.5" + }, + { + "args": [ + "--platform", + "iPad Air (3rd generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_showcase_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_showcase_eg2tests_module iPad Air (3rd generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", + "variant_id": "iPad Air (3rd generation) 14.5" + }, + { + "args": [ + "--platform", + "iPhone 7", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_showcase_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_showcase_eg2tests_module iPhone 7 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", + "variant_id": "iPhone 7 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_showcase_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_showcase_eg2tests_module iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_testing_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_testing_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/testing:ios_testing_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad Air 2", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_inttests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_inttests iPad Air 2 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web:ios_web_inttests/", + "variant_id": "iPad Air 2 14.5" + }, + { + "args": [ + "--platform", + "iPhone 6s Plus", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_inttests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_inttests iPhone 6s Plus 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web:ios_web_inttests/", + "variant_id": "iPhone 6s Plus 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_inttests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_inttests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web:ios_web_inttests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad (6th generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_web_shell_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_shell_eg2tests_module iPad (6th generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", + "variant_id": "iPad (6th generation) 14.5" + }, + { + "args": [ + "--platform", + "iPad Pro (12.9-inch) (2nd generation)", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_web_shell_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_shell_eg2tests_module iPad Pro (12.9-inch) (2nd generation) 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", + "variant_id": "iPad Pro (12.9-inch) (2nd generation) 14.5" + }, + { + "args": [ + "--platform", + "iPhone 7", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_web_shell_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_shell_eg2tests_module iPhone 7 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", + "variant_id": "iPhone 7 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_web_shell_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_shell_eg2tests_module iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad Air 2", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_unittests iPad Air 2 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web:ios_web_unittests/", + "variant_id": "iPad Air 2 14.5" + }, + { + "args": [ + "--platform", + "iPhone 6s Plus", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_unittests iPhone 6s Plus 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web:ios_web_unittests/", + "variant_id": "iPhone 6s Plus 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web:ios_web_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad Air 2", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_view_inttests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_view_inttests iPad Air 2 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", + "variant_id": "iPad Air 2 14.5" + }, + { + "args": [ + "--platform", + "iPhone 6s Plus", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_view_inttests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_view_inttests iPhone 6s Plus 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", + "variant_id": "iPhone 6s Plus 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_view_inttests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_view_inttests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad Air 2", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_view_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_view_unittests iPad Air 2 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", + "variant_id": "iPad Air 2 14.5" + }, + { + "args": [ + "--platform", + "iPhone 6s Plus", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_view_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_view_unittests iPhone 6s Plus 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", + "variant_id": "iPhone 6s Plus 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ios_web_view_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_web_view_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "net_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "net_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://net:net_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "services_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "services_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://services:services_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad Air 2", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "skia_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "skia_unittests iPad Air 2 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://skia:skia_unittests/", + "variant_id": "iPad Air 2 14.5" + }, + { + "args": [ + "--platform", + "iPhone 6s Plus", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "skia_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "skia_unittests iPhone 6s Plus 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://skia:skia_unittests/", + "variant_id": "iPhone 6s Plus 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "skia_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "skia_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://skia:skia_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "sql_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "sql_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://sql:sql_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPad Air 2", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ui_base_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ui_base_unittests iPad Air 2 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ui/base:ui_base_unittests/", + "variant_id": "iPad Air 2 14.5" + }, + { + "args": [ + "--platform", + "iPhone 6s Plus", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ui_base_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ui_base_unittests iPhone 6s Plus 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ui/base:ui_base_unittests/", + "variant_id": "iPhone 6s Plus 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "ui_base_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ui_base_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ui/base:ui_base_unittests/", + "variant_id": "iPhone X 14.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "14.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "13c100", + "--xctest" + ], + "isolate_name": "url_unittests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "url_unittests iPhone X 14.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-11|Mac-10.16" + } + ], + "named_caches": [ + { + "name": "xcode_ios_13c100", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_14_5", + "path": "Runtime-ios-14.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://url:url_unittests/", + "variant_id": "iPhone X 14.5" + } + ] + }, + "ios16-sdk-simulator": { + "additional_compile_targets": [ + "all" + ] + }, "lacros-amd64-generic-rel (goma cache silo)": { "additional_compile_targets": [ "chrome"
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 2caedc82..0062ed1 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -6905,44 +6905,6 @@ }, }, - 'ios14_beta_simulator_tests': { - 'ios_common_tests': { - 'variants': [ - 'SIM_IPHONE_X_14_5', - ], - }, - 'ios_crash_unittests': { - 'variants': [ - 'SIM_IPHONE_X_14_5', - ], - }, - 'ios_eg2_tests': { - 'mixins': ['xcode_parallelization'], - 'variants': [ - 'SIM_IPHONE_X_14_5', - 'SIM_IPHONE_7_14_5', - 'SIM_IPAD_AIR_3RD_GEN_14_5', - 'SIM_IPAD_6_GEN_14_5', - ] - }, - 'ios_eg2_cq_tests': { - 'mixins': ['xcode_parallelization'], - 'variants': [ - 'SIM_IPHONE_7_14_5', - 'SIM_IPHONE_X_14_5', - 'SIM_IPAD_PRO_2ND_GEN_14_5', - 'SIM_IPAD_6_GEN_14_5', - ] - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPHONE_6S_PLUS_14_5', - 'SIM_IPHONE_X_14_5', - 'SIM_IPAD_AIR_2_14_5', - ], - }, - }, - 'ios15_beta_simulator_tests': { 'ios_common_tests': { 'variants': [ @@ -7048,6 +7010,44 @@ }, }, + 'ios16_beta_simulator_tests': { + 'ios_common_tests': { + 'variants': [ + 'SIM_IPHONE_X_14_5', + ], + }, + 'ios_crash_unittests': { + 'variants': [ + 'SIM_IPHONE_X_14_5', + ], + }, + 'ios_eg2_tests': { + 'mixins': ['xcode_parallelization'], + 'variants': [ + 'SIM_IPHONE_X_14_5', + 'SIM_IPHONE_7_14_5', + 'SIM_IPAD_AIR_3RD_GEN_14_5', + 'SIM_IPAD_6_GEN_14_5', + ] + }, + 'ios_eg2_cq_tests': { + 'mixins': ['xcode_parallelization'], + 'variants': [ + 'SIM_IPHONE_7_14_5', + 'SIM_IPHONE_X_14_5', + 'SIM_IPAD_PRO_2ND_GEN_14_5', + 'SIM_IPAD_6_GEN_14_5', + ] + }, + 'ios_screen_size_dependent_tests': { + 'variants': [ + 'SIM_IPHONE_6S_PLUS_14_5', + 'SIM_IPHONE_X_14_5', + 'SIM_IPAD_AIR_2_14_5', + ], + }, + }, + 'ios_asan_tests': { 'ios_common_tests': { 'variants': [
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 00cc865..8218057 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -486,16 +486,16 @@ }, 'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ + '--webview-apk-path=apks/AOSP_SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--test-expectations', - '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--webview-apk-path=apks/AOSP_SystemWebView.apk', '--implementation-outdir', '../../weblayer_instrumentation_test_M102/out/Release', - '--impl-version=102' + '--test-expectations', + '../../weblayer/browser/android/javatests/skew/expectations.txt', + '--impl-version=102', ], 'identifier': 'with_impl_from_102', 'swarming': { @@ -503,10 +503,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.67' + 'revision': 'version:102.0.5005.68', } - ] - } + ], + }, }, 'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [ @@ -630,16 +630,16 @@ }, 'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ + '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--test-expectations', - '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--webview-apk-path=apks/SystemWebView.apk', '--implementation-outdir', '../../weblayer_instrumentation_test_M102/out/Release', - '--impl-version=102' + '--test-expectations', + '../../weblayer/browser/android/javatests/skew/expectations.txt', + '--impl-version=102', ], 'identifier': 'with_impl_from_102', 'swarming': { @@ -647,10 +647,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.67' + 'revision': 'version:102.0.5005.68', } - ] - } + ], + }, }, 'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [ @@ -774,16 +774,16 @@ }, 'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ + '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', + '--client-outdir', + '../../weblayer_instrumentation_test_M102/out/Release', '--implementation-outdir', '.', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--webview-apk-path=apks/SystemWebView.apk', - '--client-outdir', - '../../weblayer_instrumentation_test_M102/out/Release', - '--client-version=102' + '--client-version=102', ], 'identifier': 'with_client_from_102', 'swarming': { @@ -791,10 +791,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.67' + 'revision': 'version:102.0.5005.68', } - ] - } + ], + }, }, 'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 6e44ffd3..c66301e 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -3293,39 +3293,6 @@ 'isolated_scripts': 'ios_webkit_tot_tests', }, }, - # ios14-beta-sim compiles with xcode version n-1, but - # runs testers with xcode n during an xcode roll. - 'ios14-beta-simulator': { - 'additional_compile_targets': [ - 'all', - ], - 'mixins': [ - 'has_native_resultdb_integration', - 'mac_11_x64', - 'mac_toolchain', - 'out_dir_arg', - 'xcode_13_main', - 'xctest', - ], - 'test_suites': { - 'isolated_scripts': 'ios14_beta_simulator_tests' - }, - }, - # ios14-sdk-sim compiles with xcode version n, and runs - # testers with xcode n during an xcode roll. - 'ios14-sdk-simulator': { - 'additional_compile_targets': [ - 'all', - ], - 'mixins': [ - 'has_native_resultdb_integration', - 'mac_11_x64', - 'mac_toolchain', - 'out_dir_arg', - 'xcode_13_main', - 'xctest', - ], - }, 'ios15-beta-simulator': { 'additional_compile_targets': [ 'all', @@ -3363,6 +3330,39 @@ 'isolated_scripts': 'ios15_sdk_simulator_tests' }, }, + # ios16-beta-sim compiles with xcode version n-1, but + # runs testers with xcode n during an xcode roll. + 'ios16-beta-simulator': { + 'additional_compile_targets': [ + 'all', + ], + 'mixins': [ + 'has_native_resultdb_integration', + 'mac_11_x64', + 'mac_toolchain', + 'out_dir_arg', + 'xcode_13_main', + 'xctest', + ], + 'test_suites': { + 'isolated_scripts': 'ios16_beta_simulator_tests' + }, + }, + # ios16-sdk-sim compiles with xcode version n, and runs + # testers with xcode n during an xcode roll. + 'ios16-sdk-simulator': { + 'additional_compile_targets': [ + 'all', + ], + 'mixins': [ + 'has_native_resultdb_integration', + 'mac_11_x64', + 'mac_toolchain', + 'out_dir_arg', + 'xcode_13_main', + 'xctest', + ], + }, 'lacros-amd64-generic-rel (goma cache silo)': { 'additional_compile_targets': [ 'chrome',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 751c579..8d4a88f 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -912,28 +912,6 @@ ] } ], - "AutofillEnableSendingBcnInGetUploadDetails": [ - { - "platforms": [ - "android", - "android_webview", - "chromeos", - "chromeos_lacros", - "ios", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "AutofillEnableSendingBcnInGetUploadDetails" - ] - } - ] - } - ], "AutofillEnableSupportForMoreStructureInAddresses": [ { "platforms": [ @@ -2898,6 +2876,51 @@ "disable_features": [ "NtpShoppingTasksModule" ] + }, + { + "name": "Fre_20220509", + "params": { + "NtpChromeCartModuleAbandonedCartDiscountParam": "true", + "NtpChromeCartModuleAbandonedCartDiscountUseUtmParam": "true", + "NtpChromeCartModuleHeuristicsImprovementParam": "true", + "NtpDriveModuleExperimentGroupParam": "foo:bar", + "NtpDriveModuleManagedUsersOnlyParam": "true", + "NtpModulesLoadTimeoutMillisecondsParam": "3000", + "discount-fetch-delay": "1h", + "use_sapi_v2": "true" + }, + "enable_features": [ + "NtpChromeCartModule", + "NtpDriveModule", + "NtpModules", + "NtpModulesFirstRunExperience", + "NtpRecipeTasksModule" + ], + "disable_features": [ + "NtpShoppingTasksModule" + ] + }, + { + "name": "Fre_Control_20220509", + "params": { + "NtpChromeCartModuleAbandonedCartDiscountParam": "true", + "NtpChromeCartModuleAbandonedCartDiscountUseUtmParam": "true", + "NtpChromeCartModuleHeuristicsImprovementParam": "true", + "NtpDriveModuleExperimentGroupParam": "foo:bar", + "NtpDriveModuleManagedUsersOnlyParam": "true", + "NtpModulesLoadTimeoutMillisecondsParam": "3000", + "discount-fetch-delay": "1h" + }, + "enable_features": [ + "NtpChromeCartModule", + "NtpDriveModule", + "NtpModules", + "NtpModulesFirstRunExperience", + "NtpRecipeTasksModule" + ], + "disable_features": [ + "NtpShoppingTasksModule" + ] } ] } @@ -3388,21 +3411,6 @@ ] } ], - "EnhancedSafeBrowsing": [ - { - "platforms": [ - "ios" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "SafeBrowsingEnhancedProtection" - ] - } - ] - } - ], "EstablishGpuChannelAsync": [ { "platforms": [ @@ -3791,7 +3799,7 @@ "name": "Enabled", "params": { "enable_tab_group_auto_creation": "false", - "show_open_in_tab_group_menu_item_first": "false" + "show_open_in_tab_group_menu_item_first": "true" }, "enable_features": [ "TabGridLayoutAndroid" @@ -6670,6 +6678,21 @@ ] } ], + "SafeBrowsingEnhancedProtection": [ + { + "platforms": [ + "ios" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "SafeBrowsingEnhancedProtection" + ] + } + ] + } + ], "SafeBrowsingSendSampledPingsForProtegoAllowlistDomains": [ { "platforms": [ @@ -6937,6 +6960,61 @@ ] } ], + "SharedHighlightingRefinedMaxContextWords": [ + { + "platforms": [ + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled_MaxContextWords_15", + "params": { + "SharedHighlightingMaxContextWords": "15" + }, + "enable_features": [ + "SharedHighlightingRefinedMaxContextWords" + ] + }, + { + "name": "Enabled_MaxContextWords_5", + "params": { + "SharedHighlightingMaxContextWords": "5" + }, + "enable_features": [ + "SharedHighlightingRefinedMaxContextWords" + ] + }, + { + "name": "Enabled_MaxContextWords_10", + "params": { + "SharedHighlightingMaxContextWords": "10" + }, + "enable_features": [ + "SharedHighlightingRefinedMaxContextWords" + ] + }, + { + "name": "Enabled_MaxContextWords_20", + "params": { + "SharedHighlightingMaxContextWords": "20" + }, + "enable_features": [ + "SharedHighlightingRefinedMaxContextWords" + ] + }, + { + "name": "Control", + "disable_features": [ + "SharedHighlightingRefinedMaxContextWords" + ] + } + ] + } + ], "SharedHighlightingTimeout": [ { "platforms": [
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index b83361a..78ccefc8 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -751,7 +751,6 @@ CrossOriginWindowAlert CrossOriginWindowConfirm CSSSelectorInternalMediaControlsOverlayCastButton - CustomCursorIntersectsViewport DeprecationExample DocumentDomainSettingWithoutOriginAgentClusterHeader EventPath
diff --git a/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom b/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom index 59b29d66..3f5d776 100644 --- a/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom +++ b/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom
@@ -94,4 +94,8 @@ // Interface used by the browser to send the `start` event to Window Management // System Extensions service workers. This is only bound once when the system // extension is installed and the event is dispatched. -interface CrosWindowManagementStartObserver {}; +interface CrosWindowManagementStartObserver { + // Notify the renderer that it should dispatch the `start` event. Currently, + // start is only dispatched when the System Extension is installed. + DispatchStartEvent(); +};
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom index 2597671..727e364 100644 --- a/third_party/blink/public/mojom/frame/frame.mojom +++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -53,6 +53,7 @@ import "third_party/blink/public/mojom/frame/viewport_intersection_state.mojom"; import "third_party/blink/public/mojom/input/focus_type.mojom"; import "third_party/blink/public/mojom/input/scroll_direction.mojom"; +import "third_party/blink/public/mojom/messaging/delegated_capability.mojom"; import "third_party/blink/public/mojom/navigation/navigation_api_history_entry_arrays.mojom"; import "third_party/blink/public/mojom/navigation/navigation_policy.mojom"; import "third_party/blink/public/mojom/loader/referrer.mojom"; @@ -142,6 +143,12 @@ kRotate90Counterclockwise, }; +// The result of executing JavaScript within a frame. +enum JavaScriptExecutionResultType { + kSuccess, + kException, +}; + // The maximum number of characters of the document's title that we're willing // to accept in the browser process. const uint16 kMaxTitleChars = 4096; // 4 * 1024; @@ -571,6 +578,12 @@ // sends the new value to the browser. Also sent when a subframe's content // frame is changed. DidChangeSrcDoc(blink.mojom.FrameToken child_frame_token, string srcdoc_value); + + // Notifies the browser that this frame received a message from a local frame + // with a delegated capability (https://wicg.github.io/capability-delegation). + // `delegated_capability` is the capability delegated via postMessage(). + // RemoteFrameHost messages already signal the browser via RouteMessageEvent. + ReceivedDelegatedCapability(DelegatedCapability delegated_capability); }; // Implemented in Blink, this interface defines frame-specific methods that will @@ -772,13 +785,14 @@ // ONLY FOR TESTS: Same as above but this can optionally trigger a fake user // activation notification to test functionalities that are gated by user - // activation. + // activation, and can block until a resulting promise is resolved. JavaScriptExecuteRequestForTests( mojo_base.mojom.BigString16 javascript, - bool wants_result, bool has_user_gesture, + bool resolve_promises, int32 world_id) - => (mojo_base.mojom.Value result); + => (JavaScriptExecutionResultType result_type, + mojo_base.mojom.Value result); // Same as JavaScriptExecuteRequest above except the script is run in the // isolated world specified by the fourth parameter.
diff --git a/third_party/blink/public/mojom/service_worker/embedded_worker.mojom b/third_party/blink/public/mojom/service_worker/embedded_worker.mojom index 1ef6199..821501f8 100644 --- a/third_party/blink/public/mojom/service_worker/embedded_worker.mojom +++ b/third_party/blink/public/mojom/service_worker/embedded_worker.mojom
@@ -27,6 +27,7 @@ import "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom"; import "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom"; import "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom"; +import "services/service_manager/public/mojom/interface_provider.mojom"; import "url/mojom/url.mojom"; // Parameters to launch a service worker. This is passed from the browser to the @@ -89,6 +90,9 @@ // Used to talk to the service worker from the browser process. pending_receiver<ServiceWorker> service_worker_receiver; + // Used by the browser to request interfaces exposed by the renderer. + pending_receiver<service_manager.mojom.InterfaceProvider> interface_provider; + // Cloned and passed to each controllee to directly dispatch events from the // controllees. pending_receiver<ControllerServiceWorker> controller_receiver;
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom index 5618778..aaa55b2 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -2120,7 +2120,7 @@ kNoSysexWebMIDIWithoutPermission = 2770, kNoSysexWebMIDIOnInsecureOrigin = 2771, kOBSOLETE_ApplicationCacheInstalledButNoManifest = 2772, - kCustomCursorIntersectsViewport = 2776, + kOBSOLETE_CustomCursorIntersectsViewport = 2776, kOBSOLETE_ClientHintsLang = 2777, kLinkRelPreloadImageSrcset = 2778, kV8HTMLMediaElement_Remote_AttributeGetter = 2779,
diff --git a/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.cc b/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.cc index a9b9d72..84133514b 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.cc
@@ -55,12 +55,20 @@ } // static -ScriptEvaluationResult ScriptEvaluationResult::FromClassicException() { +ScriptEvaluationResult ScriptEvaluationResult::FromClassicExceptionRethrown() { return ScriptEvaluationResult(mojom::blink::ScriptType::kClassic, ResultType::kException, {}); } // static +ScriptEvaluationResult ScriptEvaluationResult::FromClassicException( + v8::Local<v8::Value> exception) { + DCHECK(!exception.IsEmpty()); + return ScriptEvaluationResult(mojom::blink::ScriptType::kClassic, + ResultType::kException, exception); +} + +// static ScriptEvaluationResult ScriptEvaluationResult::FromModuleException( v8::Local<v8::Value> exception) { DCHECK(!exception.IsEmpty()); @@ -102,6 +110,14 @@ return value_; } +v8::Local<v8::Value> ScriptEvaluationResult::GetExceptionForClassicForTesting() + const { + DCHECK_EQ(result_type_, ResultType::kException); + DCHECK(!value_.IsEmpty()); + + return value_; +} + ScriptPromise ScriptEvaluationResult::GetPromise( ScriptState* script_state) const { #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h b/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h index 18c77df..da3a586 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h +++ b/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h
@@ -59,8 +59,11 @@ // The script is evaluated and an exception is thrown. // Spec: #run-a-classic-script/#run-a-module-script return an abrupt // completion. - // |value_| is the non-empty exception thrown for module scripts, or - // empty for classic scripts. + // |value_| is the non-empty exception thrown for + // - module scripts or + // - classic scripts with |RethrowErrorsOption::DoNotRethrow()| + // or empty for + // - classic scripts with |RethrowErrorsOption::Rethrow()| // // Note: The exception can be already caught and passed to // https://html.spec.whatwg.org/C/#report-the-error, instead of being @@ -88,7 +91,9 @@ static ScriptEvaluationResult FromClassicNotRun(); static ScriptEvaluationResult FromClassicSuccess(v8::Local<v8::Value> value); - static ScriptEvaluationResult FromClassicException(); + static ScriptEvaluationResult FromClassicExceptionRethrown(); + static ScriptEvaluationResult FromClassicException( + v8::Local<v8::Value> exception); static ScriptEvaluationResult FromClassicAborted(); static ScriptEvaluationResult FromModuleNotRun(); @@ -112,6 +117,10 @@ // Can be called only when GetResultType() == kException. v8::Local<v8::Value> GetExceptionForModule() const; + // Returns the exception thrown for both module and classic scripts. + // Can be called only when GetResultType() == kException. + v8::Local<v8::Value> GetExceptionForClassicForTesting() const; + // Returns the promise returned by #run-a-module-script. // Can be called only // - For module script with TLA is enabled, and
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc index cd152a7..8762e2c 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
@@ -619,32 +619,35 @@ // reported to WorkerGlobalScope.onerror via `TryCatch::SetVerbose(true)` // called at top-level worker script evaluation. try_catch.ReThrow(); - return ScriptEvaluationResult::FromClassicException(); + return ScriptEvaluationResult::FromClassicExceptionRethrown(); + } + + // Step 8.1.3. Otherwise, rethrow errors is false. Perform the following + // steps: [spec text] + if (!rethrow_errors.ShouldRethrow()) { + // #report-the-error for rethrow errors == true is already handled via + // `TryCatch::SetVerbose(true)` above. + return ScriptEvaluationResult::FromClassicException( + try_catch.Exception()); } } // |v8::TryCatch| is (and should be) exited, before ThrowException() below. - if (rethrow_errors.ShouldRethrow()) { - // kDoNotSanitize case is processed and early-exited above. - DCHECK_EQ(sanitize_script_errors, SanitizeScriptErrors::kSanitize); + // kDoNotSanitize case is processed and early-exited above. + DCHECK(rethrow_errors.ShouldRethrow()); + DCHECK_EQ(sanitize_script_errors, SanitizeScriptErrors::kSanitize); - // Step 8.2. If rethrow errors is true and script's muted errors is - // true, then: [spec text] - // - // Step 8.2.2. Throw a "NetworkError" DOMException. [spec text] - // - // We don't supply any message here to avoid leaking details of muted - // errors. - V8ThrowException::ThrowException( - isolate, V8ThrowDOMException::CreateOrEmpty( - isolate, DOMExceptionCode::kNetworkError, - rethrow_errors.Message())); - return ScriptEvaluationResult::FromClassicException(); - } - - // #report-the-error for rethrow errors == true is already handled via - // |TryCatch::SetVerbose(true)| above. - return ScriptEvaluationResult::FromClassicException(); + // Step 8.2. If rethrow errors is true and script's muted errors is true, + // then: [spec text] + // + // Step 8.2.2. Throw a "NetworkError" DOMException. [spec text] + // + // We don't supply any message here to avoid leaking details of muted errors. + V8ThrowException::ThrowException( + isolate, + V8ThrowDOMException::CreateOrEmpty( + isolate, DOMExceptionCode::kNetworkError, rethrow_errors.Message())); + return ScriptEvaluationResult::FromClassicExceptionRethrown(); } v8::MaybeLocal<v8::Value> V8ScriptRunner::CompileAndRunInternalScript(
diff --git a/third_party/blink/renderer/controller/blink_initializer.cc b/third_party/blink/renderer/controller/blink_initializer.cc index 36cd94d..79e4ce5 100644 --- a/third_party/blink/renderer/controller/blink_initializer.cc +++ b/third_party/blink/renderer/controller/blink_initializer.cc
@@ -131,6 +131,13 @@ #endif // !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_ARM64) && // BUILDFLAG(IS_WIN) +#if defined(USE_BLINK_EXTENSIONS_CHROMEOS) + // ChromeOSExtensions::Initialize() initializes strings which must be done + // before calling CoreInitializer::Initialize() which is called by + // GetBlinkInitializer().Initialize() below. + ChromeOSExtensions::Initialize(); +#endif + // BlinkInitializer::Initialize() must be called before InitializeMainThread GetBlinkInitializer().Initialize(); @@ -146,10 +153,6 @@ g_end_of_task_runner = new EndOfTaskRunner; Thread::Current()->AddTaskObserver(g_end_of_task_runner); -#if defined(USE_BLINK_EXTENSIONS_CHROMEOS) - ChromeOSExtensions::Initialize(); -#endif - #if BUILDFLAG(IS_ANDROID) // Initialize CrashMemoryMetricsReporterImpl in order to assure that memory // allocation does not happen in OnOOMCallback.
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc index 1853b70..32752e70 100644 --- a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc +++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.cc
@@ -128,7 +128,15 @@ TextFragmentSelectorGenerator::TextFragmentSelectorGenerator( LocalFrame* main_frame) - : frame_(main_frame) {} + : frame_(main_frame) { + if (base::FeatureList::IsEnabled( + shared_highlighting::kSharedHighlightingRefinedMaxContextWords)) { + max_context_words_ = + shared_highlighting::kSharedHighlightingMaxContextWords.Get(); + } else { + max_context_words_ = kMaxContextWords; + } +} void TextFragmentSelectorGenerator::Generate(const RangeInFlatTree& range, GenerateCallback callback) { @@ -564,7 +572,7 @@ DCHECK(selector_); // Give up if context is already too long. - if (num_context_words_ >= kMaxContextWords) { + if (num_context_words_ >= max_context_words_) { state_ = kFailure; error_ = LinkGenerationError::kContextLimitReached; return;
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h index 0bbc96f..7ceae62f 100644 --- a/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h +++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h
@@ -196,6 +196,10 @@ int num_range_words_ = 0; + // Indicates the Max Context Words allowed for the + // SharedHighlightsMaxContextWords experiment + int max_context_words_ = 10; + int iteration_ = 0; base::TimeTicks generation_start_time_;
diff --git a/third_party/blink/renderer/core/frame/deprecation/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation/deprecation.cc index 9ebf78a..42f7ad68 100644 --- a/third_party/blink/renderer/core/frame/deprecation/deprecation.cc +++ b/third_party/blink/renderer/core/frame/deprecation/deprecation.cc
@@ -92,9 +92,6 @@ return DeprecationInfo::WithTranslation( feature, DeprecationIssueType:: kCSSSelectorInternalMediaControlsOverlayCastButton); - case WebFeature::kCustomCursorIntersectsViewport: - return DeprecationInfo::WithTranslation( - feature, DeprecationIssueType::kCustomCursorIntersectsViewport); case WebFeature::kDeprecationExample: return DeprecationInfo::WithTranslation( feature, DeprecationIssueType::kDeprecationExample);
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc index a252031..28f9aae 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -1064,6 +1064,15 @@ source->GetStorageKey(), UkmSourceID(), GetStorageKey(), UkmRecorder()); + // Notify the host if the message contained a delegated capability. That state + // should be tracked by the browser, and messages from remote hosts already + // signal the browser via RemoteFrameHost's RouteMessageEvent. + if (posted_message->delegated_capability != + mojom::blink::DelegatedCapability::kNone) { + GetFrame()->GetLocalFrameHostRemote().ReceivedDelegatedCapability( + posted_message->delegated_capability); + } + // Convert the posted message to a MessageEvent so it can be unpacked for // local dispatch. MessageEvent* event = MessageEvent::Create( @@ -1191,7 +1200,6 @@ mojom::blink::DelegatedCapability::kFullscreenRequest) { UseCounter::Count(this, WebFeature::kCapabilityDelegationOfFullscreenRequest); - // TODO(crbug.com/1293083): Activate a corresponding token in the browser. fullscreen_request_token_.Activate(); }
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc index e0795c17..e4a632d 100644 --- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc +++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -26,6 +26,7 @@ #include "third_party/blink/public/web/web_plugin.h" #include "third_party/blink/renderer/bindings/core/v8/script_controller.h" #include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h" +#include "third_party/blink/renderer/bindings/core/v8/script_function.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" @@ -168,10 +169,9 @@ } base::Value GetJavaScriptExecutionResult(v8::Local<v8::Value> result, - LocalFrame* local_frame, + v8::Local<v8::Context> context, WebV8ValueConverter* converter) { if (!result.IsEmpty()) { - v8::Local<v8::Context> context = MainWorldScriptContext(local_frame); v8::Context::Scope context_scope(context); std::unique_ptr<base::Value> new_value = converter->FromV8Value(result, context); @@ -335,6 +335,115 @@ metadata->image = document.CompleteURL(element.Content()); } +// Convert the error to a string so it can be sent back to the test. +// +// We try to use .stack property so that the error message contains a stack +// trace, but otherwise fallback to .toString(). +v8::Local<v8::String> ErrorToString(ScriptState* script_state, + v8::Local<v8::Value> error) { + if (!error.IsEmpty()) { + v8::Local<v8::Context> context = script_state->GetContext(); + v8::Local<v8::Value> value = + v8::TryCatch::StackTrace(context, error).FromMaybe(error); + v8::Local<v8::String> value_string; + if (value->ToString(context).ToLocal(&value_string)) + return value_string; + } + + v8::Isolate* isolate = script_state->GetIsolate(); + return v8::String::NewFromUtf8Literal(isolate, "Unknown Failure"); +} + +class JavaScriptExecuteRequestForTestsHandler + : public GarbageCollected<JavaScriptExecuteRequestForTestsHandler> { + public: + class PromiseCallback : public ScriptFunction::Callable { + public: + PromiseCallback(JavaScriptExecuteRequestForTestsHandler& handler, + mojom::blink::JavaScriptExecutionResultType type) + : handler_(handler), type_(type) {} + + ScriptValue Call(ScriptState* script_state, ScriptValue value) override { + DCHECK(script_state); + if (type_ == mojom::blink::JavaScriptExecutionResultType::kSuccess) + handler_->SendSuccess(script_state, value.V8Value()); + else + handler_->SendException(script_state, value.V8Value()); + return {}; + } + + void Trace(Visitor* visitor) const override { + visitor->Trace(handler_); + ScriptFunction::Callable::Trace(visitor); + } + + private: + Member<JavaScriptExecuteRequestForTestsHandler> handler_; + const mojom::blink::JavaScriptExecutionResultType type_; + }; + + explicit JavaScriptExecuteRequestForTestsHandler( + LocalFrameMojoHandler::JavaScriptExecuteRequestForTestsCallback callback) + : callback_(std::move(callback)) {} + + ~JavaScriptExecuteRequestForTestsHandler() { + if (callback_) { + std::move(callback_).Run( + mojom::blink::JavaScriptExecutionResultType::kException, + base::Value( + "JavaScriptExecuteRequestForTestsHandler was destroyed without " + "running the callback. This is usually caused by Promise " + "resolution functions getting destroyed without being called.")); + } + } + + ScriptFunction* CreateResolveCallback(ScriptState* script_state, + LocalFrame* frame) { + return MakeGarbageCollected<ScriptFunction>( + script_state, + MakeGarbageCollected<PromiseCallback>( + *this, mojom::blink::JavaScriptExecutionResultType::kSuccess)); + } + + ScriptFunction* CreateRejectCallback(ScriptState* script_state, + LocalFrame* frame) { + return MakeGarbageCollected<ScriptFunction>( + script_state, + MakeGarbageCollected<PromiseCallback>( + *this, mojom::blink::JavaScriptExecutionResultType::kException)); + } + + void SendSuccess(ScriptState* script_state, v8::Local<v8::Value> value) { + SendResponse(script_state, + mojom::blink::JavaScriptExecutionResultType::kSuccess, value); + } + + void SendException(ScriptState* script_state, v8::Local<v8::Value> error) { + SendResponse(script_state, + mojom::blink::JavaScriptExecutionResultType::kException, + ErrorToString(script_state, error)); + } + + void Trace(Visitor* visitor) const {} + + private: + void SendResponse(ScriptState* script_state, + mojom::blink::JavaScriptExecutionResultType type, + v8::Local<v8::Value> value) { + std::unique_ptr<WebV8ValueConverter> converter = + Platform::Current()->CreateWebV8ValueConverter(); + converter->SetDateAllowed(true); + converter->SetRegExpAllowed(true); + + CHECK(callback_) << "Promise resolved twice"; + std::move(callback_).Run( + type, GetJavaScriptExecutionResult(value, script_state->GetContext(), + converter.get())); + } + + LocalFrameMojoHandler::JavaScriptExecuteRequestForTestsCallback callback_; +}; + } // namespace ActiveURLMessageFilter::~ActiveURLMessageFilter() { @@ -871,8 +980,9 @@ .ToLocal(&result)) { std::move(callback).Run({}); } else if (wants_result) { + v8::Local<v8::Context> context = MainWorldScriptContext(frame_); std::move(callback).Run( - GetJavaScriptExecutionResult(result, frame_, converter.get())); + GetJavaScriptExecutionResult(result, context, converter.get())); } else { std::move(callback).Run({}); } @@ -903,8 +1013,9 @@ converter->SetDateAllowed(true); converter->SetRegExpAllowed(true); + v8::Local<v8::Context> context = MainWorldScriptContext(frame_); std::move(callback).Run( - GetJavaScriptExecutionResult(result, frame_, converter.get())); + GetJavaScriptExecutionResult(result, context, converter.get())); } else { std::move(callback).Run({}); } @@ -915,8 +1026,8 @@ void LocalFrameMojoHandler::JavaScriptExecuteRequestForTests( const String& javascript, - bool wants_result, bool has_user_gesture, + bool resolve_promises, int32_t world_id, JavaScriptExecuteRequestForTestsCallback callback) { TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequestForTests", @@ -927,8 +1038,13 @@ if (has_user_gesture) NotifyUserActivation(mojom::blink::UserActivationNotificationType::kTest); - v8::HandleScope handle_scope(V8PerIsolateData::MainThreadIsolate()); - v8::Local<v8::Value> result; + v8::Isolate* isolate = ToIsolate(frame_); + ScriptState* script_state = + (world_id == DOMWrapperWorld::kMainWorldId) + ? ToScriptStateForMainWorld(frame_) + : ToScriptState(frame_, *DOMWrapperWorld::EnsureIsolatedWorld( + isolate, world_id)); + ScriptState::Scope script_state_scope(script_state); // `kDoNotSanitize` is used because this is only for tests and some tests // need `kDoNotSanitize` for dynamic imports. @@ -936,28 +1052,40 @@ javascript, ScriptSourceLocationType::kUnknown, SanitizeScriptErrors::kDoNotSanitize); - if (world_id == DOMWrapperWorld::kMainWorldId) { - result = - script->RunScriptAndReturnValue(DomWindow()).GetSuccessValueOrEmpty(); - } else { - CHECK_GT(world_id, DOMWrapperWorld::kMainWorldId); - CHECK_LT(world_id, DOMWrapperWorld::kDOMWrapperWorldEmbedderWorldIdLimit); - result = - script->RunScriptInIsolatedWorldAndReturnValue(DomWindow(), world_id) - .GetSuccessValueOrEmpty(); - } + ScriptEvaluationResult result = + script->RunScriptOnScriptStateAndReturnValue(script_state); - if (wants_result) { - std::unique_ptr<WebV8ValueConverter> converter = - Platform::Current()->CreateWebV8ValueConverter(); - converter->SetDateAllowed(true); - converter->SetRegExpAllowed(true); + auto* handler = MakeGarbageCollected<JavaScriptExecuteRequestForTestsHandler>( + std::move(callback)); + v8::Local<v8::Value> error; + switch (result.GetResultType()) { + case ScriptEvaluationResult::ResultType::kSuccess: { + v8::Local<v8::Value> value = result.GetSuccessValue(); + if (resolve_promises && !value.IsEmpty() && value->IsPromise()) { + ScriptPromise promise = ScriptPromise::Cast(script_state, value); + promise.Then(handler->CreateResolveCallback(script_state, frame_), + handler->CreateRejectCallback(script_state, frame_)); + } else { + handler->SendSuccess(script_state, value); + } + return; + } - std::move(callback).Run( - GetJavaScriptExecutionResult(result, frame_, converter.get())); - } else { - std::move(callback).Run({}); + case ScriptEvaluationResult::ResultType::kException: + error = result.GetExceptionForClassicForTesting(); + break; + + case ScriptEvaluationResult::ResultType::kAborted: + error = v8::String::NewFromUtf8Literal(isolate, "Script aborted"); + break; + + case ScriptEvaluationResult::ResultType::kNotRun: + error = v8::String::NewFromUtf8Literal(isolate, "Script not run"); + break; } + DCHECK_NE(result.GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); + handler->SendException(script_state, error); } void LocalFrameMojoHandler::JavaScriptExecuteRequestInIsolatedWorld(
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc index 224cfd8..cb186a7 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -205,11 +205,8 @@ // The process where this frame actually lives won't have sufficient // information to upgrade the url, since it won't have access to the // origin context. Do it now. - const FetchClientSettingsObject* fetch_client_settings_object = nullptr; - if (window) { - fetch_client_settings_object = - &window->Fetcher()->GetProperties().GetFetchClientSettingsObject(); - } + const FetchClientSettingsObject* fetch_client_settings_object = + &window->Fetcher()->GetProperties().GetFetchClientSettingsObject(); MixedContentChecker::UpgradeInsecureRequest( frame_request.GetResourceRequest(), fetch_client_settings_object, window, frame_request.GetFrameType(),
diff --git a/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/third_party/blink/renderer/core/fullscreen/fullscreen.cc index 5027aff..bc58535 100644 --- a/third_party/blink/renderer/core/fullscreen/fullscreen.cc +++ b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -709,9 +709,9 @@ LocalFrame& frame = *window.GetFrame(); frame.GetChromeClient().EnterFullscreen(frame, options, request_type); - // After the first fullscreen request, the user activation should be - // consumed, and the following fullscreen requests should receive an error. if (!for_cross_process_descendant) { + // Consume any transient user activation and delegated fullscreen token. + // AllowedToRequestFullscreen() enforces algorithm requirements earlier. LocalFrame::ConsumeTransientUserActivation(&frame); window.ConsumeFullscreenRequestToken(); }
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc index 869b1fb..7231b5e 100644 --- a/third_party/blink/renderer/core/input/event_handler.cc +++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -645,9 +645,6 @@ PhysicalRect cursor_rect(cursor_offset, LayoutSize(size)); if (!PhysicalRect(page->GetVisualViewport().VisibleContentRect()) .Contains(cursor_rect)) { - Deprecation::CountDeprecation( - node->GetExecutionContext(), - WebFeature::kCustomCursorIntersectsViewport); continue; } }
diff --git a/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc b/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc index d07131cd..0b40a08 100644 --- a/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc +++ b/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc
@@ -456,10 +456,6 @@ type = protocol::Audits::DeprecationIssueTypeEnum:: CSSSelectorInternalMediaControlsOverlayCastButton; break; - case DeprecationIssueType::kCustomCursorIntersectsViewport: - type = protocol::Audits::DeprecationIssueTypeEnum:: - CustomCursorIntersectsViewport; - break; case DeprecationIssueType::kDeprecationExample: type = protocol::Audits::DeprecationIssueTypeEnum::DeprecationExample; break;
diff --git a/third_party/blink/renderer/core/inspector/inspector_audits_issue.h b/third_party/blink/renderer/core/inspector/inspector_audits_issue.h index 7d2dbb2..221f57c 100644 --- a/third_party/blink/renderer/core/inspector/inspector_audits_issue.h +++ b/third_party/blink/renderer/core/inspector/inspector_audits_issue.h
@@ -48,7 +48,6 @@ kCrossOriginWindowAlert, kCrossOriginWindowConfirm, kCSSSelectorInternalMediaControlsOverlayCastButton, - kCustomCursorIntersectsViewport, kDeprecationExample, kDocumentDomainSettingWithoutOriginAgentClusterHeader, kEventPath,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h index c442d61..b2adb237 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
@@ -606,6 +606,13 @@ table_cell_column_index_ = table_cell_column_index; } + void SetTableSectionCollapsedBordersGeometry( + wtf_size_t start_row_index, + Vector<LayoutUnit>&& row_offsets) { + table_section_start_row_index_ = start_row_index; + table_section_row_offsets_ = std::move(row_offsets); + } + void TransferGridLayoutData( std::unique_ptr<NGGridLayoutData> grid_layout_data) { grid_layout_data_ = std::move(grid_layout_data); @@ -774,6 +781,8 @@ // Table cell specific types. absl::optional<wtf_size_t> table_cell_column_index_; + wtf_size_t table_section_start_row_index_; + Vector<LayoutUnit> table_section_row_offsets_; NGBlockBreakTokenData* break_token_data_ = nullptr;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc index 96b0a7ca..f2452911 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -197,7 +197,8 @@ !builder->table_column_geometries_.IsEmpty() || builder->table_collapsed_borders_ || builder->table_collapsed_borders_geometry_ || - builder->table_cell_column_index_; + builder->table_cell_column_index_ || + !builder->table_section_row_offsets_.IsEmpty(); wtf_size_t num_fragment_items = builder->ItemsBuilder() ? builder->ItemsBuilder()->Size() : 0; @@ -541,6 +542,10 @@ } if (builder->table_cell_column_index_) table_cell_column_index = *builder->table_cell_column_index_; + if (!builder->table_section_row_offsets_.IsEmpty()) { + table_section_start_row_index = builder->table_section_start_row_index_; + table_section_row_offsets = std::move(builder->table_section_row_offsets_); + } } NGPhysicalBoxFragment::RareData::RareData(const RareData& other) @@ -555,7 +560,9 @@ ? new NGTableFragmentData::CollapsedBordersGeometry( *other.table_collapsed_borders_geometry) : nullptr), - table_cell_column_index(other.table_cell_column_index) {} + table_cell_column_index(other.table_cell_column_index), + table_section_start_row_index(other.table_section_start_row_index), + table_section_row_offsets(other.table_section_row_offsets) {} const LayoutBox* NGPhysicalBoxFragment::OwnerLayoutBox() const { // TODO(layout-dev): We should probably get rid of this method, now that it
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h index ecd0300..a5f3f53 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -160,6 +160,23 @@ return ComputeRareDataAddress()->table_cell_column_index; } + absl::optional<wtf_size_t> TableSectionStartRowIndex() const { + DCHECK(IsTableNGSection()); + if (!const_has_rare_data_) + return absl::nullopt; + const auto* rare_data = ComputeRareDataAddress(); + if (rare_data->table_section_row_offsets.IsEmpty()) + return absl::nullopt; + return rare_data->table_section_start_row_index; + } + + const Vector<LayoutUnit>* TableSectionRowOffsets() const { + DCHECK(IsTableNGSection()); + return const_has_rare_data_ + ? &ComputeRareDataAddress()->table_section_row_offsets + : nullptr; + } + // Returns the layout-overflow for this fragment. const PhysicalRect LayoutOverflow() const { if (is_legacy_layout_root_) @@ -423,13 +440,19 @@ const std::unique_ptr<const NGMathMLPaintInfo> mathml_paint_info; - // TablesNG rare data. + // Table rare-data. PhysicalRect table_grid_rect; NGTableFragmentData::ColumnGeometries table_column_geometries; scoped_refptr<const NGTableBorders> table_collapsed_borders; std::unique_ptr<NGTableFragmentData::CollapsedBordersGeometry> table_collapsed_borders_geometry; + + // Table-cell rare-data. wtf_size_t table_cell_column_index; + + // Table-section rare-data. + wtf_size_t table_section_start_row_index; + Vector<LayoutUnit> table_section_row_offsets; }; const NGFragmentItems* ComputeItemsAddress() const {
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_constraint_space_data.h b/third_party/blink/renderer/core/layout/ng/table/ng_table_constraint_space_data.h index 005ce0c..4b1d817 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_constraint_space_data.h +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_constraint_space_data.h
@@ -154,6 +154,11 @@ const wtf_size_t new_start_row_index = new_section.start_row_index; const wtf_size_t old_start_row_index = old_section.start_row_index; + // Collapsed-border painting has a dependency on the row-index. + DCHECK_EQ(has_collapsed_borders, other.has_collapsed_borders); + if (has_collapsed_borders && new_start_row_index != old_start_row_index) + return false; + const wtf_size_t new_end_row_index = new_start_row_index + new_section.row_count; const wtf_size_t old_end_row_index =
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_fragment_data.h b/third_party/blink/renderer/core/layout/ng/table/ng_table_fragment_data.h index b5193e1..dc6a370 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_fragment_data.h +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_fragment_data.h
@@ -41,20 +41,17 @@ using ColumnGeometries = HeapVector<ColumnGeometry>; - // Column/row location is used for collapsed border painting. - // Only present if borders are collapsed. + // Column locations are used for collapsed-border painting. struct CollapsedBordersGeometry { USING_FAST_MALLOC(CollapsedBordersGeometry); public: - Vector<LayoutUnit> columns; // Column offsets from table grid border. - Vector<LayoutUnit> rows; // Row offsets from table grid border. + Vector<LayoutUnit> columns; #if DCHECK_IS_ON() void CheckSameForSimplifiedLayout( const CollapsedBordersGeometry& other) const { DCHECK(columns == other.columns); - DCHECK(rows == other.rows); } #endif };
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc index d06bb7d4..2088efd 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
@@ -778,28 +778,20 @@ } // Collapsed borders. if (!table_borders.IsEmpty()) { - LayoutUnit grid_inline_start = table_borders.TableBorder().inline_start; std::unique_ptr<NGTableFragmentData::CollapsedBordersGeometry> fragment_borders_geometry = std::make_unique<NGTableFragmentData::CollapsedBordersGeometry>(); - for (const auto& column : column_locations) { - fragment_borders_geometry->columns.push_back(column.offset + - grid_inline_start); - } + for (const auto& column : column_locations) + fragment_borders_geometry->columns.push_back(column.offset); DCHECK_NE(column_locations.size(), 0u); fragment_borders_geometry->columns.push_back( - column_locations.back().offset + column_locations.back().size + - grid_inline_start); - LayoutUnit row_offset = table_borders.TableBorder().block_start; - for (const auto& row : rows) { - fragment_borders_geometry->rows.push_back(row_offset); - row_offset += row.block_size; - } - fragment_borders_geometry->rows.push_back(row_offset); - // crbug.com/1179369 make sure dimensions of table_borders and - // fragment_borders_geometry are consistent. + column_locations.back().offset + column_locations.back().size); + + // Ensure the dimensions of table_borders and fragment_borders_geometry are + // consistent. DCHECK_LE(table_borders.EdgesPerRow() / 2, fragment_borders_geometry->columns.size()); + container_builder_.SetTableCollapsedBorders(table_borders); container_builder_.SetTableCollapsedBordersGeometry( std::move(fragment_borders_geometry));
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc index bbc5df62..d2c1cd1 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc
@@ -50,6 +50,9 @@ offset.block_offset, FragmentainerSpaceAtBfcStart(ConstraintSpace())); }; + Vector<LayoutUnit> row_offsets = {LayoutUnit()}; + wtf_size_t actual_start_row_index = 0u; + NGBlockChildIterator child_iterator(Node().FirstChild(), BreakToken(), /* calculate_child_idx */ true); for (auto entry = child_iterator.NextChild(); @@ -119,6 +122,13 @@ offset.block_offset += fragment.BlockSize(); is_first_non_collapsed_row &= is_row_collapsed; + if (table_data.has_collapsed_borders) { + // Determine the start row-index for this section. + if (row_offsets.size() == 1u) + actual_start_row_index = row_index; + row_offsets.emplace_back(offset.block_offset); + } + if (container_builder_.HasInflowChildBreakInside()) break; } @@ -142,6 +152,12 @@ container_builder_.SetBaseline(*section_baseline); container_builder_.SetIsTableNGPart(); + // Store the collapsed-borders row geometry on this section fragment. + if (table_data.has_collapsed_borders && row_offsets.size() > 1u) { + container_builder_.SetTableSectionCollapsedBordersGeometry( + actual_start_row_index, std::move(row_offsets)); + } + if (UNLIKELY(InvolvedInBlockFragmentation(container_builder_))) { NGBreakStatus status = FinishFragmentation( Node(), ConstraintSpace(), BorderPadding().block_end,
diff --git a/third_party/blink/renderer/core/paint/ng/ng_table_painters.cc b/third_party/blink/renderer/core/paint/ng/ng_table_painters.cc index 3fdfc3c..dbe7c34 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_table_painters.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_table_painters.cc
@@ -435,6 +435,31 @@ } } +namespace { + +bool IsFirstRowFragmented(const NGPhysicalBoxFragment& section) { + for (const auto& child : section.Children()) { + if (!child->IsTableNGRow()) + continue; + return !To<NGPhysicalBoxFragment>(*child).IsFirstForNode(); + } + return false; +} + +bool IsLastRowFragmented(const NGPhysicalBoxFragment& section) { + const auto children = section.Children(); + for (auto it = children.rbegin(); it != children.rend(); ++it) { + const auto& child = *it; + if (!child->IsTableNGRow()) + continue; + return child->BreakToken() && + !To<NGBlockBreakToken>(child->BreakToken())->IsAtBlockEnd(); + } + return false; +} + +} // namespace + void NGTablePainter::PaintCollapsedBorders(const PaintInfo& paint_info, const PhysicalOffset& paint_offset, const gfx::Rect& visual_rect) { @@ -452,102 +477,165 @@ return; DrawingRecorder recorder(paint_info.context, layout_table, paint_info.phase, visual_rect); - - PhysicalRect grid_paint_rect = fragment_.TableGridRect(); - grid_paint_rect.offset += paint_offset; - - WritingModeConverter grid_converter(fragment_.Style().GetWritingDirection(), - grid_paint_rect.size); - AutoDarkMode auto_dark_mode(PaintAutoDarkMode( fragment_.Style(), DarkModeFilter::ElementRole::kBackground)); - for (NGTableCollapsedEdge edge = NGTableCollapsedEdge(*collapsed_borders, 0); - edge.Exists(); ++edge) { - if (!edge.CanPaint()) + // We paint collapsed-borders section-by-section for fragmentation purposes. + // This means that we need to track the final row we've painted in each + // section to avoid double painting. + absl::optional<wtf_size_t> previous_painted_row_index; + + for (const auto& child : fragment_.Children()) { + if (!child->IsTableNGSection()) continue; - LayoutUnit inline_start; - LayoutUnit block_start; - LayoutUnit inline_size; - LayoutUnit block_size; - wtf_size_t table_row = edge.TableRow(); - wtf_size_t table_column = edge.TableColumn(); - if (edge.IsInlineAxis()) { - // crbug.com/1179369 This crash has been observed, but we have no - // reproducible case. - if (table_column + 1 >= collapsed_borders_geometry->columns.size()) { - NOTREACHED(); + const auto& section = To<NGPhysicalBoxFragment>(*child); + const absl::optional<wtf_size_t> section_start_row_index = + section.TableSectionStartRowIndex(); + if (!section_start_row_index) + continue; + + bool is_first_row_fragmented = IsFirstRowFragmented(section); + bool is_last_row_fragmented = IsLastRowFragmented(section); + + WritingModeConverter converter(fragment_.Style().GetWritingDirection(), + section.Size()); + + const auto& section_row_offsets = *section.TableSectionRowOffsets(); + const wtf_size_t start_edge_index = + *section_start_row_index * collapsed_borders->EdgesPerRow(); + + for (NGTableCollapsedEdge edge = + NGTableCollapsedEdge(*collapsed_borders, start_edge_index); + edge.Exists(); ++edge) { + const wtf_size_t table_row = edge.TableRow(); + const wtf_size_t table_column = edge.TableColumn(); + const wtf_size_t fragment_table_row = + table_row - *section_start_row_index; + + // Check if we've exhausted the rows in this section. Store the final row + // which we painted. + if (fragment_table_row >= section_row_offsets.size()) { + previous_painted_row_index = table_row - 1; + break; + } + + if (!edge.CanPaint()) continue; - } - inline_start = collapsed_borders_geometry->columns[table_column]; - inline_size = collapsed_borders_geometry->columns[table_column + 1] - - collapsed_borders_geometry->columns[table_column]; - block_size = edge.BorderWidth(); - CHECK_LT(table_row, collapsed_borders_geometry->rows.size()); - block_start = - collapsed_borders_geometry->rows[table_row] - edge.BorderWidth() / 2; - LogicalSize start_joint; - LogicalSize end_joint; - bool start_wins; - bool end_wins; - ComputeEdgeJoints(*collapsed_borders, edge, start_joint, end_joint, - start_wins, end_wins); - if (start_wins) { - inline_start -= start_joint.inline_size / 2; - inline_size += start_joint.inline_size / 2; - } else { - inline_start += start_joint.inline_size / 2; - inline_size -= start_joint.inline_size / 2; - } - if (end_wins) { - inline_size += end_joint.inline_size / 2; - } else { - inline_size -= end_joint.inline_size / 2; - } - } else { // block_axis - CHECK_LT(table_row + 1, collapsed_borders_geometry->rows.size()); - block_start = collapsed_borders_geometry->rows[table_row]; - block_size = - collapsed_borders_geometry->rows[table_row + 1] - block_start; - CHECK_LT(table_column, collapsed_borders_geometry->columns.size()); - inline_start = collapsed_borders_geometry->columns[table_column] - - edge.BorderWidth() / 2; - inline_size = edge.BorderWidth(); - LogicalSize start_joint; - LogicalSize end_joint; - bool start_wins; - bool end_wins; - ComputeEdgeJoints(*collapsed_borders, edge, start_joint, end_joint, - start_wins, end_wins); - if (start_wins) { - block_start -= start_joint.block_size / 2; - block_size += start_joint.block_size / 2; - } else { - block_start += start_joint.block_size / 2; - block_size -= start_joint.block_size / 2; - } - if (end_wins) { - block_size += end_joint.block_size / 2; - } else { - block_size -= end_joint.block_size / 2; - } - } - const LogicalRect logical_border_rect(inline_start, block_start, - inline_size, block_size); - PhysicalRect physical_border_rect = - grid_converter.ToPhysical(logical_border_rect); - physical_border_rect.offset += grid_paint_rect.offset; - BoxSide box_side; - if (IsHorizontalWritingMode(fragment_.Style().GetWritingMode())) { - box_side = edge.IsInlineAxis() ? BoxSide::kTop : BoxSide::kLeft; - } else { - box_side = edge.IsInlineAxis() ? BoxSide::kLeft : BoxSide::kTop; + bool is_row_start_fragmented = + is_first_row_fragmented && fragment_table_row == 0u; + + const LayoutUnit row_start_offset = + section_row_offsets[fragment_table_row]; + const LayoutUnit column_start_offset = + collapsed_borders_geometry->columns[table_column]; + + LayoutUnit inline_start; + LayoutUnit block_start; + LayoutUnit inline_size; + LayoutUnit block_size; + + if (edge.IsInlineAxis()) { + // NOTE: This crash has been observed, but we aren't able to find a + // reproducible testcase. See: crbug.com/1179369. + if (table_column + 1 >= collapsed_borders_geometry->columns.size()) { + NOTREACHED(); + continue; + } + + // Check if we have painted this inline border in a previous section. + if (previous_painted_row_index && + *previous_painted_row_index == table_row) { + continue; + } + + bool is_row_end_fragmented = + is_last_row_fragmented && + fragment_table_row == section_row_offsets.size() - 1u; + + // If the current row has been fragmented, omit the inline border. + if (is_row_start_fragmented || is_row_end_fragmented) + continue; + + inline_start = column_start_offset; + inline_size = collapsed_borders_geometry->columns[table_column + 1] - + column_start_offset; + block_size = edge.BorderWidth(); + block_start = row_start_offset - edge.BorderWidth() / 2; + LogicalSize start_joint; + LogicalSize end_joint; + bool start_wins; + bool end_wins; + ComputeEdgeJoints(*collapsed_borders, edge, start_joint, end_joint, + start_wins, end_wins); + if (start_wins) { + inline_start -= start_joint.inline_size / 2; + inline_size += start_joint.inline_size / 2; + } else { + inline_start += start_joint.inline_size / 2; + inline_size -= start_joint.inline_size / 2; + } + if (end_wins) { + inline_size += end_joint.inline_size / 2; + } else { + inline_size -= end_joint.inline_size / 2; + } + } else { // block_axis + // Check if this block border exists in this section. + if (fragment_table_row + 1 >= section_row_offsets.size()) + continue; + + bool is_row_end_fragmented = + is_last_row_fragmented && + fragment_table_row + 1u == section_row_offsets.size() - 1u; + + block_start = row_start_offset; + block_size = + section_row_offsets[fragment_table_row + 1] - row_start_offset; + inline_start = column_start_offset - edge.BorderWidth() / 2; + inline_size = edge.BorderWidth(); + LogicalSize start_joint; + LogicalSize end_joint; + bool start_wins; + bool end_wins; + ComputeEdgeJoints(*collapsed_borders, edge, start_joint, end_joint, + start_wins, end_wins); + if (is_row_start_fragmented) { + // We don't need to perform any adjustment if we've been start + // fragmented as there isn't a joint here. + } else if (start_wins) { + block_start -= start_joint.block_size / 2; + block_size += start_joint.block_size / 2; + } else { + block_start += start_joint.block_size / 2; + block_size -= start_joint.block_size / 2; + } + if (is_row_end_fragmented) { + // We don't need to perform any adjustment if we've been end + // fragmented as there isn't a joint here. + } else if (end_wins) { + block_size += end_joint.block_size / 2; + } else { + block_size -= end_joint.block_size / 2; + } + } + const LogicalRect logical_border_rect(inline_start, block_start, + inline_size, block_size); + PhysicalRect physical_border_rect = + converter.ToPhysical(logical_border_rect); + physical_border_rect.offset += child.offset + paint_offset; + + BoxSide box_side; + if (IsHorizontalWritingMode(fragment_.Style().GetWritingMode())) { + box_side = edge.IsInlineAxis() ? BoxSide::kTop : BoxSide::kLeft; + } else { + box_side = edge.IsInlineAxis() ? BoxSide::kLeft : BoxSide::kTop; + } + BoxBorderPainter::DrawBoxSide( + paint_info.context, ToPixelSnappedRect(physical_border_rect), + box_side, edge.BorderColor(), edge.BorderStyle(), auto_dark_mode); } - BoxBorderPainter::DrawBoxSide( - paint_info.context, ToPixelSnappedRect(physical_border_rect), box_side, - edge.BorderColor(), edge.BorderStyle(), auto_dark_mode); } }
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc index 420e6ff0..7ec8ee7 100644 --- a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc +++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
@@ -244,4 +244,7 @@ const blink::FrameToken& child_frame_token, const WTF::String& srcdoc_value) {} +void FakeLocalFrameHost::ReceivedDelegatedCapability( + blink::mojom::DelegatedCapability delegated_capability) {} + } // namespace blink
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.h b/third_party/blink/renderer/core/testing/fake_local_frame_host.h index 56f5693..93aef56 100644 --- a/third_party/blink/renderer/core/testing/fake_local_frame_host.h +++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.h
@@ -163,6 +163,8 @@ blink::mojom::PreferredColorScheme preferred_color_scheme) override; void DidChangeSrcDoc(const blink::FrameToken& child_frame_token, const WTF::String& srcdoc_value) override; + void ReceivedDelegatedCapability( + blink::mojom::DelegatedCapability delegated_capability) override; private: void BindFrameHostReceiver(mojo::ScopedInterfaceEndpointHandle handle);
diff --git a/third_party/blink/renderer/extensions/chromeos/BUILD.gn b/third_party/blink/renderer/extensions/chromeos/BUILD.gn index 3dc7524..c2bc0dbc 100644 --- a/third_party/blink/renderer/extensions/chromeos/BUILD.gn +++ b/third_party/blink/renderer/extensions/chromeos/BUILD.gn
@@ -9,7 +9,10 @@ assert(use_blink_extensions_chromeos) -visibility = [ "//third_party/blink/renderer/extensions/*" ] +visibility = [ + "//third_party/blink/renderer/bindings/extensions/*", + "//third_party/blink/renderer/extensions/*", +] config("extensions_chromeos_implementation") { visibility += [ "//third_party/blink/renderer/bindings/extensions/*" ] @@ -42,6 +45,7 @@ ] deps = [ + ":chromeos_events", "//third_party/blink/renderer/core", "//third_party/blink/renderer/extensions/chromeos/system_extensions/hid", "//third_party/blink/renderer/extensions/chromeos/system_extensions/window_management", @@ -51,3 +55,32 @@ public_deps = [ "//third_party/blink/renderer/bindings/extensions/v8:v8_chromeos" ] } + +group("make_chromeos_generated") { + public_deps = [ ":make_chromeos_generated_event_target_names" ] +} + +blink_chromeos_extensions_output_dir = "$blink_extensions_output_dir/chromeos" + +# make_names ------------------------------------------------------------------- +make_names("make_chromeos_generated_event_target_names") { + in_files = [ "event_target_chromeos_names.json5" ] + output_dir = blink_chromeos_extensions_output_dir +} + +blink_extensions_chromeos_sources("chromeos_events") { + sources = [ "event_target_chromeos.h" ] + public_deps = [ ":chromeos_generated" ] +} + +blink_extensions_chromeos_sources("chromeos_generated") { + # Targets from above that generate outputs that need to be compiled. + # All sources declared as outputs from these targets will be compiled + # into one target. + targets_generating_sources = [ ":make_chromeos_generated_event_target_names" ] + + sources = [] + foreach(current, targets_generating_sources) { + sources += get_target_outputs(current) + } +}
diff --git a/third_party/blink/renderer/extensions/chromeos/chromeos_extensions.cc b/third_party/blink/renderer/extensions/chromeos/chromeos_extensions.cc index 5b6d309..8957af2 100644 --- a/third_party/blink/renderer/extensions/chromeos/chromeos_extensions.cc +++ b/third_party/blink/renderer/extensions/chromeos/chromeos_extensions.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/bindings/extensions_chromeos/v8/v8_chrome_os.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/extensions/chromeos/chromeos.h" +#include "third_party/blink/renderer/extensions/chromeos/event_target_chromeos_names.h" #include "third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h" #include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h" #include "third_party/blink/renderer/platform/bindings/extensions_registry.h" @@ -48,6 +49,15 @@ void ChromeOSExtensions::Initialize() { ExtensionsRegistry::GetInstance().RegisterBlinkExtensionInstallCallback( &InstallChromeOSExtensions); + + // Static strings need to be initialized here, before + // CoreInitializer::Initialize(). + const unsigned kChromeOSStaticStringsCount = + event_target_names::kChromeOSNamesCount; + StringImpl::ReserveStaticStringsCapacityForSize( + kChromeOSStaticStringsCount + StringImpl::AllStaticStrings().size()); + + event_target_names::InitChromeOS(); } void ChromeOSExtensions::InitServiceWorkerGlobalScope(
diff --git a/third_party/blink/renderer/extensions/chromeos/event_target_chromeos.h b/third_party/blink/renderer/extensions/chromeos/event_target_chromeos.h new file mode 100644 index 0000000..6f886cb --- /dev/null +++ b/third_party/blink/renderer/extensions/chromeos/event_target_chromeos.h
@@ -0,0 +1,11 @@ +// Copyright 2022 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 THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_EVENT_TARGET_CHROMEOS_H_ +#define THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_EVENT_TARGET_CHROMEOS_H_ + +#include "third_party/blink/renderer/core/dom/events/event_target.h" +#include "third_party/blink/renderer/extensions/chromeos/event_target_chromeos_names.h" + +#endif // THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_EVENT_TARGET_CHROMEOS_H_
diff --git a/third_party/blink/renderer/extensions/chromeos/event_target_chromeos_names.json5 b/third_party/blink/renderer/extensions/chromeos/event_target_chromeos_names.json5 new file mode 100644 index 0000000..694931ea --- /dev/null +++ b/third_party/blink/renderer/extensions/chromeos/event_target_chromeos_names.json5
@@ -0,0 +1,12 @@ +{ + metadata: { + namespace: "event_target_names", + suffix: "ChromeOS", + }, + # You don't need to specify ImplementedAs even though an interface name and + # its C++ class name don't match. You need to specify ImplementedAs only if + # you'd like to change recorded names in ActivityLogger. + data: [ + "CrosWindowManagement", + ] +}
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/BUILD.gn b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/BUILD.gn index 0f9fac3..35acf1c 100644 --- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/BUILD.gn +++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/BUILD.gn
@@ -14,6 +14,7 @@ deps = [ "//third_party/blink/renderer/bindings:generate_bindings_all", + "//third_party/blink/renderer/extensions/chromeos:chromeos_events", "//third_party/blink/renderer/platform", "//v8", ]
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc index 3e46007a4e..9c6264fd 100644 --- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc +++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc
@@ -6,8 +6,10 @@ #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" +#include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" +#include "third_party/blink/renderer/extensions/chromeos/event_target_chromeos.h" #include "third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.h" namespace blink { @@ -53,10 +55,7 @@ } const WTF::AtomicString& CrosWindowManagement::InterfaceName() const { - // TODO(b/221130654): Move to event_target_names::kCrosWindowManagement. - DEFINE_STATIC_LOCAL(const AtomicString, kInterfaceName, - ("CrosWindowManagement")); - return kInterfaceName; + return event_target_names::kCrosWindowManagement; } ExecutionContext* CrosWindowManagement::GetExecutionContext() const { @@ -102,6 +101,10 @@ resolver->Resolve(results); } +void CrosWindowManagement::DispatchStartEvent() { + DispatchEvent(*Event::Create(event_type_names::kStart)); +} + void CrosWindowManagement::BindWindowManagerStartObserverImpl( mojo::PendingReceiver<mojom::blink::CrosWindowManagementStartObserver> receiver) {
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h index 8dbc24f..2910fb4e 100644 --- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h +++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h
@@ -50,6 +50,9 @@ void WindowsCallback(ScriptPromiseResolver* resolver, WTF::Vector<mojom::blink::CrosWindowInfoPtr> windows); + // mojom::blink::CrosWindowManagementObserver + void DispatchStartEvent() override; + private: void BindWindowManagerStartObserverImpl( mojo::PendingReceiver<mojom::blink::CrosWindowManagementStartObserver>
diff --git a/third_party/blink/renderer/extensions/extensions.gni b/third_party/blink/renderer/extensions/extensions.gni index 69b0dca..0a1c4c3 100644 --- a/third_party/blink/renderer/extensions/extensions.gni +++ b/third_party/blink/renderer/extensions/extensions.gni
@@ -31,6 +31,7 @@ deps = [ "//third_party/blink/renderer/core", + "//third_party/blink/renderer/extensions/chromeos:make_chromeos_generated", "//third_party/blink/renderer/modules", ] if (defined(invoker.deps)) {
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc index 079d85a..307e408 100644 --- a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc +++ b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "base/metrics/histogram_functions.h" #include "base/task/single_thread_task_runner.h" #include "mojo/public/cpp/base/big_buffer.h" #include "third_party/blink/public/common/features.h" @@ -554,8 +555,11 @@ return; } - if (!custom_format_items_.IsEmpty() && - !LocalFrame::HasTransientUserActivation(GetLocalFrame())) { + bool has_transient_user_activation = + LocalFrame::HasTransientUserActivation(GetLocalFrame()); + base::UmaHistogramBoolean("Blink.Clipboard.HasTransientUserActivation", + has_transient_user_activation); + if (!custom_format_items_.IsEmpty() && !has_transient_user_activation) { script_promise_resolver_->Reject(MakeGarbageCollected<DOMException>( DOMExceptionCode::kSecurityError, "Must be handling a user gesture to use custom clipboard"));
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc index 817b3f2..73e4f0f3 100644 --- a/third_party/blink/renderer/modules/modules_initializer.cc +++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -168,7 +168,8 @@ const unsigned kModulesStaticStringsCount = event_interface_names::kModulesNamesCount + event_target_names::kModulesNamesCount + indexed_db_names::kNamesCount; - StringImpl::ReserveStaticStringsCapacityForSize(kModulesStaticStringsCount); + StringImpl::ReserveStaticStringsCapacityForSize( + kModulesStaticStringsCount + StringImpl::AllStaticStrings().size()); event_interface_names::InitModules(); event_target_names::InitModules();
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.idl b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.idl index 1a254308..c423fbf 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.idl
@@ -9,7 +9,7 @@ [ Exposed=Window ] interface RTCEncodedAudioFrame { - readonly attribute unsigned long long timestamp; // RTP timestamp. + readonly attribute unsigned long timestamp; // RTP timestamp. attribute ArrayBuffer data; RTCEncodedAudioFrameMetadata getMetadata(); stringifier;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.idl b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.idl index 257fa31..c3517d0 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.idl
@@ -16,7 +16,7 @@ Exposed=Window ] interface RTCEncodedVideoFrame { readonly attribute RTCEncodedVideoFrameType type; - readonly attribute unsigned long long timestamp; // RTP timestamp. + readonly attribute unsigned long timestamp; // RTP timestamp. attribute ArrayBuffer data; RTCEncodedVideoFrameMetadata getMetadata(); stringifier;
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc index e62d134..89660662 100644 --- a/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc
@@ -26,6 +26,9 @@ return page_holder.release(); }(); + // Request a full GC upon returning. + auto scoped_gc = MakeScopedGarbageCollectionRequest(); + ScriptState* script_state = ToScriptStateForMainWorld(&page_holder->GetFrame()); ScriptState::Scope scope(script_state); @@ -48,15 +51,6 @@ // is memory-backed. // TODO(chcunningham): Wait for promise resolution. audio_data->copyTo(destination, options, IGNORE_EXCEPTION_FOR_TESTING); - - // Request a V8 GC. Oilpan will be invoked by the GC epilogue. - // - // Multiple GCs may be required to ensure everything is collected (due to - // a chain of persistent handles), so some objects may not be collected until - // a subsequent iteration. This is slow enough as is, so we compromise on one - // major GC, as opposed to the 5 used in V8GCController for unit tests. - V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting( - v8::Isolate::kFullGarbageCollection); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_decoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/audio_decoder_fuzzer.cc index 9e9fe0f..6fd6831 100644 --- a/third_party/blink/renderer/modules/webcodecs/audio_decoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/audio_decoder_fuzzer.cc
@@ -18,7 +18,6 @@ #include "third_party/blink/renderer/modules/webcodecs/fuzzer_utils.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_per_isolate_data.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -37,6 +36,9 @@ return page_holder.release(); }(); + // Request a full GC upon returning. + auto scoped_gc = MakeScopedGarbageCollectionRequest(); + // // NOTE: GC objects that need to survive iterations of the loop below // must be Persistent<>! @@ -112,15 +114,6 @@ } } } - - // Request a V8 GC. Oilpan will be invoked by the GC epilogue. - // - // Multiple GCs may be required to ensure everything is collected (due to - // a chain of persistent handles), so some objects may not be collected until - // a subsequent iteration. This is slow enough as is, so we compromise on one - // major GC, as opposed to the 5 used in V8GCController for unit tests. - V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting( - v8::Isolate::kFullGarbageCollection); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_encoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/audio_encoder_fuzzer.cc index 93094b8..14856d8 100644 --- a/third_party/blink/renderer/modules/webcodecs/audio_encoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/audio_encoder_fuzzer.cc
@@ -27,7 +27,6 @@ #include "third_party/blink/renderer/modules/webcodecs/fuzzer_utils.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_per_isolate_data.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -157,6 +156,9 @@ return page_holder.release(); }(); + // Request a full GC upon returning. + auto scoped_gc = MakeScopedGarbageCollectionRequest(); + // The platform audio encoder and some Image related classes that use // base::Singleton will expect this to exist for registering exit // callbacks (e.g. DarkModeImageClassifier). @@ -255,15 +257,6 @@ } } } - - // Request a V8 GC. Oilpan will be invoked by the GC epilogue. - // - // Multiple GCs may be required to ensure everything is collected (due to - // a chain of persistent handles), so some objects may not be collected until - // a subsequent iteration. This is slow enough as is, so we compromise on one - // major GC, as opposed to the 5 used in V8GCController for unit tests. - V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting( - v8::Isolate::kFullGarbageCollection); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc index f235e02af..1975a7ed 100644 --- a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc +++ b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include <string> +#include "base/callback_helpers.h" #include "media/base/limits.h" #include "media/base/sample_format.h" #include "third_party/blink/renderer/bindings/core/v8/script_function.h" @@ -37,7 +38,9 @@ #include "third_party/blink/renderer/platform/audio/audio_bus.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_per_isolate_data.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { @@ -52,6 +55,20 @@ } // namespace +base::ScopedClosureRunner MakeScopedGarbageCollectionRequest() { + return base::ScopedClosureRunner(WTF::Bind([]() { + // Request a V8 GC. Oilpan will be invoked by the GC epilogue. + // + // Multiple GCs may be required to ensure everything is collected (due to + // a chain of persistent handles), so some objects may not be collected + // until a subsequent iteration. This is slow enough as is, so we compromise + // on one major GC, as opposed to the 5 used in V8GCController for unit + // tests. + V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting( + v8::Isolate::kFullGarbageCollection); + })); +} + FakeFunction::FakeFunction(std::string name) : name_(std::move(name)) {} ScriptValue FakeFunction::Call(ScriptState*, ScriptValue) {
diff --git a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h index 0c70b7d..d472582 100644 --- a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h +++ b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h
@@ -25,11 +25,17 @@ #include <string> +namespace base { +class ScopedClosureRunner; +} + namespace blink { class DOMRectInit; class PlaneLayout; +base::ScopedClosureRunner MakeScopedGarbageCollectionRequest(); + class FakeFunction : public ScriptFunction::Callable { public: explicit FakeFunction(std::string name);
diff --git a/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc index 52b726d3..cc11f6c 100644 --- a/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc
@@ -24,7 +24,6 @@ #include "third_party/blink/renderer/modules/webcodecs/image_track_list.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_per_isolate_data.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -99,6 +98,9 @@ return page_holder.release(); }(); + // Request a full GC upon returning. + auto scoped_gc = MakeScopedGarbageCollectionRequest(); + base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature(features::kJXL); @@ -204,15 +206,8 @@ } } - // Request a V8 GC. Oilpan will be invoked by the GC epilogue. - // - // Multiple GCs may be required to ensure everything is collected (due to - // a chain of persistent handles), so some objects may not be collected until - // a subsequent iteration. This is slow enough as is, so we compromise on one - // major GC, as opposed to the 5 used in V8GCController for unit tests. + // Give other tasks a chance to run before we GC. base::RunLoop().RunUntilIdle(); - V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting( - v8::Isolate::kFullGarbageCollection); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc index de3d474..75b31a9 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc
@@ -18,7 +18,6 @@ #include "third_party/blink/renderer/modules/webcodecs/video_decoder.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_per_isolate_data.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -37,6 +36,9 @@ return page_holder.release(); }(); + // Request a full GC upon returning. + auto scoped_gc = MakeScopedGarbageCollectionRequest(); + // // NOTE: GC objects that need to survive iterations of the loop below // must be Persistent<>! @@ -112,15 +114,6 @@ } } } - - // Request a V8 GC. Oilpan will be invoked by the GC epilogue. - // - // Multiple GCs may be required to ensure everything is collected (due to - // a chain of persistent handles), so some objects may not be collected until - // a subsequent iteration. This is slow enough as is, so we compromise on one - // major GC, as opposed to the 5 used in V8GCController for unit tests. - V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting( - v8::Isolate::kFullGarbageCollection); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc index 2be9804..d431fb06 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc
@@ -19,7 +19,6 @@ #include "third_party/blink/renderer/modules/webcodecs/video_encoder.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_per_isolate_data.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -40,6 +39,9 @@ return page_holder.release(); }(); + // Request a full GC upon returning. + auto scoped_gc = MakeScopedGarbageCollectionRequest(); + // Some Image related classes that use base::Singleton will expect this to // exist for registering exit callbacks (e.g. DarkModeImageClassifier). base::AtExitManager exit_manager; @@ -130,15 +132,6 @@ } } } - - // Request a V8 GC. Oilpan will be invoked by the GC epilogue. - // - // Multiple GCs may be required to ensure everything is collected (due to - // a chain of persistent handles), so some objects may not be collected until - // a subsequent iteration. This is slow enough as is, so we compromise on one - // major GC, as opposed to the 5 used in V8GCController for unit tests. - V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting( - v8::Isolate::kFullGarbageCollection); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc index d088963..4580666 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc
@@ -28,6 +28,9 @@ return page_holder.release(); }(); + // Request a full GC upon returning. + auto scoped_gc = MakeScopedGarbageCollectionRequest(); + ScriptState* script_state = ToScriptStateForMainWorld(&page_holder->GetFrame()); ScriptState::Scope scope(script_state); @@ -62,15 +65,6 @@ // TODO(sandersd): Wait for promise resolution. video_frame->copyTo(script_state, destination, options, IGNORE_EXCEPTION_FOR_TESTING); - - // Request a V8 GC. Oilpan will be invoked by the GC epilogue. - // - // Multiple GCs may be required to ensure everything is collected (due to - // a chain of persistent handles), so some objects may not be collected until - // a subsequent iteration. This is slow enough as is, so we compromise on one - // major GC, as opposed to the 5 used in V8GCController for unit tests. - V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting( - v8::Isolate::kFullGarbageCollection); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/font_family.cc b/third_party/blink/renderer/platform/fonts/font_family.cc index feab496..36a9ba4 100644 --- a/third_party/blink/renderer/platform/fonts/font_family.cc +++ b/third_party/blink/renderer/platform/fonts/font_family.cc
@@ -49,6 +49,14 @@ return true; } +wtf_size_t FontFamily::CountNames() const { + wtf_size_t count = 0; + for (const FontFamily* font_family = this; font_family; + font_family = font_family->Next()) + ++count; + return count; +} + void FontFamily::AppendFamily(AtomicString family_name, Type family_type) { scoped_refptr<SharedFontFamily> appended_family = SharedFontFamily::Create(); appended_family->SetFamily(family_name, family_type);
diff --git a/third_party/blink/renderer/platform/fonts/font_family.h b/third_party/blink/renderer/platform/fonts/font_family.h index fa45a6d7..e71bfff 100644 --- a/third_party/blink/renderer/platform/fonts/font_family.h +++ b/third_party/blink/renderer/platform/fonts/font_family.h
@@ -57,6 +57,9 @@ const AtomicString& FamilyName() const { return family_name_; } bool FamilyIsGeneric() const { return family_type_ == Type::kGenericFamily; } + // Returns number of linked `FontFamily` including `this`, so return value is + // greater than or equal to 1. When `Next()` is `nullptr`, return value is 1. + wtf_size_t CountNames() const; const FontFamily* Next() const; void AppendFamily(scoped_refptr<SharedFontFamily>);
diff --git a/third_party/blink/renderer/platform/fonts/font_family_test.cc b/third_party/blink/renderer/platform/fonts/font_family_test.cc index d8d4d91..98ef231 100644 --- a/third_party/blink/renderer/platform/fonts/font_family_test.cc +++ b/third_party/blink/renderer/platform/fonts/font_family_test.cc
@@ -21,6 +21,27 @@ } // namespace +TEST(FontFamilyTest, CountNames) { + { + FontFamily family; + EXPECT_EQ(1u, family.CountNames()); + } + { + FontFamily family; + family.SetFamily("A", FontFamily::Type::kFamilyName); + CreateAndAppendFamily(family, "B", FontFamily::Type::kFamilyName); + EXPECT_EQ(2u, family.CountNames()); + } + { + FontFamily family; + family.SetFamily("A", FontFamily::Type::kFamilyName); + FontFamily* b_family = + CreateAndAppendFamily(family, "B", FontFamily::Type::kFamilyName); + CreateAndAppendFamily(*b_family, "C", FontFamily::Type::kFamilyName); + EXPECT_EQ(3u, family.CountNames()); + } +} + TEST(FontFamilyTest, ToString) { { FontFamily family;
diff --git a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc index b7a22ee..0a54857 100644 --- a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc +++ b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc
@@ -5,8 +5,10 @@ #include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h" #include "components/viz/common/gpu/raster_context_provider.h" +#include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" +#include "gpu/command_buffer/client/raster_interface.h" #include "gpu/command_buffer/client/shared_image_interface.h" #include "media/base/video_frame.h" #include "media/renderers/video_frame_rgba_to_yuva_converter.h" @@ -139,22 +141,48 @@ return false; #endif // BUILDFLAG(IS_WIN) - scoped_refptr<media::VideoFrame> dst_frame = - pool_->MaybeCreateVideoFrame(src_size, dst_color_space); + auto dst_frame = pool_->MaybeCreateVideoFrame(src_size, dst_color_space); if (!dst_frame) return false; - gpu::SyncToken copy_done_sync_token; + auto* ri = raster_context_provider->RasterInterface(); + DCHECK(ri); + unsigned query_id = 0; + ri->GenQueriesEXT(1, &query_id); + ri->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query_id); + const bool copy_succeeded = media::CopyRGBATextureToVideoFrame( raster_context_provider, src_format, src_size, src_color_space, - src_surface_origin, src_mailbox_holder, dst_frame.get(), - copy_done_sync_token); + src_surface_origin, src_mailbox_holder, dst_frame.get()); if (!copy_succeeded) return false; IgnoreResult(failure_runner.Release()); - raster_context_provider->ContextSupport()->SignalSyncToken( - copy_done_sync_token, base::BindOnce(std::move(callback), dst_frame)); + auto on_query_done_cb = + [](scoped_refptr<media::VideoFrame> frame, + base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper> ctx_wrapper, + unsigned query_id, FrameReadyCallback callback) { + if (ctx_wrapper) { + if (auto* ctx_provider = ctx_wrapper->ContextProvider()) { + if (auto* ri_provider = ctx_provider->RasterContextProvider()) { + auto* ri = ri_provider->RasterInterface(); + ri->DeleteQueriesEXT(1, &query_id); + } + } + } + std::move(callback).Run(std::move(frame)); + }; + + // QueryEXT functions are used to make sure that CopyRGBATextureToVideoFrame() + // texture copy before we access GMB data. + ri->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); + auto* context_support = raster_context_provider->ContextSupport(); + DCHECK(context_support); + context_support->SignalQuery( + query_id, + base::BindOnce(on_query_done_cb, dst_frame, weak_context_provider_, + query_id, std::move(callback))); + return true; }
diff --git a/third_party/blink/renderer/platform/image-decoders/avif/OWNERS b/third_party/blink/renderer/platform/image-decoders/avif/OWNERS new file mode 100644 index 0000000..6be2ef7 --- /dev/null +++ b/third_party/blink/renderer/platform/image-decoders/avif/OWNERS
@@ -0,0 +1,2 @@ +dalecurtis@chromium.org +wtc@google.com
diff --git a/third_party/blink/renderer/platform/media/web_media_player_impl.cc b/third_party/blink/renderer/platform/media/web_media_player_impl.cc index 8ff836d..ee6dbd0 100644 --- a/third_party/blink/renderer/platform/media/web_media_player_impl.cc +++ b/third_party/blink/renderer/platform/media/web_media_player_impl.cc
@@ -1461,6 +1461,7 @@ GetCurrentFrameFromCompositor(); last_frame_request_time_ = tick_clock_->NowTicks(); video_frame_readback_count_++; + pipeline_controller_->OnExternalVideoFrameRequest(); video_renderer_.Paint( video_frame, canvas, gfx::RectF(rect), flags, @@ -1471,6 +1472,7 @@ scoped_refptr<media::VideoFrame> WebMediaPlayerImpl::GetCurrentFrame() { last_frame_request_time_ = tick_clock_->NowTicks(); video_frame_readback_count_++; + pipeline_controller_->OnExternalVideoFrameRequest(); return GetCurrentFrameFromCompositor(); }
diff --git a/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc b/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc index 73bf7672..4e337d8a 100644 --- a/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc +++ b/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
@@ -262,11 +262,10 @@ } if (dst_frame) { - gpu::SyncToken copy_done_sync_token; const bool copy_succeeded = media::CopyRGBATextureToVideoFrame( raster_context_provider.get(), format, source_frame->coded_size(), source_frame->ColorSpace(), origin, source_frame->mailbox_holder(0), - dst_frame.get(), copy_done_sync_token); + dst_frame.get()); if (copy_succeeded) { // CopyRGBATextureToVideoFrame() operates on mailboxes and not frames, // so we must manually copy over properties relevant to the encoder. @@ -284,8 +283,10 @@ dst_frame->set_timestamp(source_frame->timestamp()); dst_frame->set_metadata(source_frame->metadata()); - // TODO(crbug.com/1224279): We should remove this wait by internalizing - // it into VideoFrame::Map(). + // RI::Finish() makes sure that CopyRGBATextureToVideoFrame() finished + // texture copy before we call ConstructVideoFrameFromGpu(). It's not + // the best way to wait for completion, but it's the only sync way + // to wait, and making this function async is currently impractical. raster_context_provider->RasterInterface()->Finish(); auto vf = ConstructVideoFrameFromGpu(std::move(dst_frame)); return vf;
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng index 85e53a5..78fce2c 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng +++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -13,6 +13,8 @@ # Tests that fail in legacy but pass in NG # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] +crbug.com/626703 virtual/wasm-csp/external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] crbug.com/626703 external/wpt/css/css-writing-modes/abs-pos-border-offset-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/abs-pos-border-offset-002.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/abs-pos-vlr-border-001.html [ Failure ]
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials index ac5243e..6858146 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials +++ b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
@@ -44,6 +44,8 @@ crbug.com/1209223 external/wpt/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-security-check-same-origin-domain.sub.html [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] +crbug.com/626703 virtual/wasm-csp/external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] crbug.com/626703 external/wpt/fetch/metadata/generated/css-images.https.sub.tentative.html [ Timeout ] crbug.com/626703 external/wpt/fetch/metadata/generated/css-images.sub.tentative.html [ Timeout ] crbug.com/626703 external/wpt/fetch/metadata/generated/element-link-icon.https.sub.html [ Timeout ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 98718f9..641a5d3 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1608,6 +1608,9 @@ virtual/layout_ng_table_frag/external/wpt/css/css-break/table/break-before-table-cell-child.html [ Pass ] virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-cell-expansion-003.html [ Pass ] virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-col-paint-htb-ltr.html [ Pass ] +virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-collapsed-borders-paint-htb-ltr.html [ Pass ] +virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-collapsed-borders-paint-vlr-rtl.html [ Pass ] +virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-collapsed-borders-paint-vrl-ltr.html [ Pass ] virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-row-paint-vlr-rtl.html [ Pass ] virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-row-paint-vrl-rtl.html [ Pass ] virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-section-paint-vrl-rtl.html [ Pass ] @@ -3246,6 +3249,16 @@ crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Linux ] external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] +crbug.com/626703 [ Mac10.15 ] external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] +crbug.com/626703 [ Mac11 ] external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] +crbug.com/626703 [ Win ] external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] +crbug.com/626703 [ Linux ] virtual/wasm-csp/external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] +crbug.com/626703 [ Mac10.15 ] virtual/wasm-csp/external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] +crbug.com/626703 [ Mac11 ] virtual/wasm-csp/external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] +crbug.com/626703 [ Mac11-arm64 ] virtual/wasm-csp/external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] +crbug.com/626703 [ Win ] virtual/wasm-csp/external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ] crbug.com/626703 [ Win11 ] external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-per-origin-ids.sub.https.html [ Failure Timeout ] crbug.com/626703 [ Win11 ] external/wpt/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html [ Timeout ] crbug.com/626703 [ Win11 ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-per-origin-ids.sub.https.html [ Failure Timeout ] @@ -3875,6 +3888,9 @@ crbug.com/1078927 external/wpt/css/css-break/table/break-before-table-cell-child.html [ Failure ] crbug.com/1078927 external/wpt/css/css-break/table/table-cell-expansion-003.html [ Failure ] crbug.com/1078927 external/wpt/css/css-break/table/table-col-paint-htb-ltr.html [ Failure ] +crbug.com/1078927 external/wpt/css/css-break/table/table-collapsed-borders-paint-htb-ltr.html [ Failure ] +crbug.com/1078927 external/wpt/css/css-break/table/table-collapsed-borders-paint-vlr-rtl.html [ Failure ] +crbug.com/1078927 external/wpt/css/css-break/table/table-collapsed-borders-paint-vrl-ltr.html [ Failure ] crbug.com/1078927 external/wpt/css/css-break/table/table-row-paint-vlr-rtl.html [ Failure ] crbug.com/1078927 external/wpt/css/css-break/table/table-row-paint-vrl-rtl.html [ Failure ] crbug.com/1078927 external/wpt/css/css-break/table/table-section-paint-vrl-rtl.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version index 0cc502b89..9472ce5 100644 --- a/third_party/blink/web_tests/external/Version +++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@ -Version: f84b1101de028a8a26acd28fba772f595e94454e +Version: 5f3c4872a168e983f9310845ce739ef8e356584f
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 260fbd4..a42439d 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -143695,6 +143695,100 @@ {} ] ], + "overflow-clip-margin-mul-column-border-box.html": [ + "a0a1e895a66fa27a4ec95d115d646c0881e8da31", + [ + null, + [ + [ + "/css/css-overflow/overflow-clip-margin-mul-column-border-box-ref.html", + "==" + ] + ], + {} + ] + ], + "overflow-clip-margin-mul-column-content-box.html": [ + "26c081e04c8010dadc972dadcc74284a39e7cf8a", + [ + null, + [ + [ + "/css/css-overflow/overflow-clip-margin-mul-column-content-box-ref.html", + "==" + ] + ], + {} + ] + ], + "overflow-clip-margin-mul-column-padding-box.html": [ + "e3b3700608b4e1256481477db436d82bb3bf4528", + [ + null, + [ + [ + "/css/css-overflow/overflow-clip-margin-mul-column-padding-box-ref.html", + "==" + ] + ], + {} + ] + ], + "overflow-clip-margin-visual-box-and-value-with-border-radius.html": [ + "06ddb5c1630340d39af7cd2c35146910d5e5bcfc", + [ + null, + [ + [ + "/css/css-overflow/overflow-clip-margin-visual-box-and-value-with-border-radius-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 5 + ], + [ + 0, + 100 + ] + ] + ] + ] + } + ] + ], + "overflow-clip-margin-visual-box-and-value.html": [ + "cfef43481446054671348ce5582438aaa10a7f3a", + [ + null, + [ + [ + "/css/css-overflow/overflow-clip-margin-visual-box-and-value-ref.html", + "==" + ] + ], + {} + ] + ], + "overflow-clip-margin-visual-box.html": [ + "db2c17fcc39cb057616a137d76b1fd12939d0127", + [ + null, + [ + [ + "/css/css-overflow/overflow-clip-margin-visual-box-ref.html", + "==" + ] + ], + {} + ] + ], "overflow-ellipsis-dynamic-001.html": [ "2a9edba9308bf06009d7b9a27f21f1e0f1a231c7", [ @@ -209034,6 +209128,32 @@ ] }, "css-writing-modes": { + "abs-pos-border-offset-001.html": [ + "f7b7375bdf085c7072e73bee190c7183a7adf701", + [ + null, + [ + [ + "/css/css-writing-modes/abs-pos-border-offset-001-ref.html", + "==" + ] + ], + {} + ] + ], + "abs-pos-border-offset-002.html": [ + "a954a567331dcbaaf43c3c61413dd2b113f207f3", + [ + null, + [ + [ + "/css/css-writing-modes/abs-pos-border-offset-002-ref.html", + "==" + ] + ], + {} + ] + ], "abs-pos-non-replaced-icb-vlr-003.xht": [ "dea0f93355843cb66a111b01a4b0644060132e04", [ @@ -212375,6 +212495,32 @@ {} ] ], + "abs-pos-vlr-border-001.html": [ + "795bd972d452ce85d9a62c47ffa2e12133fed582", + [ + null, + [ + [ + "/css/css-writing-modes/abs-pos-vlr-border-001-ref.html", + "==" + ] + ], + {} + ] + ], + "abs-pos-vlr-padding-001.html": [ + "209cce14d2e1065a955f5403e1ff6053a0a7e67f", + [ + null, + [ + [ + "/css/css-writing-modes/abs-pos-vlr-padding-001-ref.html", + "==" + ] + ], + {} + ] + ], "abs-pos-with-replaced-child.html": [ "c68de4fb57b32f810ab1668d98d27e0209428a0e", [ @@ -250382,7 +250528,17 @@ "script-src-wasm-unsafe-eval-allows-wasm.any.js.headers": [ "3463403572752de8ea928bd924378fe74b37aa52", [] - ] + ], + "support": { + "iframe.html": [ + "4d8b937558a9290c9ecc1de73c747ac9508d1507", + [] + ], + "iframe.html.headers": [ + "bc3a72a880db1bfc0ba930a2d663b666fe618656", + [] + ] + } }, "webrtc": { "webrtc.js": [ @@ -277641,6 +277797,30 @@ "1ec2a5ce0a21c8dd578b3fcfde702307e4e2a9a8", [] ], + "overflow-clip-margin-mul-column-border-box-ref.html": [ + "98de614875ed30e0a99cb9771ee50ed749ade6b8", + [] + ], + "overflow-clip-margin-mul-column-content-box-ref.html": [ + "be5e46e341faa5475253704c3de092656ae4abce", + [] + ], + "overflow-clip-margin-mul-column-padding-box-ref.html": [ + "3cfa1a7eba3f724377530ec032c757029823e5e3", + [] + ], + "overflow-clip-margin-visual-box-and-value-ref.html": [ + "000e12ad1bf1d2ddb291d67adbb0d816c9edb822", + [] + ], + "overflow-clip-margin-visual-box-and-value-with-border-radius-ref.html": [ + "84b845fb5c74453801884661e4899c2666b9e112", + [] + ], + "overflow-clip-margin-visual-box-ref.html": [ + "5a265c7a73978fdf7e84fbfbf72e2593433cd264", + [] + ], "overflow-scroll-big-border-small-content-ref.html": [ "c7ea1807443ef1b2d454edd547e65c89a59cea16", [] @@ -289347,6 +289527,14 @@ "53463b38f4154029f9fadf7c337119f9828f57b4", [] ], + "abs-pos-border-offset-001-ref.html": [ + "18a54a41b8b9b9fae5c8c72359a2f2a1cabf8a48", + [] + ], + "abs-pos-border-offset-002-ref.html": [ + "98ec0d0c708407179339ee48bec3cbae86777699", + [] + ], "abs-pos-non-replaced-icb-vrl-004-ref.xht": [ "8153a72aff210565ae77aaaaa2fc8cfe4dd03029", [] @@ -289407,6 +289595,14 @@ "35f8d909c9cdae7e7df11b7ee25e792b212ea502", [] ], + "abs-pos-vlr-border-001-ref.html": [ + "e4098f1dd4574c65d3cbdf56e8d4dd1a0a15f448", + [] + ], + "abs-pos-vlr-padding-001-ref.html": [ + "6a941ff6407fc610681f674b67504492e8433e6d", + [] + ], "astral-bidi": { "adlam-ref.html": [ "d039127044e0bc9744bc358441da559cdd73bf81", @@ -300045,10 +300241,6 @@ [] ], "anonymous-iframe": { - "anonymous-window.tentative.https.js": [ - "14ea26dab5bcf069e8b4d1179b4a3754b0865bf6", - [] - ], "require-corp-embed-anonymous-iframe.tentative.https.window.js.headers": [ "6604450991a122e3e241e40b1b9e0516c525389d", [] @@ -304522,10 +304714,6 @@ [] ], "render-blocking": { - "header-inserted-preload-link.tentative.html.headers": [ - "77399147c4c15310c2140752a0361e50730ef03e", - [] - ], "support": { "dummy-1.js": [ "597772cf641d83b41f0e4238a1fa74a050f29d3c", @@ -304535,18 +304723,6 @@ "9b85a21033e92389cf43e11f5fb97d6d4139f9d2", [] ], - "font-with-preload-link-header.css": [ - "ba0b24be2deaf9f34d4aab9ac2cf9961985866cb", - [] - ], - "font-with-preload-link-header.css.headers": [ - "77399147c4c15310c2140752a0361e50730ef03e", - [] - ], - "subframe-render-blocking-preload.html": [ - "31734b9bbc733de8db4e8b93070ceaf73b1823c2", - [] - ], "target-red.css": [ "a387acd4ecb17a0a0419fb5b3c90a1f0b2f1b0ea", [] @@ -363744,6 +363920,13 @@ } ] ], + "postMessage-wasm-module.html": [ + "9d5e1e0ff326f5607421706a01a6766b05a83a8d", + [ + null, + {} + ] + ], "script-src-blocks-wasm.any.js": [ "15e9d87ce9e0920472b4302f813df0ab0e79ed43", [ @@ -370240,6 +370423,13 @@ {} ] ], + "container-units-svglength.html": [ + "8bb227c0498941222275c024b2707fd089639624", + [ + null, + {} + ] + ], "container-units-typed-om.html": [ "6da3306fdfa3e88dde176d43c81813c3959a0306", [ @@ -379447,6 +379637,20 @@ {} ] ], + "overflow-clip-margin-computed.html": [ + "17f271b37034cdfe6f5b560a37473498bb672272", + [ + null, + {} + ] + ], + "overflow-clip-margin.html": [ + "bfa41285558f2bab20abefc80d535543056daea9", + [ + null, + {} + ] + ], "overflow-computed.html": [ "563d1b31d259c650935684b727544e75960b0444", [ @@ -390267,6 +390471,13 @@ {} ] ], + "overflow-clip-margin.html": [ + "d11964136450c3db199988d27a97b962c59bb751", + [ + null, + {} + ] + ], "overflow-wrap.html": [ "0a7bcc7ac303631b8b005fecf9e10b5e30a5c289", [ @@ -430429,7 +430640,7 @@ "fullscreen": { "api": { "delegate-request.https.sub.tentative.html": [ - "3760461d15dd41b778e9063d9f12d2250c4a6235", + "37e0099e6a8692ac24a531814cd3324c0b71e8d5", [ null, { @@ -431285,6 +431496,28 @@ } ] ], + "anonymous-window.tentative.https.window.js": [ + "a2ff8d8dbfb5988ebb53c2e24f1667315143b8f8", + [ + "html/anonymous-iframe/anonymous-window.tentative.https.window.html", + { + "script_metadata": [ + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "/common/dispatcher/dispatcher.js" + ], + [ + "script", + "/html/cross-origin-embedder-policy/credentialless/resources/common.js" + ] + ] + } + ] + ], "cache-storage.tentative.https.window.js": [ "8ce6410290a63bd234f3c8a2dd8a0e19c36c3300", [ @@ -431486,7 +431719,7 @@ ] ], "initial-empty-document.tentative.https.window.js": [ - "b4d4d5191a2985a5da4578552b9c04bfc2486234", + "4d9d00b55b2caabba4ea7953f855392e6f9304dd", [ "html/anonymous-iframe/initial-empty-document.tentative.https.window.html", { @@ -458333,20 +458566,6 @@ {} ] ], - "header-inserted-preload-link.tentative.html": [ - "12eda1de2cd4d01ec39221501ce5653c0350625b", - [ - null, - {} - ] - ], - "invalid-render-blocking-preload-link.html": [ - "a640f72e6feaf0288440a15a4ffb42ee50fdf59e", - [ - null, - {} - ] - ], "non-render-blocking-scripts.optional.html": [ "a4c32ea037b7b47490c54ddd7616b88bfebcdc76", [ @@ -458382,20 +458601,6 @@ {} ] ], - "parser-inserted-modulepreload-link.tentative.html": [ - "70fbac6d3ba18127f7040d2bc00b579a81c914e7", - [ - null, - {} - ] - ], - "parser-inserted-preload-link.tentative.html": [ - "827985d71a8a92e64a3bded1463e6d247d3d0f79", - [ - null, - {} - ] - ], "parser-inserted-style-element.tentative.html": [ "9a358aa4938e762b31b43fb38381a763c2222c33", [ @@ -458432,14 +458637,14 @@ ] ], "remove-attr-unblocks-rendering.optional.html": [ - "e7b75f5c139893606f1351c2f6f473263f4b3880", + "c73e3c6452b5acbc6546b182ccd94687aa7a2e22", [ null, {} ] ], "remove-element-unblocks-rendering.optional.html": [ - "8ab44cdb9d8bb5ddde06c4f5aa43aacafa103456", + "ad49c48c2e0d2332521ec660f5478b1a59dffa0c", [ null, {} @@ -458452,15 +458657,6 @@ {} ] ], - "render-blocked-apis-by-preload-link.tentative.html": [ - "07827371be7cacff976c2dc0ac893db977b16d38", - [ - null, - { - "testdriver": true - } - ] - ], "script-inserted-module-script.tentative.html": [ "73f0d3cdf4f2223530dcaf4e48fbf0f5034410cd", [ @@ -458468,20 +458664,6 @@ {} ] ], - "script-inserted-modulepreload-link.tentative.html": [ - "67c79f01bfec48ac795d4e8ef4ae1f8b9c4c4e98", - [ - null, - {} - ] - ], - "script-inserted-preload-link.tentative.html": [ - "a96e223d623cd89b2c907fed6d52f0b30552fedf", - [ - null, - {} - ] - ], "script-inserted-script.html": [ "faf346b4ddaa37a090b97225ef89ef2e96a9233b", [ @@ -458502,13 +458684,6 @@ null, {} ] - ], - "stylesheet-header-inserted-preload-link.tentative.html": [ - "6ad9ddb1cd1cdcee10fdad792f7dd0629c7f220d", - [ - null, - {} - ] ] }, "self-origin.any.js": [ @@ -511585,17 +511760,17 @@ ] }, "sanitizer-api": { - "element-set-sanitized-html.https.tentative.html": [ + "element-set-sanitized-html.https.html": [ "560e9cd63523287bacafa1b23a2ab3ea4bd21288", [ null, {} ] ], - "idlharness.https.tentative.window.js": [ + "idlharness.https.window.js": [ "384317b8e55bd318464c68e20ca737bfb5b2c966", [ - "sanitizer-api/idlharness.https.tentative.window.html", + "sanitizer-api/idlharness.https.window.html", { "script_metadata": [ [ @@ -511610,21 +511785,21 @@ } ] ], - "sanitizer-config.https.tentative.html": [ - "fb29631e33ba184990b4e131e91171ba8a98ec89", + "sanitizer-config.https.html": [ + "4faa156ead3b152f92d102c23e2a575837d293f4", [ null, {} ] ], - "sanitizer-names.https.tentative.html": [ + "sanitizer-names.https.html": [ "22b913574e83f03f223bd49dff36573f908ab144", [ null, {} ] ], - "sanitizer-query-config.https.tenative.html": [ + "sanitizer-query-config.https.html": [ "bd7c7ea3f65570e5b3e9e1dda3f098697ad22e8e", [ null, @@ -523420,7 +523595,7 @@ ] ], "readable-stream.html": [ - "59b57ce6723c10be746e2b3b478dcf81df105db1", + "b1ede4695bf4cd73a74fb43d52d471a72534d210", [ null, {} @@ -523447,8 +523622,15 @@ {} ] ], + "transfer-with-messageport.window.js": [ + "37f8c9df169607a4565f76d04c7cc56bc408af47", + [ + "streams/transferable/transfer-with-messageport.window.html", + {} + ] + ], "transform-stream.html": [ - "fbfbfe8fc1347ab9211845f439a9a7e105a33539", + "355d5d807433d75c02adff23e228d050b7772c0f", [ null, {} @@ -523469,7 +523651,7 @@ ] ], "writable-stream.html": [ - "adc6f457c27e87569be2fd32bfe723d29aef7135", + "297131b8a823538116e1a826f65b2ac814c6f65a", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html b/third_party/blink/web_tests/external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html new file mode 100644 index 0000000..9d5e1e0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>eval-in-iframe</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/utils.js"></script> +</head> +<body> + <iframe src="/content-security-policy/wasm-unsafe-eval/support/iframe.html"> + </iframe> + + <script> + async_test(t => { + self.addEventListener('message', t.step_func_done(({data}) => { + assert_equals(data.violatedDirective, "script-src"); + assert_equals(data.originalPolicy, "default-src 'unsafe-inline'") + assert_equals(data.blockedURI, "wasm-eval") + })); + }, "Got the expected securitypolicyviolation in the iframe"); + + const iframe = document.querySelector('iframe'); + iframe.addEventListener('load', () => { + let m = new WebAssembly.Module( + new Uint8Array([0, 0x61, 0x73, 0x6d, 0x1, 0, 0, 0])); + iframe.contentWindow.postMessage(m); + }); + </script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/wasm-unsafe-eval/support/iframe.html b/third_party/blink/web_tests/external/wpt/content-security-policy/wasm-unsafe-eval/support/iframe.html new file mode 100644 index 0000000..4d8b9375 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/content-security-policy/wasm-unsafe-eval/support/iframe.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<body> + <h1>iframe</h1> + <script> + self.addEventListener('securitypolicyviolation', e => { + window.parent.postMessage({ violatedDirective: e.violatedDirective, + originalPolicy: e.originalPolicy, blockedURI: e.blockedURI }); + }); + </script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/wasm-unsafe-eval/support/iframe.html.headers b/third_party/blink/web_tests/external/wpt/content-security-policy/wasm-unsafe-eval/support/iframe.html.headers new file mode 100644 index 0000000..bc3a72a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/content-security-policy/wasm-unsafe-eval/support/iframe.html.headers
@@ -0,0 +1 @@ +Content-Security-Policy: default-src 'unsafe-inline'
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-htb-ltr-ref.html b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-htb-ltr-ref.html new file mode 100644 index 0000000..1841ff58 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-htb-ltr-ref.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<style> +.multicol { + inline-size: 400px; + block-size: 100px; + columns: 4; + column-fill: auto; + gap: 10px; + padding: 10px; + border: solid 3px; +} +</style> +<div class="multicol"> + <div style="background: dodgerblue; block-size: 120px;"></div> + <div style="block-size: 40px; border: solid 10px lime;"></div> + <div style="block-size: 135px; border: solid 10px; border-top: none;"></div> + <div style="block-size: 40px; border: solid 10px blue; border-top: none;"></div> + <div style="block-size: 15px; border: solid 10px blue; border-top: none;"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-htb-ltr.html b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-htb-ltr.html new file mode 100644 index 0000000..60e1462 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-htb-ltr.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<link rel="match" href="table-collapsed-borders-paint-htb-ltr-ref.html"> +<link rel="help" href="https://drafts.csswg.org/css-tables-3/#fragmentation"> +<link rel="help" href="https://drafts.csswg.org/css-tables-3/#rendering"> +<style> +.multicol { + inline-size: 400px; + block-size: 100px; + columns: 4; + column-fill: auto; + gap: 10px; + padding: 10px; + border: solid 3px; +} +</style> +<div class="multicol"> + <table style="border-collapse: collapse; inline-size: 100%;"> + <caption style="background: dodgerblue; block-size: 120px;"></caption> + <tbody> + <tr style="block-size: 50px;"> + <td style="border: solid 10px lime;"></td> + </tr> + <tr style="block-size: 145px;"> + <td style="border: solid 10px;"></td> + </tr> + </tbody> + <tbody> + <tr style="block-size: 50px;"> + <td style="border: solid blue 10px;"></td> + </tr> + <tr style="block-size: 25px;"> + <td style="border: solid blue 10px;"></td> + </tr> + </tbody> + </table> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vlr-rtl-ref.html b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vlr-rtl-ref.html new file mode 100644 index 0000000..e17497a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vlr-rtl-ref.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<style> +body { + writing-mode: vertical-lr; + direction: rtl; +} +.multicol { + inline-size: 400px; + block-size: 100px; + columns: 4; + column-fill: auto; + gap: 10px; + padding: 10px; + border: solid 3px; +} +</style> +<div class="multicol"> + <div style="background: dodgerblue; block-size: 120px;"></div> + <div style="block-size: 40px; border: solid 10px lime;"></div> + <div style="block-size: 135px; border: solid 10px; border-left: none;"></div> + <div style="block-size: 40px; border: solid 10px blue; border-left: none;"></div> + <div style="block-size: 15px; border: solid 10px blue; border-left: none;"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vlr-rtl.html b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vlr-rtl.html new file mode 100644 index 0000000..d03968ec --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vlr-rtl.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<link rel="match" href="table-collapsed-borders-paint-vlr-rtl-ref.html"> +<link rel="help" href="https://drafts.csswg.org/css-tables-3/#fragmentation"> +<link rel="help" href="https://drafts.csswg.org/css-tables-3/#rendering"> +<style> +body { + writing-mode: vertical-lr; + direction: rtl; +} +.multicol { + inline-size: 400px; + block-size: 100px; + columns: 4; + column-fill: auto; + gap: 10px; + padding: 10px; + border: solid 3px; +} +</style> +<div class="multicol"> + <table style="border-collapse: collapse; inline-size: 100%;"> + <caption style="background: dodgerblue; block-size: 120px;"></caption> + <tbody> + <tr style="block-size: 50px;"> + <td style="border: solid 10px lime;"></td> + </tr> + <tr style="block-size: 145px;"> + <td style="border: solid 10px;"></td> + </tr> + </tbody> + <tbody> + <tr style="block-size: 50px;"> + <td style="border: solid blue 10px;"></td> + </tr> + <tr style="block-size: 25px;"> + <td style="border: solid blue 10px;"></td> + </tr> + </tbody> + </table> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vrl-ltr-ref.html b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vrl-ltr-ref.html new file mode 100644 index 0000000..2721bc0a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vrl-ltr-ref.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<style> +body { + writing-mode: vertical-rl; +} +.multicol { + inline-size: 400px; + block-size: 100px; + columns: 4; + column-fill: auto; + gap: 10px; + padding: 10px; + border: solid 3px; +} +</style> +<div class="multicol"> + <div style="background: dodgerblue; block-size: 120px;"></div> + <div style="block-size: 40px; border: solid 10px lime;"></div> + <div style="block-size: 135px; border: solid 10px; border-right: none;"></div> + <div style="block-size: 40px; border: solid 10px blue; border-right: none;"></div> + <div style="block-size: 15px; border: solid 10px blue; border-right: none;"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vrl-ltr.html b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vrl-ltr.html new file mode 100644 index 0000000..6dff501 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-collapsed-borders-paint-vrl-ltr.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<link rel="match" href="table-collapsed-borders-paint-vrl-ltr-ref.html"> +<link rel="help" href="https://drafts.csswg.org/css-tables-3/#fragmentation"> +<link rel="help" href="https://drafts.csswg.org/css-tables-3/#rendering"> +<style> +body { + writing-mode: vertical-rl; +} +.multicol { + inline-size: 400px; + block-size: 100px; + columns: 4; + column-fill: auto; + gap: 10px; + padding: 10px; + border: solid 3px; +} +</style> +<div class="multicol"> + <table style="border-collapse: collapse; inline-size: 100%;"> + <caption style="background: dodgerblue; block-size: 120px;"></caption> + <tbody> + <tr style="block-size: 50px;"> + <td style="border: solid 10px lime;"></td> + </tr> + <tr style="block-size: 145px;"> + <td style="border: solid 10px;"></td> + </tr> + </tbody> + <tbody> + <tr style="block-size: 50px;"> + <td style="border: solid blue 10px;"></td> + </tr> + <tr style="block-size: 25px;"> + <td style="border: solid blue 10px;"></td> + </tr> + </tbody> + </table> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-tables/border-collapse-dynamic-section.html b/third_party/blink/web_tests/external/wpt/css/css-tables/border-collapse-dynamic-section.html new file mode 100644 index 0000000..5f48749 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-tables/border-collapse-dynamic-section.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-tables-3/"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<table style="border-collapse: collapse; width: 100px; background: red;"> + <tbody> + <tr id="target" style="height: 50px; display: none;"> + <td style="border: solid green 25px; background: green; padding: 0;"></td> + </tr> + </tbody> + <tbody> + <tr style="height: 25px;"> + <td style="border: solid green 25px; padding: 0;"></td> + </tr> + </tbody> +</table> +<script> +document.body.offsetTop; +document.getElementById('target').style.display = ''; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-001-ref.html new file mode 100644 index 0000000..18a54a4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-001-ref.html
@@ -0,0 +1,243 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<style> + body { margin: 0; } + .cb { + position: relative; + inline-size: 45px; + block-size: 40px; + background: lightblue; + border: solid gray; + border-width: 1px 2px 3px 4px; + float: left; + margin-right: 5px; + } + .parent { + inline-size: 35px; + block-size: 30px; + background: orange; + } + .abspos { + inline-size: 20px; + block-size: 15px; + background: pink; + } + + .vrl { + writing-mode: vertical-rl; + } + .vlr { + writing-mode: vertical-lr; + } + .htb { + writing-mode: horizontal-tb; + } + + .ltr { + direction: ltr; + } + .rtl { + direction: rtl; + } + + .sep { + clear: both; + display: block; + height: 5px; + } +</style> +<body> + <div class="cb htb ltr"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb htb rtl"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vlr ltr"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vlr rtl"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vrl ltr"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vrl rtl"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-001.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-001.html new file mode 100644 index 0000000..f7b7375 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-001.html
@@ -0,0 +1,248 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"> +<meta name="assert" + content="This test checks that absolutely positioned elements are offset correctly in a bordered containing block, in different combinations of writing modes and directions." /> +<link rel="match" href="abs-pos-border-offset-001-ref.html"> +<style> + body { margin: 0; } + .cb { + position: relative; + inline-size: 45px; + block-size: 40px; + background: lightblue; + border: solid gray; + border-width: 1px 2px 3px 4px; + float: left; + margin-right: 5px; + } + .parent { + inline-size: 35px; + block-size: 30px; + background: orange; + } + .abspos { + position: absolute; + inline-size: 20px; + block-size: 15px; + background: pink; + } + + .vrl { + writing-mode: vertical-rl; + } + .vlr { + writing-mode: vertical-lr; + } + .htb { + writing-mode: horizontal-tb; + } + + .ltr { + direction: ltr; + } + .rtl { + direction: rtl; + } + + .sep { + clear: both; + display: block; + height: 5px; + } +</style> +<body> + <div class="cb htb ltr"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb htb rtl"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vlr ltr"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vlr rtl"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vrl ltr"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vrl rtl"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-002-ref.html new file mode 100644 index 0000000..98ec0d0c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-002-ref.html
@@ -0,0 +1,397 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<style> + body { margin: 0; } + .cb { + position: relative; + inline-size: 45px; + block-size: 40px; + background: lightblue; + border: solid gray; + border-width: 1px 2px 3px 4px; + float: left; + margin-right: 5px; + } + .parent { + inline-size: 35px; + block-size: 30px; + background: orange; + } + .abspos { + inline-size: 20px; + block-size: 15px; + background: pink; + } + + .vrl { + writing-mode: vertical-rl; + } + .vlr { + writing-mode: vertical-lr; + } + .srl { + writing-mode: sideways-rl; + } + .slr { + writing-mode: sideways-lr; + } + .htb { + writing-mode: horizontal-tb; + } + + .ltr { + direction: ltr; + } + .rtl { + direction: rtl; + } + + .sep { + clear: both; + display: block; + height: 5px; + } +</style> +<body> + <div class="cb htb ltr"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb htb rtl"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vlr ltr"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vlr rtl"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vrl ltr"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vrl rtl"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb slr ltr"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb slr rtl"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb srl ltr"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb srl rtl"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-002.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-002.html new file mode 100644 index 0000000..a954a567 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-border-offset-002.html
@@ -0,0 +1,401 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"> +<meta name="assert" content="This test checks that absolutely positioned elements are offset correctly in a bordered containing block, in different combinations of sideways writing modes and directions." /> +<link rel="match" href="abs-pos-border-offset-002-ref.html"> +<style> + body { margin: 0; } + .cb { + position: relative; + inline-size: 45px; + block-size: 40px; + background: lightblue; + border: solid gray; + border-width: 1px 2px 3px 4px; + float: left; + margin-right: 5px; + } + .parent { + inline-size: 35px; + block-size: 30px; + background: orange; + } + .abspos { + position: absolute; + inline-size: 20px; + block-size: 15px; + background: pink; + } + + .srl { + writing-mode: sideways-rl; + } + .slr { + writing-mode: sideways-lr; + } + .vrl { + writing-mode: vertical-rl; + } + .vlr { + writing-mode: vertical-lr; + } + .htb { + writing-mode: horizontal-tb; + } + + .ltr { + direction: ltr; + } + .rtl { + direction: rtl; + } + + .sep { + clear: both; + display: block; + height: 5px; + } +</style> +<body> + <div class="cb htb ltr"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb ltr"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb htb rtl"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb htb rtl"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vlr ltr"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr ltr"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vlr rtl"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vlr rtl"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vrl ltr"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl ltr"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb vrl rtl"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb vrl rtl"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb slr ltr"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr ltr"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb slr rtl"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb slr rtl"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb srl ltr"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl ltr"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> + + <div class="cb srl rtl"> + <div class="parent htb ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent htb rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent vlr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent vlr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent vrl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent vrl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent slr ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent slr rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent srl ltr"> + <div class="abspos"></div> + </div> + </div> + <div class="cb srl rtl"> + <div class="parent srl rtl"> + <div class="abspos"></div> + </div> + </div> + <div class="sep"></div> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-border-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-border-001-ref.html new file mode 100644 index 0000000..e4098f1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-border-001-ref.html
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<style> + body { margin: 0; } + .vert-cb { + position: relative; + width: 150px; + height: 60px; + writing-mode: vertical-lr; + direction: rtl; + background: lightblue; + border: solid gray; + border-width: 1px 2px 3px 4px; + margin-bottom: 2px; + } + .horiz-parent { + width: 120px; + height: 100%; + box-sizing: border-box; + border: solid orange; + border-width: 4px 3px 2px 1px; + writing-mode: horizontal-tb; + } + .abspos-equivalent { + height: 40px; + background: pink; + border: solid black; + border-width: 2px 1px 4px 3px; + } +</style> +<body> + <div class="vert-cb"> + <div class="horiz-parent"> + <div class="abspos-equivalent" style="width: max-content">Hello</div> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <div class="abspos-equivalent" style="width: 100px">Hello</div> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <canvas class="abspos-equivalent" height="40px" width="100px"></canvas> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <img src="broken" class="abspos-equivalent" height="40px" width="100px"> + </div> + </div> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-border-001.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-border-001.html new file mode 100644 index 0000000..795bd97 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-border-001.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"> +<meta name="assert" content="This test checks that absolutely positioned elements are offset correctly in a containing block with an orthogonal writing mode and that has a border." /> +<link rel="match" href="abs-pos-vlr-border-001-ref.html"> +<style> + body { margin: 0; } + .vert-cb { + position: relative; + width: 150px; + height: 60px; + writing-mode: vertical-lr; + direction: rtl; + background: lightblue; + border: solid gray; + border-width: 1px 2px 3px 4px; + margin-bottom: 2px; + } + .horiz-parent { + width: 120px; + height: 100%; + box-sizing: border-box; + border: solid orange; + border-width: 4px 3px 2px 1px; + writing-mode: horizontal-tb; + } + .abspos { + position: absolute; + /* Specify a height to work around https://bugzilla.mozilla.org/1769102 */ + height: 40px; + background: pink; + border: solid black; + border-width: 2px 1px 4px 3px; + } +</style> +<body> + <div class="vert-cb"> + <div class="horiz-parent"> + <div class="abspos" style="width: max-content">Hello</div> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <div class="abspos" style="width: 100px">Hello</div> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <canvas class="abspos" height="40px" width="100px"></canvas> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <img src="broken" class="abspos" height="40px" width="100px"> + </div> + </div> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-padding-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-padding-001-ref.html new file mode 100644 index 0000000..6a941ff6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-padding-001-ref.html
@@ -0,0 +1,53 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<style> + body { margin: 0; } + .vert-cb { + position: relative; + width: 150px; + height: 60px; + writing-mode: vertical-lr; + direction: rtl; + background: lightblue; + padding: 1px 2px 3px 4px; + margin-bottom: 2px; + } + .horiz-parent { + width: 120px; + height: 100%; + box-sizing: border-box; + border: solid orange; + border-width: 4px 3px 2px 1px; + writing-mode: horizontal-tb; + } + .abspos-equivalent { + height: 40px; + background: pink; + border: solid black; + border-width: 2px 1px 4px 3px; + } +</style> +<body> + <div class="vert-cb"> + <div class="horiz-parent"> + <div class="abspos-equivalent" style="width: max-content">Hello</div> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <div class="abspos-equivalent" style="width: 100px">Hello</div> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <canvas class="abspos-equivalent" height="40px" width="100px"></canvas> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <img src="broken" class="abspos-equivalent" height="40px" width="100px"> + </div> + </div> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-padding-001.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-padding-001.html new file mode 100644 index 0000000..209cce1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/abs-pos-vlr-padding-001.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"> +<meta name="assert" content="This test checks that absolutely positioned elements are offset correctly in a containing block with a different writing mode and that has padding." /> +<link rel="match" href="abs-pos-vlr-padding-001-ref.html"> +<style> + body { margin: 0; } + .vert-cb { + position: relative; + width: 150px; + height: 60px; + writing-mode: vertical-lr; + direction: rtl; + background: lightblue; + padding: 1px 2px 3px 4px; + margin-bottom: 2px; + } + .horiz-parent { + width: 120px; + height: 100%; + box-sizing: border-box; + border: solid orange; + border-width: 4px 3px 2px 1px; + writing-mode: horizontal-tb; + } + .abspos { + position: absolute; + /* Specify a height to work around https://bugzilla.mozilla.org/1769102 */ + height: 40px; + background: pink; + border: solid black; + border-width: 2px 1px 4px 3px; + } +</style> +<body> + <div class="vert-cb"> + <div class="horiz-parent"> + <div class="abspos" style="width: max-content">Hello</div> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <div class="abspos" style="width: 100px">Hello</div> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <canvas class="abspos" height="40px" width="100px"></canvas> + </div> + </div> + <div class="vert-cb"> + <div class="horiz-parent"> + <img src="broken" class="abspos" height="40px" width="100px"> + </div> + </div> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/form-submission.https.sub.html b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/form-submission.https.sub.html index a0f683a..988b07c 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/form-submission.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/form-submission.https.sub.html
@@ -7,6 +7,7 @@ --> <html lang="en"> <meta charset="utf-8"> + <meta name="timeout" content="long"> <title>HTTP headers on request for HTML form navigation</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/form-submission.sub.html b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/form-submission.sub.html index c4a5e2f..f862062 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/form-submission.sub.html +++ b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/form-submission.sub.html
@@ -7,6 +7,7 @@ --> <html lang="en"> <meta charset="utf-8"> + <meta name="timeout" content="long"> <title>HTTP headers on request for HTML form navigation</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/metadata/tools/templates/form-submission.sub.html b/third_party/blink/web_tests/external/wpt/fetch/metadata/tools/templates/form-submission.sub.html index cbf7b5ca..4c9c8c5 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/metadata/tools/templates/form-submission.sub.html +++ b/third_party/blink/web_tests/external/wpt/fetch/metadata/tools/templates/form-submission.sub.html
@@ -4,6 +4,7 @@ --> <html lang="en"> <meta charset="utf-8"> + <meta name="timeout" content="long"> <title>HTTP headers on request for HTML form navigation</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/delegate-request.https.sub.tentative.html b/third_party/blink/web_tests/external/wpt/fullscreen/api/delegate-request.https.sub.tentative.html index 3760461d15..37e0099 100644 --- a/third_party/blink/web_tests/external/wpt/fullscreen/api/delegate-request.https.sub.tentative.html +++ b/third_party/blink/web_tests/external/wpt/fullscreen/api/delegate-request.https.sub.tentative.html
@@ -14,6 +14,11 @@ Verifies that element.requestFullscreen() call from a cross-origin subframe without user activation works if and only if the top frame has user activation and it delegates the capability to the subframe. + + https://wicg.github.io/capability-delegation/spec.html + + See wpt/html/user-activation/propagation*.html for child->parent user activation visibility tests. + TODO: Check same-origin iframes, sibling frames, and popup<->opener delegation. </div> <iframe allow="fullscreen" width="300px" height="50px"
diff --git a/third_party/blink/web_tests/external/wpt/streams/transferable/readable-stream.html b/third_party/blink/web_tests/external/wpt/streams/transferable/readable-stream.html index 59b57ce6..b1ede46 100644 --- a/third_party/blink/web_tests/external/wpt/streams/transferable/readable-stream.html +++ b/third_party/blink/web_tests/external/wpt/streams/transferable/readable-stream.html
@@ -135,18 +135,7 @@ assert_array_equals(rs.events, ['pull'], 'pull() should have been called'); }, 'the extra queue from transferring is counted in chunks'); -promise_test(async () => { - const rs = await recordingTransferredReadableStream(); - rs.cancel('message'); - await delay(0); - assert_array_equals(rs.events, ['pull', 'cancel', 'message'], - 'cancel() should have been called'); - const reader = rs.getReader(); - // Check the stream really got closed. - await reader.closed; -}, 'cancel should be propagated to the original'); - -promise_test(async () => { +async function transferredReadableStreamWithCancelPromise() { let resolveCancelCalled; const cancelCalled = new Promise(resolve => { resolveCancelCalled = resolve; @@ -156,6 +145,22 @@ resolveCancelCalled(); } }); + return { rs, cancelCalled }; +} + +promise_test(async () => { + const { rs, cancelCalled } = await transferredReadableStreamWithCancelPromise(); + rs.cancel('message'); + await cancelCalled; + assert_array_equals(rs.events, ['pull', 'cancel', 'message'], + 'cancel() should have been called'); + const reader = rs.getReader(); + // Check the stream really got closed. + await reader.closed; +}, 'cancel should be propagated to the original'); + +promise_test(async () => { + const { rs, cancelCalled } = await transferredReadableStreamWithCancelPromise(); const reader = rs.getReader(); const readPromise = reader.read(); reader.cancel('done');
diff --git a/third_party/blink/web_tests/external/wpt/streams/transferable/transfer-with-messageport.window.js b/third_party/blink/web_tests/external/wpt/streams/transferable/transfer-with-messageport.window.js new file mode 100644 index 0000000..37f8c9d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/streams/transferable/transfer-with-messageport.window.js
@@ -0,0 +1,219 @@ +"use strict"; + +function receiveEventOnce(target, name) { + return new Promise(resolve => { + target.addEventListener( + name, + ev => { + resolve(ev); + }, + { once: true } + ); + }); +} + +async function postAndTestMessageEvent(data, transfer, title) { + postMessage(data, "*", transfer); + const messagePortCount = transfer.filter(i => i instanceof MessagePort) + .length; + const ev = await receiveEventOnce(window, "message"); + assert_equals( + ev.ports.length, + messagePortCount, + `Correct number of ports ${title}` + ); + for (const [i, port] of ev.ports.entries()) { + assert_true( + port instanceof MessagePort, + `ports[${i}] include MessagePort ${title}` + ); + } + for (const [key, value] of Object.entries(data)) { + assert_true( + ev.data[key] instanceof value.constructor, + `data.${key} has correct interface ${value.constructor.name} ${title}` + ); + } +} + +async function transferMessagePortWithOrder1(stream) { + const channel = new MessageChannel(); + await postAndTestMessageEvent( + { stream, port2: channel.port2 }, + [stream, channel.port2], + `when transferring [${stream.constructor.name}, MessagePort]` + ); +} + +async function transferMessagePortWithOrder2(stream) { + const channel = new MessageChannel(); + await postAndTestMessageEvent( + { stream, port2: channel.port2 }, + [channel.port2, stream], + `when transferring [MessagePort, ${stream.constructor.name}]` + ); +} + +async function transferMessagePortWithOrder3(stream) { + const channel = new MessageChannel(); + await postAndTestMessageEvent( + { port1: channel.port1, stream, port2: channel.port2 }, + [channel.port1, stream, channel.port2], + `when transferring [MessagePort, ${stream.constructor.name}, MessagePort]` + ); +} + +async function transferMessagePortWithOrder4(stream) { + const channel = new MessageChannel(); + await postAndTestMessageEvent( + {}, + [channel.port1, stream, channel.port2], + `when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with empty data` + ); +} + +async function transferMessagePortWithOrder5(stream) { + const channel = new MessageChannel(); + await postAndTestMessageEvent( + { port2: channel.port2, port1: channel.port1, stream }, + [channel.port1, stream, channel.port2], + `when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with data having different order` + ); +} + +async function transferMessagePortWithOrder6(stream) { + const channel = new MessageChannel(); + await postAndTestMessageEvent( + { port2: channel.port2, port1: channel.port1 }, + [channel.port1, stream, channel.port2], + `when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with stream not being in the data` + ); +} + +async function transferMessagePortWithOrder7(stream) { + const channel = new MessageChannel(); + await postAndTestMessageEvent( + { stream }, + [channel.port1, stream, channel.port2], + `when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with ports not being in the data` + ); +} + +async function transferMessagePortWith(constructor) { + await transferMessagePortWithOrder1(new constructor()); + await transferMessagePortWithOrder2(new constructor()); + await transferMessagePortWithOrder3(new constructor()); +} + +async function advancedTransferMesagePortWith(constructor) { + await transferMessagePortWithOrder4(new constructor()); + await transferMessagePortWithOrder5(new constructor()); + await transferMessagePortWithOrder6(new constructor()); + await transferMessagePortWithOrder7(new constructor()); +} + +async function mixedTransferMessagePortWithOrder1() { + const channel = new MessageChannel(); + const readable = new ReadableStream(); + const writable = new WritableStream(); + const transform = new TransformStream(); + await postAndTestMessageEvent( + { + readable, + writable, + transform, + port1: channel.port1, + port2: channel.port2, + }, + [readable, writable, transform, channel.port1, channel.port2], + `when transferring [ReadableStream, WritableStream, TransformStream, MessagePort, MessagePort]` + ); +} + +async function mixedTransferMessagePortWithOrder2() { + const channel = new MessageChannel(); + const readable = new ReadableStream(); + const writable = new WritableStream(); + const transform = new TransformStream(); + await postAndTestMessageEvent( + { readable, writable, transform }, + [transform, channel.port1, readable, channel.port2, writable], + `when transferring [TransformStream, MessagePort, ReadableStream, MessagePort, WritableStream]` + ); +} + +async function mixedTransferMessagePortWithOrder3() { + const channel = new MessageChannel(); + const readable1 = new ReadableStream(); + const readable2 = new ReadableStream(); + const writable1 = new WritableStream(); + const writable2 = new WritableStream(); + const transform1 = new TransformStream(); + const transform2 = new TransformStream(); + await postAndTestMessageEvent( + { readable1, writable1, transform1, readable2, writable2, transform2 }, + [ + transform2, + channel.port1, + readable1, + channel.port2, + writable2, + readable2, + writable1, + transform1, + ], + `when transferring [TransformStream, MessagePort, ReadableStream, MessagePort, WritableStream, ReadableStream, WritableStream, TransformStream] but with the data having different order` + ); +} + +async function mixedTransferMesagePortWith() { + await mixedTransferMessagePortWithOrder1(); + await mixedTransferMessagePortWithOrder2(); + await mixedTransferMessagePortWithOrder3(); +} + +promise_test(async t => { + await transferMessagePortWith(ReadableStream); +}, "Transferring a MessagePort with a ReadableStream should set `.ports`"); + +promise_test(async t => { + await transferMessagePortWith(WritableStream); +}, "Transferring a MessagePort with a WritableStream should set `.ports`"); + +promise_test(async t => { + await transferMessagePortWith(TransformStream); +}, "Transferring a MessagePort with a TransformStream should set `.ports`"); + +promise_test(async t => { + await transferMessagePortWith(ReadableStream); +}, "Transferring a MessagePort with a ReadableStream should set `.ports`, advanced"); + +promise_test(async t => { + await transferMessagePortWith(WritableStream); +}, "Transferring a MessagePort with a WritableStream should set `.ports`, advanced"); + +promise_test(async t => { + await transferMessagePortWith(TransformStream); +}, "Transferring a MessagePort with a TransformStream should set `.ports`, advanced"); + +promise_test(async t => { + await mixedTransferMesagePortWith(); +}, "Transferring a MessagePort with multiple streams should set `.ports`"); + +test(() => { + assert_throws_dom("DataCloneError", () => + postMessage({ stream: new ReadableStream() }, "*") + ); +}, "ReadableStream must not be serializable"); + +test(() => { + assert_throws_dom("DataCloneError", () => + postMessage({ stream: new WritableStream() }, "*") + ); +}, "WritableStream must not be serializable"); + +test(() => { + assert_throws_dom("DataCloneError", () => + postMessage({ stream: new TransformStream() }, "*") + ); +}, "TransformStream must not be serializable");
diff --git a/third_party/blink/web_tests/external/wpt/streams/transferable/transform-stream.html b/third_party/blink/web_tests/external/wpt/streams/transferable/transform-stream.html index fbfbfe8f..355d5d80 100644 --- a/third_party/blink/web_tests/external/wpt/streams/transferable/transform-stream.html +++ b/third_party/blink/web_tests/external/wpt/streams/transferable/transform-stream.html
@@ -66,9 +66,14 @@ controller.close(); } }); + let resolve; + const ready = new Promise(r => resolve = r); let result = ''; const sink = new WritableStream({ write(chunk) { + if (result) { + resolve(); + } result += chunk; } }); @@ -93,8 +98,7 @@ }); postMessage({source, sink, transform1, transform2}, '*', [source, transform1, sink, transform2]); - return promise - .then(() => delay(0)) + return ready .then(() => { assert_equals(result, 'HELLO HELLO THERE THERE ', 'transforms should have been applied');
diff --git a/third_party/blink/web_tests/external/wpt/streams/transferable/writable-stream.html b/third_party/blink/web_tests/external/wpt/streams/transferable/writable-stream.html index adc6f45..297131b 100644 --- a/third_party/blink/web_tests/external/wpt/streams/transferable/writable-stream.html +++ b/third_party/blink/web_tests/external/wpt/streams/transferable/writable-stream.html
@@ -99,35 +99,46 @@ const writer = transferred.getWriter(); await writer.write('a'); let writeDone = false; - writer.write('b').then(() => { + const writePromise = writer.write('b').then(() => { writeDone = true; }); await flushAsyncEvents(); assert_false(writeDone, 'second write should not have resolved yet'); resolveWrite(); - await delay(0); - assert_true(writeDone, 'second write should have resolved'); + await writePromise; // (makes sure this doesn't cause timeout) }, 'second write should wait for first underlying write to complete'); -promise_test(async t => { - const orig = recordingWritableStream(); +async function transferredWritableStreamWithAbortPromise() { + let resolveAbortCalled; + const abortCalled = new Promise(resolve => { + resolveAbortCalled = resolve; + }); + const orig = recordingWritableStream({ + abort() { + resolveAbortCalled(); + } + }); const transferred = await transfer(orig); + return { orig, transferred, abortCalled }; +} + +promise_test(async t => { + const { orig, transferred, abortCalled } = await transferredWritableStreamWithAbortPromise(); transferred.abort('p'); - await delay(0); + await abortCalled; assert_array_equals(orig.events, ['abort', 'p'], 'abort() should have been called'); }, 'abort() should work'); promise_test(async t => { - const orig = recordingWritableStream(); - const transferred = await transfer(orig); + const { orig, transferred, abortCalled } = await transferredWritableStreamWithAbortPromise(); const writer = transferred.getWriter(); // A WritableStream object cannot be cloned. await promise_rejects_dom(t, 'DataCloneError', writer.write(new WritableStream()), 'the write should reject'); await promise_rejects_dom(t, 'DataCloneError', writer.closed, 'the stream should be errored'); - await delay(0); + await abortCalled; assert_equals(orig.events.length, 2, 'abort should have been called'); assert_equals(orig.events[0], 'abort', 'first event should be abort'); assert_equals(orig.events[1].name, 'DataCloneError',
diff --git a/third_party/ipcz/src/BUILD.gn b/third_party/ipcz/src/BUILD.gn index 13dc9c5..9f214d0 100644 --- a/third_party/ipcz/src/BUILD.gn +++ b/third_party/ipcz/src/BUILD.gn
@@ -5,6 +5,10 @@ import("//build_overrides/ipcz.gni") import("//testing/test.gni") +# ipcz will not implement a multiprocess reference driver or its supporting +# primitives for iOS or NaCl platforms. Note that this only affects ipcz tests. +enable_ipcz_multiprocess_test_support = !is_ios && !is_nacl + shared_library("ipcz_shared") { output_name = "ipcz" sources = [ @@ -126,6 +130,8 @@ } ipcz_source_set("reference_drivers") { + testonly = true + public = [ "reference_drivers/single_process_reference_driver.h" ] sources = [ @@ -136,9 +142,58 @@ "reference_drivers/single_process_reference_driver.cc", ] + if (enable_ipcz_multiprocess_test_support) { + public += [ + "reference_drivers/memory.h", + "reference_drivers/os_handle.h", + ] + sources += [ "reference_drivers/memory.cc" ] + + if (is_android) { + sources += [ + "reference_drivers/memory_android.cc", + "reference_drivers/os_handle_posix.cc", + "reference_drivers/os_handle_posix.h", + ] + } else if (is_mac) { + sources += [ + "reference_drivers/memory_mac.cc", + "reference_drivers/os_handle_mac.cc", + "reference_drivers/os_handle_mac.h", + ] + } else if (is_win) { + sources += [ + "reference_drivers/memory_win.cc", + "reference_drivers/os_handle_win.cc", + "reference_drivers/os_handle_win.h", + ] + } else if (is_fuchsia) { + sources += [ + "reference_drivers/memory_fuchsia.cc", + "reference_drivers/os_handle_fuchsia.cc", + "reference_drivers/os_handle_fuchsia.h", + ] + } else if (is_posix) { + sources += [ + "reference_drivers/memory_posix.cc", + "reference_drivers/os_handle_posix.cc", + "reference_drivers/os_handle_posix.h", + ] + } + } + ipcz_deps = [ ":util" ] public_deps = [ ":ipcz_header" ] configs = [ ":ipcz_include_src_dir" ] + + deps = [] + if (is_fuchsia) { + public_deps += [ "//third_party/fuchsia-sdk/sdk/pkg/zx" ] + } + + if (is_android) { + deps += [ "//third_party/ashmem" ] + } } ipcz_source_set("util") { @@ -295,6 +350,10 @@ "util/stack_trace_test.cc", ] + if (enable_ipcz_multiprocess_test_support) { + sources += [ "reference_drivers/memory_test.cc" ] + } + deps = [ "//testing/gmock", "//testing/gtest",
diff --git a/third_party/ipcz/src/reference_drivers/memory.cc b/third_party/ipcz/src/reference_drivers/memory.cc new file mode 100644 index 0000000..041fa84 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/memory.cc
@@ -0,0 +1,50 @@ +// Copyright 2022 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 "reference_drivers/memory.h" + +#include <utility> + +#include "build/build_config.h" +#include "third_party/abseil-cpp/absl/base/macros.h" + +namespace ipcz::reference_drivers { + +Memory::Mapping::Mapping() = default; + +Memory::Mapping::Mapping(void* base_address, size_t size) + : base_address_(base_address), size_(size) {} + +Memory::Mapping::Mapping(Mapping&& other) + : base_address_(std::exchange(other.base_address_, nullptr)), + size_(std::exchange(other.size_, 0)) {} + +Memory::Mapping& Memory::Mapping::operator=(Mapping&& other) { + Reset(); + base_address_ = std::exchange(other.base_address_, nullptr); + size_ = std::exchange(other.size_, 0); + return *this; +} + +Memory::Mapping::~Mapping() { + Reset(); +} + +Memory::Memory() = default; + +Memory::Memory(OSHandle handle, size_t size) + : handle_(std::move(handle)), size_(size) {} + +Memory::Memory(Memory&&) = default; + +Memory& Memory::operator=(Memory&&) = default; + +Memory::~Memory() = default; + +Memory Memory::Clone() { + ABSL_ASSERT(is_valid()); + return Memory(handle_.Clone(), size_); +} + +} // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/memory.h b/third_party/ipcz/src/reference_drivers/memory.h new file mode 100644 index 0000000..eaf24857 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/memory.h
@@ -0,0 +1,95 @@ +// Copyright 2022 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 IPCZ_SRC_REFERENCE_DRIVERS_MEMORY_H_ +#define IPCZ_SRC_REFERENCE_DRIVERS_MEMORY_H_ + +#include "reference_drivers/os_handle.h" +#include "third_party/abseil-cpp/absl/types/span.h" + +namespace ipcz::reference_drivers { + +// Cross-platform abstraction for a shared memory region. +class Memory { + public: + // Cross-platform abstraction for an active mapping of a shared memory region. + // + // Instances of this object should be acquired from Memory::Map(). + class Mapping { + public: + Mapping(); + Mapping(void* base_address, size_t size); + Mapping(Mapping&&); + Mapping& operator=(Mapping&&); + Mapping(const Mapping&) = delete; + Mapping& operator=(const Mapping&) = delete; + ~Mapping(); + + bool is_valid() const { return base_address_ != nullptr; } + + size_t size() const { return size_; } + void* base() const { return base_address_; } + + absl::Span<uint8_t> bytes() const { + return {static_cast<uint8_t*>(base()), size_}; + } + + template <typename T> + T* As() const { + return static_cast<T*>(base()); + } + + void Reset(); + + private: + void* base_address_ = nullptr; + size_t size_ = 0; + }; + + // Constructs an invalid Memory object which cannot be mapped. + Memory(); + + // Constructs a new Memory object over `handle`, an OSHandle which should have + // been previously taken from some other valid Memory object. `size` must + // correspond to the size of that original region. + Memory(OSHandle handle, size_t size); + + // Constructs a new Memory object over a newly allocated shared memory region + // of at least `size` bytes. + explicit Memory(size_t size); + + Memory(Memory&&); + Memory& operator=(Memory&&); + Memory(const Memory&) = delete; + Memory& operator=(const Memory&) = delete; + ~Memory(); + + size_t size() const { return size_; } + bool is_valid() const { return handle_.is_valid(); } + const OSHandle& handle() const { return handle_; } + + // Invalidates this Memory object and returns an OSHandle which can be used + // later to reconstruct an equivalent Memory object, given the same size(). + OSHandle TakeHandle() { return std::move(handle_); } + + // Resets this object, closing its handle to the underlying region. + void reset() { handle_.reset(); } + + // Returns a new Memory object with its own handle to the same underlying + // region as `this`. Must only be called on a valid Memory object (i.e. + // is_valid() must be true.) + Memory Clone(); + + // Maps the entire region owned by Memory and returns a Mapping for it. Must + // only be called on a valid Memory object (i.e. is_valid() must be true.) + Mapping Map(); + + private: + OSHandle handle_; + size_t size_ = 0; +}; + +} // namespace ipcz::reference_drivers + +#endif // IPCZ_SRC_REFERENCE_DRIVERS_MEMORY_H_
diff --git a/third_party/ipcz/src/reference_drivers/memory_android.cc b/third_party/ipcz/src/reference_drivers/memory_android.cc new file mode 100644 index 0000000..355b20f --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/memory_android.cc
@@ -0,0 +1,45 @@ +// Copyright 2022 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 "reference_drivers/memory.h" + +#include <sys/mman.h> +#include <unistd.h> + +#include <cstddef> + +#include "reference_drivers/os_handle.h" +#include "third_party/abseil-cpp/absl/base/macros.h" +#include "third_party/ashmem/ashmem.h" + +namespace ipcz::reference_drivers { + +void Memory::Mapping::Reset() { + if (base_address_) { + munmap(base_address_, size_); + base_address_ = nullptr; + size_ = 0; + } +} + +Memory::Memory(size_t size) { + const size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE)); + const size_t rounded_size = (size + page_size - 1) & (page_size - 1); + int fd = ashmem_create_region("ipcz-memory", rounded_size); + ABSL_ASSERT(fd >= 0); + int err = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE); + ABSL_ASSERT(err == 0); + handle_ = OSHandle(fd); + size_ = size; +} + +Memory::Mapping Memory::Map() { + ABSL_ASSERT(is_valid()); + void* addr = + mmap(nullptr, size_, PROT_READ | PROT_WRITE, MAP_SHARED, handle_.fd(), 0); + ABSL_ASSERT(addr && addr != MAP_FAILED); + return Mapping(addr, size_); +} + +} // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/memory_fuchsia.cc b/third_party/ipcz/src/reference_drivers/memory_fuchsia.cc new file mode 100644 index 0000000..e2c8e2c --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/memory_fuchsia.cc
@@ -0,0 +1,54 @@ +// Copyright 2022 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 "reference_drivers/memory.h" + +#include <lib/zx/vmar.h> +#include <zircon/syscalls.h> + +#include <cstddef> +#include <cstdint> +#include <utility> + +#include "reference_drivers/os_handle.h" +#include "third_party/abseil-cpp/absl/base/macros.h" + +namespace ipcz::reference_drivers { + +void Memory::Mapping::Reset() { + if (base_address_) { + uintptr_t addr = reinterpret_cast<uintptr_t>(base_address_); + zx_status_t status = zx::vmar::root_self()->unmap(addr, size_); + ABSL_ASSERT(status == ZX_OK); + } +} + +Memory::Memory(size_t size) { + const uint32_t page_size = zx_system_get_page_size(); + const size_t rounded_size = (size + page_size - 1) & (page_size - 1); + zx::vmo vmo; + zx_status_t status = zx::vmo::create(rounded_size, 0, &vmo); + ABSL_ASSERT(status == ZX_OK); + const int kNoExec = ZX_DEFAULT_VMO_RIGHTS & ~ZX_RIGHT_EXECUTE; + status = vmo.replace(kNoExec, &vmo); + ABSL_ASSERT(status == ZX_OK); + handle_ = OSHandle(std::move(vmo)); + size_ = size; +} + +Memory::Mapping Memory::Map() { + ABSL_ASSERT(is_valid()); + uintptr_t addr; + zx_vm_option_t options = + ZX_VM_REQUIRE_NON_RESIZABLE | ZX_VM_PERM_READ | ZX_VM_PERM_WRITE; + zx_status_t status = zx::vmar::root_self()->map( + options, /*vmar_offset=*/0, *zx::unowned_vmo(handle_.handle().get()), 0, + size_, &addr); + if (status != ZX_OK) { + return {}; + } + return Mapping(reinterpret_cast<void*>(addr), size_); +} + +} // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/memory_mac.cc b/third_party/ipcz/src/reference_drivers/memory_mac.cc new file mode 100644 index 0000000..4f1c561 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/memory_mac.cc
@@ -0,0 +1,47 @@ +// Copyright 2022 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 "reference_drivers/memory.h" + +#include <mach/mach_vm.h> + +#include "reference_drivers/os_handle.h" +#include "third_party/abseil-cpp/absl/base/macros.h" + +namespace ipcz::reference_drivers { + +void Memory::Mapping::Reset() { + if (base_address_) { + kern_return_t kr = mach_vm_deallocate( + mach_task_self(), reinterpret_cast<mach_vm_address_t>(base_address_), + size_); + ABSL_ASSERT(kr == KERN_SUCCESS); + } +} + +Memory::Memory(size_t size) { + mach_vm_size_t vm_size = size; + mach_port_t named_right; + kern_return_t kr = mach_make_memory_entry_64( + mach_task_self(), &vm_size, 0, + MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE, &named_right, + MACH_PORT_NULL); + ABSL_ASSERT(kr == KERN_SUCCESS); + ABSL_ASSERT(vm_size >= size); + handle_ = OSHandle(OSHandle::MachSendRight(named_right)); + size_ = size; +} + +Memory::Mapping Memory::Map() { + ABSL_ASSERT(is_valid()); + mach_vm_address_t address = 0; + kern_return_t kr = mach_vm_map(mach_task_self(), &address, size_, 0, + VM_FLAGS_ANYWHERE, handle_.mach_send_right(), + 0, FALSE, VM_PROT_READ | VM_PROT_WRITE, + VM_PROT_READ | VM_PROT_WRITE, VM_INHERIT_NONE); + ABSL_ASSERT(kr == KERN_SUCCESS); + return Mapping(reinterpret_cast<void*>(address), size_); +} + +} // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/memory_posix.cc b/third_party/ipcz/src/reference_drivers/memory_posix.cc new file mode 100644 index 0000000..37e7775 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/memory_posix.cc
@@ -0,0 +1,47 @@ +// Copyright 2022 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 "reference_drivers/memory.h" + +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <unistd.h> + +#include "reference_drivers/os_handle.h" +#include "third_party/abseil-cpp/absl/base/macros.h" + +namespace ipcz::reference_drivers { + +void Memory::Mapping::Reset() { + if (base_address_) { + munmap(base_address_, size_); + base_address_ = nullptr; + size_ = 0; + } +} + +Memory::Memory(size_t size) { + int fd = memfd_create("/ipcz/mem", MFD_ALLOW_SEALING); + ABSL_ASSERT(fd >= 0); + + int result = ftruncate(fd, size); + ABSL_ASSERT(result == 0); + + result = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK); + ABSL_ASSERT(result == 0); + + handle_ = OSHandle(fd); + size_ = size; +} + +Memory::Mapping Memory::Map() { + ABSL_ASSERT(is_valid()); + void* addr = + mmap(nullptr, size_, PROT_READ | PROT_WRITE, MAP_SHARED, handle_.fd(), 0); + ABSL_ASSERT(addr && addr != MAP_FAILED); + return Mapping(addr, size_); +} + +} // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/memory_test.cc b/third_party/ipcz/src/reference_drivers/memory_test.cc new file mode 100644 index 0000000..7017852 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/memory_test.cc
@@ -0,0 +1,70 @@ +// Copyright 2022 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 "reference_drivers/memory.h" + +#include <tuple> + +#include "testing/gtest/include/gtest/gtest.h" + +namespace ipcz::reference_drivers { +namespace { + +using MemoryTest = testing::Test; + +TEST_F(MemoryTest, CreateAndMap) { + Memory memory(64); + + Memory::Mapping mapping0 = memory.Map(); + Memory::Mapping mapping1 = memory.Map(); + + int* data0 = mapping0.As<int>(); + int* data1 = mapping1.As<int>(); + + // Each mapping should have a different base address. + EXPECT_NE(data0, data1); + + // But they should be backed by the same physical memory. + data1[0] = 0; + data0[0] = 42; + EXPECT_EQ(42, data1[0]); +} + +TEST_F(MemoryTest, CreateMapClose) { + Memory memory(64); + + Memory::Mapping mapping0 = memory.Map(); + Memory::Mapping mapping1 = memory.Map(); + + // Even with the memfd closed, the mappings above should persist. + memory.reset(); + + int* data0 = mapping0.As<int>(); + int* data1 = mapping1.As<int>(); + EXPECT_NE(data0, data1); + data1[0] = 0; + data0[0] = 42; + EXPECT_EQ(42, data1[0]); +} + +TEST_F(MemoryTest, CreateCloneMapClose) { + Memory memory(64); + Memory clone = memory.Clone(); + + Memory::Mapping mapping0 = memory.Map(); + Memory::Mapping mapping1 = clone.Map(); + + memory.reset(); + clone.reset(); + + int* data0 = mapping0.As<int>(); + int* data1 = mapping1.As<int>(); + EXPECT_NE(data0, data1); + data1[0] = 0; + data0[0] = 42; + EXPECT_EQ(42, data1[0]); +} + +} // namespace +} // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/memory_win.cc b/third_party/ipcz/src/reference_drivers/memory_win.cc new file mode 100644 index 0000000..77ef5b6 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/memory_win.cc
@@ -0,0 +1,48 @@ +// Copyright 2022 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 "reference_drivers/memory.h" + +#include <windows.h> + +#include "reference_drivers/os_handle.h" +#include "third_party/abseil-cpp/absl/base/macros.h" +#include "util/safe_math.h" + +namespace ipcz::reference_drivers { + +void Memory::Mapping::Reset() { + if (base_address_) { + ::UnmapViewOfFile(base_address_); + } +} + +Memory::Memory(size_t size) { + HANDLE h = ::CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, + 0, checked_cast<DWORD>(size), nullptr); + const HANDLE process = ::GetCurrentProcess(); + HANDLE h2; + + // NOTE: DuplicateHandle is called here to remove some permissions from the + // handle (at least WRITE_DAC, among others). This allows the handle to be + // duplicated to other processes under strict sandboxing conditions, which may + // be useful in some test scenarios. + BOOL ok = ::DuplicateHandle(process, h, process, &h2, + FILE_MAP_READ | FILE_MAP_WRITE, FALSE, 0); + ::CloseHandle(h); + ABSL_ASSERT(ok); + + handle_ = OSHandle(h2); + size_ = size; +} + +Memory::Mapping Memory::Map() { + ABSL_ASSERT(is_valid()); + void* addr = ::MapViewOfFile(handle_.handle(), FILE_MAP_READ | FILE_MAP_WRITE, + 0, 0, size_); + ABSL_ASSERT(addr); + return Mapping(addr, size_); +} + +} // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/os_handle.h b/third_party/ipcz/src/reference_drivers/os_handle.h new file mode 100644 index 0000000..1ed3802 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/os_handle.h
@@ -0,0 +1,22 @@ +// Copyright 2022 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 IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_H_ +#define IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_H_ + +#include "build/build_config.h" + +#if BUILDFLAG(IS_WIN) +#include "reference_drivers/os_handle_win.h" +#elif BUILDFLAG(IS_MAC) +#include "reference_drivers/os_handle_mac.h" +#elif BUILDFLAG(IS_FUCHSIA) +#include "reference_drivers/os_handle_fuchsia.h" +#elif BUILDFLAG(IS_POSIX) +#include "reference_drivers/os_handle_posix.h" +#else +#error "Unsupported platform" +#endif + +#endif // IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_H_
diff --git a/third_party/ipcz/src/reference_drivers/os_handle_fuchsia.cc b/third_party/ipcz/src/reference_drivers/os_handle_fuchsia.cc new file mode 100644 index 0000000..c329b7d2 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/os_handle_fuchsia.cc
@@ -0,0 +1,37 @@ +// Copyright 2022 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 "reference_drivers/os_handle.h" + +#include <lib/zx/handle.h> +#include <zircon/status.h> + +#include "third_party/abseil-cpp/absl/base/macros.h" + +namespace ipcz::reference_drivers { + +OSHandle::OSHandle() = default; + +OSHandle::OSHandle(zx::handle handle) : handle_(std::move(handle)) {} + +OSHandle::OSHandle(OSHandle&& other) = default; + +OSHandle& OSHandle::operator=(OSHandle&& other) = default; + +OSHandle::~OSHandle() = default; + +void OSHandle::reset() { + handle_.reset(); +} + +OSHandle OSHandle::Clone() const { + ABSL_ASSERT(is_valid()); + + zx::handle dupe; + zx_status_t status = handle_.duplicate(ZX_RIGHT_SAME_RIGHTS, &dupe); + ABSL_ASSERT(status == ZX_OK); + return OSHandle(std::move(dupe)); +} + +} // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/os_handle_fuchsia.h b/third_party/ipcz/src/reference_drivers/os_handle_fuchsia.h new file mode 100644 index 0000000..4f03657 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/os_handle_fuchsia.h
@@ -0,0 +1,41 @@ +// Copyright 2022 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 IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_FUCHSIA_H_ +#define IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_FUCHSIA_H_ + +#include <lib/zx/handle.h> + +namespace ipcz::reference_drivers { + +// The Fuchsia OSHandle implementation can wrap any zx::handle. +class OSHandle { + public: + OSHandle(); + explicit OSHandle(zx::handle handle); + + OSHandle(const OSHandle&) = delete; + OSHandle& operator=(const OSHandle&) = delete; + + OSHandle(OSHandle&& other); + OSHandle& operator=(OSHandle&& other); + + ~OSHandle(); + + void reset(); + + // Duplicates the underlying handle, returning a new OSHandle to wrap it. The + // handle must be valid. + OSHandle Clone() const; + + bool is_valid() const { return handle_.is_valid(); } + const zx::handle& handle() const { return handle_; } + + private: + zx::handle handle_; +}; + +} // namespace ipcz::reference_drivers + +#endif // IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_FUCHSIA_H_
diff --git a/third_party/ipcz/src/reference_drivers/os_handle_mac.cc b/third_party/ipcz/src/reference_drivers/os_handle_mac.cc new file mode 100644 index 0000000..a62061e --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/os_handle_mac.cc
@@ -0,0 +1,76 @@ +// Copyright 2022 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 "reference_drivers/os_handle.h" + +#include <errno.h> +#include <mach/mach.h> +#include <mach/mach_vm.h> +#include <unistd.h> + +#include <utility> + +#include "third_party/abseil-cpp/absl/base/macros.h" + +namespace ipcz::reference_drivers { + +OSHandle::OSHandle() = default; + +OSHandle::OSHandle(Value value) : value_(value) {} + +OSHandle::OSHandle(OSHandle&& other) + : value_(std::exchange(other.value_, {})) {} + +OSHandle& OSHandle::operator=(OSHandle&& other) { + reset(); + value_ = std::exchange(other.value_, {}); + return *this; +} + +OSHandle::~OSHandle() { + reset(); +} + +void OSHandle::reset() { + if (is_valid_fd()) { + int rv = close(fd()); + ABSL_ASSERT(rv == 0 || errno == EINTR); + } else if (is_valid_mach_send_right()) { + kern_return_t kr = + mach_port_deallocate(mach_task_self(), mach_send_right()); + ABSL_ASSERT(kr == KERN_SUCCESS); + } else if (is_valid_mach_receive_right()) { + kern_return_t kr = mach_port_mod_refs( + mach_task_self(), mach_receive_right(), MACH_PORT_RIGHT_RECEIVE, -1); + ABSL_ASSERT(kr == KERN_SUCCESS); + } + + value_ = {}; +} + +OSHandle OSHandle::Clone() const { + ABSL_ASSERT(is_valid()); + + // Cloning of receive rights is not supported. + ABSL_ASSERT(!absl::holds_alternative<MachReceiveRight>(value_)); + + if (is_valid_fd()) { + int duped_fd = dup(fd()); + ABSL_ASSERT(duped_fd >= 0); + return OSHandle(FileDescriptor(duped_fd)); + } + + if (is_valid_mach_send_right()) { + kern_return_t kr = mach_port_mod_refs(mach_task_self(), mach_send_right(), + MACH_PORT_RIGHT_SEND, 1); + if (kr != KERN_SUCCESS) { + return OSHandle(); + } + return OSHandle(MachSendRight(mach_send_right())); + } + + return {}; +} + +} // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/os_handle_mac.h b/third_party/ipcz/src/reference_drivers/os_handle_mac.h new file mode 100644 index 0000000..1c9d7e2 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/os_handle_mac.h
@@ -0,0 +1,84 @@ +// Copyright 2022 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 IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_MAC_H_ +#define IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_MAC_H_ + +#include <mach/mach.h> + +#include "third_party/abseil-cpp/absl/base/macros.h" +#include "third_party/abseil-cpp/absl/types/variant.h" +#include "util/strong_alias.h" + +namespace ipcz::reference_drivers { + +// The macOS implementation of OSHandle supports wrapping a single Mach send +// right, or a POSIX file descriptor. +class OSHandle { + public: + using FileDescriptor = StrongAlias<class FileDescriptorTag, int>; + using MachSendRight = StrongAlias<class MachSendRightTag, mach_port_t>; + using MachReceiveRight = StrongAlias<class MachReceiveRightTag, mach_port_t>; + using Value = absl:: + variant<absl::monostate, FileDescriptor, MachSendRight, MachReceiveRight>; + + OSHandle(); + explicit OSHandle(Value value); + + OSHandle(const OSHandle&) = delete; + OSHandle& operator=(const OSHandle&) = delete; + + OSHandle(OSHandle&& other); + OSHandle& operator=(OSHandle&& other); + + ~OSHandle(); + + void reset(); + + // Duplicates the underlying handle, returning a new OSHandle to wrap it. + // The handle must be a valid file descriptor or Mach send right. Cloning of + // of Mach receive rights is not supported. + OSHandle Clone() const; + + bool is_valid() const { + return is_valid_fd() || is_valid_mach_send_right() || + is_valid_mach_receive_right(); + } + + bool is_valid_fd() const { + return absl::holds_alternative<FileDescriptor>(value_) && fd() != -1; + } + + bool is_valid_mach_send_right() const { + return absl::holds_alternative<MachSendRight>(value_) && + mach_send_right() != MACH_PORT_NULL; + } + + bool is_valid_mach_receive_right() const { + return absl::holds_alternative<MachReceiveRight>(value_) && + mach_receive_right() != MACH_PORT_NULL; + } + + int fd() const { + ABSL_ASSERT(is_valid_fd()); + return absl::get<FileDescriptor>(value_).value(); + } + + mach_port_t mach_send_right() const { + ABSL_ASSERT(is_valid_mach_send_right()); + return absl::get<MachSendRight>(value_).value(); + } + + mach_port_t mach_receive_right() const { + ABSL_ASSERT(is_valid_mach_receive_right()); + return absl::get<MachReceiveRight>(value_).value(); + } + + private: + Value value_; +}; + +} // namespace ipcz::reference_drivers + +#endif // IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_MAC_H_
diff --git a/third_party/ipcz/src/reference_drivers/os_handle_posix.cc b/third_party/ipcz/src/reference_drivers/os_handle_posix.cc new file mode 100644 index 0000000..c96dbdf --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/os_handle_posix.cc
@@ -0,0 +1,46 @@ +// Copyright 2022 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 "reference_drivers/os_handle.h" + +#include <errno.h> +#include <unistd.h> + +#include <utility> + +#include "third_party/abseil-cpp/absl/base/macros.h" + +namespace ipcz::reference_drivers { + +OSHandle::OSHandle() = default; + +OSHandle::OSHandle(int fd) : fd_(fd) {} + +OSHandle::OSHandle(OSHandle&& other) : fd_(std::exchange(other.fd_, -1)) {} + +OSHandle& OSHandle::operator=(OSHandle&& other) { + reset(); + fd_ = std::exchange(other.fd_, -1); + return *this; +} + +OSHandle::~OSHandle() { + reset(); +} + +void OSHandle::reset() { + int fd = std::exchange(fd_, -1); + if (fd >= 0) { + int rv = close(fd); + ABSL_ASSERT(rv == 0 || errno == EINTR); + } +} + +OSHandle OSHandle::Clone() const { + ABSL_ASSERT(is_valid()); + int dupe = dup(fd_); + return OSHandle(dupe); +} + +} // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/os_handle_posix.h b/third_party/ipcz/src/reference_drivers/os_handle_posix.h new file mode 100644 index 0000000..0ab5efc2 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/os_handle_posix.h
@@ -0,0 +1,40 @@ +// Copyright 2022 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 IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_POSIX_H_ +#define IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_POSIX_H_ + +namespace ipcz::reference_drivers { + +// The POSIX OSHandle implementation wraps a file descriptor. +class OSHandle { + public: + OSHandle(); + explicit OSHandle(int fd); + + OSHandle(const OSHandle&) = delete; + OSHandle& operator=(const OSHandle&) = delete; + + OSHandle(OSHandle&& other); + OSHandle& operator=(OSHandle&& other); + + ~OSHandle(); + + void reset(); + + // Duplicates the underlying handle, returning a new OSHandle to wrap it. The + // handle must be valid. + OSHandle Clone() const; + + bool is_valid() const { return fd_ != -1; } + + int fd() const { return fd_; } + + private: + int fd_ = -1; +}; + +} // namespace ipcz::reference_drivers + +#endif // IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_POSIX_H_
diff --git a/third_party/ipcz/src/reference_drivers/os_handle_win.cc b/third_party/ipcz/src/reference_drivers/os_handle_win.cc new file mode 100644 index 0000000..570f45ea --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/os_handle_win.cc
@@ -0,0 +1,54 @@ +// Copyright 2022 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 "reference_drivers/os_handle.h" + +#include <windows.h> + +#include <utility> + +#include "third_party/abseil-cpp/absl/base/macros.h" + +namespace ipcz::reference_drivers { + +OSHandle::OSHandle() = default; + +OSHandle::OSHandle(HANDLE handle) : handle_(handle) {} + +OSHandle::OSHandle(OSHandle&& other) + : handle_(std::exchange(other.handle_, INVALID_HANDLE_VALUE)) {} + +OSHandle& OSHandle::operator=(OSHandle&& other) { + reset(); + handle_ = std::exchange(other.handle_, INVALID_HANDLE_VALUE); + return *this; +} + +OSHandle::~OSHandle() { + reset(); +} + +void OSHandle::reset() { + HANDLE handle = std::exchange(handle_, INVALID_HANDLE_VALUE); + if (handle != INVALID_HANDLE_VALUE) { + ::CloseHandle(handle); + } +} + +OSHandle OSHandle::Clone() const { + ABSL_ASSERT(is_valid()); + + HANDLE dupe; + BOOL result = + ::DuplicateHandle(::GetCurrentProcess(), handle_, ::GetCurrentProcess(), + &dupe, 0, FALSE, DUPLICATE_SAME_ACCESS); + if (!result) { + return OSHandle(); + } + + ABSL_ASSERT(dupe != INVALID_HANDLE_VALUE); + return OSHandle(dupe); +} + +} // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/os_handle_win.h b/third_party/ipcz/src/reference_drivers/os_handle_win.h new file mode 100644 index 0000000..2506f95 --- /dev/null +++ b/third_party/ipcz/src/reference_drivers/os_handle_win.h
@@ -0,0 +1,42 @@ +// Copyright 2022 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 IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_WIN_H_ +#define IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_WIN_H_ + +#include <windows.h> + +namespace ipcz::reference_drivers { + +// The Windows OSHandle implementation can wrap any HANDLE value. +class OSHandle { + public: + OSHandle(); + explicit OSHandle(HANDLE handle); + + OSHandle(const OSHandle&) = delete; + OSHandle& operator=(const OSHandle&) = delete; + + OSHandle(OSHandle&& other); + OSHandle& operator=(OSHandle&& other); + + ~OSHandle(); + + void reset(); + + // Duplicates the underlying handle, returning a new OSHandle to wrap it. The + // handle must be valid. + OSHandle Clone() const; + + bool is_valid() const { return handle_ != INVALID_HANDLE_VALUE; } + + HANDLE handle() const { return handle_; } + + private: + HANDLE handle_ = INVALID_HANDLE_VALUE; +}; + +} // namespace ipcz::reference_drivers + +#endif // IPCZ_SRC_REFERENCE_DRIVERS_OS_HANDLE_WIN_H_
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index ece1e5a2..78dfc930 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -381,11 +381,11 @@ 'ios-simulator-cronet': 'ios_cronet_xctest', 'ios-simulator-multi-window': 'ios_simulator_debug_static_bot_xctest', 'ios-webkit-tot': 'ios_simulator_debug_static_bot_xctest_no_lld', - 'ios14-beta-simulator': 'ios_simulator_debug_static_bot_xctest', - 'ios14-sdk-simulator': 'ios_simulator_debug_static_bot_xctest', 'ios15-beta-simulator': 'ios_simulator_debug_static_bot_xctest', 'ios15-sdk-device': 'ios_device_release_static_bot_xctest', 'ios15-sdk-simulator': 'ios_simulator_debug_static_bot_xctest', + 'ios16-beta-simulator': 'ios_simulator_debug_static_bot_xctest', + 'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest', 'lacros-amd64-generic-rel (goma cache silo)': 'chromeos_amd64-generic_lacros_rel', 'lacros-amd64-generic-rel (reclient)': 'chromeos_amd64-generic-vm_lacros_rel_reclient', 'lacros-amd64-generic-rel-fyi': 'chromeos_amd64-generic_lacros_rel_reclient', @@ -1160,10 +1160,10 @@ 'ios-simulator-multi-window': 'ios_simulator_debug_static_bot_xctest', 'ios-simulator-noncq': 'ios_simulator_debug_static_bot_xctest', 'ios-simulator-rts': 'ios_simulator_code_coverage_partial_instrumentation_xctest', - 'ios14-beta-simulator': 'ios_simulator_debug_static_bot_xctest', - 'ios14-sdk-simulator': 'ios_simulator_debug_static_bot_xctest', 'ios15-beta-simulator': 'ios_simulator_debug_static_bot_xctest', 'ios15-sdk-simulator': 'ios_simulator_debug_static_bot_xctest', + 'ios16-beta-simulator': 'ios_simulator_debug_static_bot_xctest', + 'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest', 'mac-arm64-on-arm64-rel': 'mac_arm64_release_trybot', 'mac-builder-next-rel': 'mac_arm64_gpu_tests_release_bot_minimal_symbols_no_nacl', 'mac-clang-tidy-rel': 'release_trybot',
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json index 3f28e21..d86dc71b 100644 --- a/tools/mb/mb_config_expectations/chromium.fyi.json +++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -804,32 +804,6 @@ "use_lld": false } }, - "ios14-beta-simulator": { - "gn_args": { - "enable_run_ios_unittests_with_xctest": true, - "ios_set_attributes_for_xcode_project_generation": false, - "is_component_build": false, - "is_debug": true, - "symbol_level": 1, - "target_cpu": "x64", - "target_environment": "simulator", - "target_os": "ios", - "use_goma": true - } - }, - "ios14-sdk-simulator": { - "gn_args": { - "enable_run_ios_unittests_with_xctest": true, - "ios_set_attributes_for_xcode_project_generation": false, - "is_component_build": false, - "is_debug": true, - "symbol_level": 1, - "target_cpu": "x64", - "target_environment": "simulator", - "target_os": "ios", - "use_goma": true - } - }, "ios15-beta-simulator": { "gn_args": { "enable_run_ios_unittests_with_xctest": true, @@ -870,6 +844,32 @@ "use_goma": true } }, + "ios16-beta-simulator": { + "gn_args": { + "enable_run_ios_unittests_with_xctest": true, + "ios_set_attributes_for_xcode_project_generation": false, + "is_component_build": false, + "is_debug": true, + "symbol_level": 1, + "target_cpu": "x64", + "target_environment": "simulator", + "target_os": "ios", + "use_goma": true + } + }, + "ios16-sdk-simulator": { + "gn_args": { + "enable_run_ios_unittests_with_xctest": true, + "ios_set_attributes_for_xcode_project_generation": false, + "is_component_build": false, + "is_debug": true, + "symbol_level": 1, + "target_cpu": "x64", + "target_environment": "simulator", + "target_os": "ios", + "use_goma": true + } + }, "lacros-amd64-generic-rel (goma cache silo)": { "args_file": "//build/args/chromeos/amd64-generic-crostoolchain.gni", "gn_args": {
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json index cbd24f5..1b53e5f 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
@@ -412,32 +412,6 @@ "use_goma": true } }, - "ios14-beta-simulator": { - "gn_args": { - "enable_run_ios_unittests_with_xctest": true, - "ios_set_attributes_for_xcode_project_generation": false, - "is_component_build": false, - "is_debug": true, - "symbol_level": 1, - "target_cpu": "x64", - "target_environment": "simulator", - "target_os": "ios", - "use_goma": true - } - }, - "ios14-sdk-simulator": { - "gn_args": { - "enable_run_ios_unittests_with_xctest": true, - "ios_set_attributes_for_xcode_project_generation": false, - "is_component_build": false, - "is_debug": true, - "symbol_level": 1, - "target_cpu": "x64", - "target_environment": "simulator", - "target_os": "ios", - "use_goma": true - } - }, "ios15-beta-simulator": { "gn_args": { "enable_run_ios_unittests_with_xctest": true, @@ -464,6 +438,32 @@ "use_goma": true } }, + "ios16-beta-simulator": { + "gn_args": { + "enable_run_ios_unittests_with_xctest": true, + "ios_set_attributes_for_xcode_project_generation": false, + "is_component_build": false, + "is_debug": true, + "symbol_level": 1, + "target_cpu": "x64", + "target_environment": "simulator", + "target_os": "ios", + "use_goma": true + } + }, + "ios16-sdk-simulator": { + "gn_args": { + "enable_run_ios_unittests_with_xctest": true, + "ios_set_attributes_for_xcode_project_generation": false, + "is_component_build": false, + "is_debug": true, + "symbol_level": 1, + "target_cpu": "x64", + "target_environment": "simulator", + "target_os": "ios", + "use_goma": true + } + }, "mac-arm64-on-arm64-rel": { "gn_args": { "dcheck_always_on": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 6d0dec1..3f3091b4 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -38598,7 +38598,7 @@ <int value="2774" label="OBSOLETE_CSSValueAppearanceButtonForNonButtonRendered"/> <int value="2775" label="OBSOLETE_CSSValueAppearanceButtonForOthersRendered"/> - <int value="2776" label="CustomCursorIntersectsViewport"/> + <int value="2776" label="OBSOLETE_CustomCursorIntersectsViewport"/> <int value="2777" label="OBSOLETE_ClientHintsLang"/> <int value="2778" label="LinkRelPreloadImageSrcset"/> <int value="2779" label="V8HTMLMediaElement_Remote_AttributeGetter"/> @@ -41681,6 +41681,14 @@ <int value="2" label="Unable to open"/> </enum> +<enum name="FileManagerExtractStatus"> + <int value="0" label="Success"/> + <int value="1" label="Cancelled"/> + <int value="2" label="Low Disk Space"/> + <int value="3" label="Bad Password"/> + <int value="4" label="Unknown Error"/> +</enum> + <enum name="FileManagerFormatFileSystemType"> <int value="0" label="Unknown"/> <int value="1" label="FAT32"/> @@ -57803,6 +57811,8 @@ <int value="75747474" label="disable-webview-signin-flow"/> <int value="77886794" label="AllowRepeatedUpdates:enabled"/> <int value="77946316" label="PrefixWebAppWindowsWithAppName:disabled"/> + <int value="78900745" + label="SharedHighlightingRefinedMaxContextWords:disabled"/> <int value="78998551" label="disable-hosted-app-shim-creation"/> <int value="79094339" label="VrLaunchIntents:enabled"/> <int value="79503461" label="disable-account-consistency"/> @@ -59518,6 +59528,8 @@ <int value="1226624874" label="Mus:disabled"/> <int value="1226676061" label="PageInfoV2Desktop:enabled"/> <int value="1226760549" label="LauncherGameSearch:enabled"/> + <int value="1226782541" + label="SharedHighlightingRefinedMaxContextWords:enabled"/> <int value="1227633129" label="NtpChromeCartModule:disabled"/> <int value="1228054141" label="OverrideUnsupportedPageLanguageForHrefTranslate:enabled"/> @@ -84321,6 +84333,8 @@ <int value="12" label="At least one segment does not have default signals"/> <int value="13" label="At least one segment default model execution failed"/> <int value="14" label="At least one segment default model missing metadata"/> + <int value="15" + label="At least one segment on demand tflite model execution failed"/> </enum> <enum name="SelectedNewTabCreationOption">
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml index a3752c2a..7732c62 100644 --- a/tools/metrics/histograms/metadata/blink/histograms.xml +++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -490,6 +490,17 @@ </summary> </histogram> +<histogram name="Blink.Clipboard.HasTransientUserActivation" enum="Boolean" + expires_after="2022-08-01"> + <owner>asully@chromium.org</owner> + <owner>snianu@microsoft.com</owner> + <owner>chrome-owp-storage@google.com</owner> + <summary> + Records if a transient user activation is present or not when the web + authors execute the async clipboard read/write call. + </summary> +</histogram> + <histogram name="Blink.ColorGamut.Destination" enum="Gamut" expires_after="M85"> <owner>brianosman@chromium.org</owner> <owner>mcasas@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml index a9322b4..3185a97e 100644 --- a/tools/metrics/histograms/metadata/chromeos/histograms.xml +++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -42,6 +42,10 @@ <owner>cros-connectivity@google.com</owner> <owner>hsuregan@chromium.org</owner> </variant> + <variant name="FakeKeyboardHeuristic" summary="Fake Keyboard Heuristic"> + <owner>wmahon@chromium.org</owner> + <owner>chromeos-tango@google.com</owner> + </variant> <variant name="FastPair" summary="Fast Pair"> <owner>shanefitz@google.com</owner> <owner>julietlevesque@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/compositing/histograms.xml b/tools/metrics/histograms/metadata/compositing/histograms.xml index 2d7a23d..0cce5fa 100644 --- a/tools/metrics/histograms/metadata/compositing/histograms.xml +++ b/tools/metrics/histograms/metadata/compositing/histograms.xml
@@ -351,19 +351,6 @@ </histogram> <histogram - name="Compositing.Display.OverlayProcessorOzone.IsCandidateSharedImage" - enum="Boolean" expires_after="2021-09-19"> - <owner>samans@chromium.org</owner> - <owner>rjkroege@chromium.org</owner> - <summary> - Indicates whether the OverlayCandidate passed to - OverlayCandidateValidatorOzone is backed by a SharedImage (as opposed to a - legacy mailbox). Recorded for every candidate in every overlay configuration - passed to OverlayProcessorOzone. - </summary> -</histogram> - -<histogram name="Compositing.Display.OverlayProcessorOzone.MaxOverlaysSupported" units="units" expires_after="2022-11-30"> <owner>khaslett@chromium.org</owner> @@ -376,16 +363,6 @@ </summary> </histogram> -<histogram name="Compositing.Display.OverlayProcessorOzone.SharedImageExists" - enum="Boolean" expires_after="2021-09-19"> - <owner>samans@chromium.org</owner> - <owner>rjkroege@chromium.org</owner> - <summary> - Indicates whether the SharedImage corresponding to the OverlayCandidate was - found. Reported for every OverlayCandidate that is backed by a SharedImage. - </summary> -</histogram> - <histogram name="Compositing.Display.OverlayProcessorUsingStrategy.CandidateCombinationPreviouslySucceeded" enum="Boolean" expires_after="2022-11-30">
diff --git a/tools/metrics/histograms/metadata/direct/histograms.xml b/tools/metrics/histograms/metadata/direct/histograms.xml index dc06431..625c947 100644 --- a/tools/metrics/histograms/metadata/direct/histograms.xml +++ b/tools/metrics/histograms/metadata/direct/histograms.xml
@@ -22,91 +22,6 @@ <histograms> -<histogram - name="DirectWrite.Fonts.Content.FallbackFamilyAndStyleForCodepointTime" - units="microseconds" expires_after="2022-06-15"> - <owner>sky@chromium.org</owner> - <owner>jam@chromium.org</owner> - <summary> - The time in microseconds it takes to execute - DWriteFontProxyImpl::FallbackFamilyAndStyleForCodepoint. - - This metric is reported for all users. - </summary> -</histogram> - -<histogram name="DirectWrite.Fonts.Content.FindFamilyTime" units="microseconds" - expires_after="2022-10-16"> - <owner>sky@chromium.org</owner> - <owner>jam@chromium.org</owner> - <summary> - The time in microseconds it takes to execute - DWriteFontProxyImpl::FindFamily. - - This metric is reported for all users. - </summary> -</histogram> - -<histogram name="DirectWrite.Fonts.Content.GetFamilyCountTime" - units="microseconds" expires_after="2022-10-16"> - <owner>sky@chromium.org</owner> - <owner>jam@chromium.org</owner> - <summary> - The time in microseconds it takes to execute - DWriteFontProxyImpl::GetFamilyCount. - - This metric is reported for all users. - </summary> -</histogram> - -<histogram name="DirectWrite.Fonts.Content.GetFamilyNamesTime" - units="microseconds" expires_after="2022-06-15"> - <owner>sky@chromium.org</owner> - <owner>jam@chromium.org</owner> - <summary> - The time in microseconds it takes to execute - DWriteFontProxyImpl::GetFamilyNames. - - This metric is reported for all users. - </summary> -</histogram> - -<histogram name="DirectWrite.Fonts.Content.GetFontFilesTime" - units="microseconds" expires_after="2022-10-16"> - <owner>sky@chromium.org</owner> - <owner>jam@chromium.org</owner> - <summary> - The time in microseconds it takes to execute - DWriteFontProxyImpl::GetFontFiles. - - This metric is reported for all users. - </summary> -</histogram> - -<histogram name="DirectWrite.Fonts.Content.InitializeTime" units="microseconds" - expires_after="2022-06-15"> - <owner>sky@chromium.org</owner> - <owner>jam@chromium.org</owner> - <summary> - The time in microseconds it takes to execute - DWriteFontProxyImpl::Initialize. - - This metric is reported for all users. - </summary> -</histogram> - -<histogram name="DirectWrite.Fonts.Content.MapCharactersTime" - units="microseconds" expires_after="2022-10-16"> - <owner>sky@chromium.org</owner> - <owner>jam@chromium.org</owner> - <summary> - The time in microseconds it takes to execute - DWriteFontProxyImpl::MapCharacters. - - This metric is reported for all users. - </summary> -</histogram> - <histogram name="DirectWrite.Fonts.Gfx.InitializeLoopCount" units="units" expires_after="2022-10-15"> <owner>drott@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/file/histograms.xml b/tools/metrics/histograms/metadata/file/histograms.xml index 1c3141c..f58fff3 100644 --- a/tools/metrics/histograms/metadata/file/histograms.xml +++ b/tools/metrics/histograms/metadata/file/histograms.xml
@@ -275,6 +275,13 @@ <summary>Tracks success rate of pinning files in Drive.</summary> </histogram> +<histogram name="FileBrowser.ExtractTask.Status" + enum="FileManagerExtractStatus" expires_after="M113"> + <owner>adanilo@chromium.org</owner> + <owner>src/ui/file_manager/OWNERS</owner> + <summary>Tracks success/error rate of extracting archive contents.</summary> +</histogram> + <histogram name="FileBrowser.FileSystemProviderMounted" enum="FileSystemProviderMountType" expires_after="2023-04-10"> <owner>simmonsjosh@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml index 54c0658..858967e 100644 --- a/tools/metrics/histograms/metadata/history/histograms.xml +++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -1028,6 +1028,25 @@ </token> </histogram> +<histogram name="History.Clusters.WebUISessionDuration" units="ms" + expires_after="2022-11-30"> + <owner>tommycli@chromium.org</owner> + <owner>chrome-journeys@google.com</owner> + <summary> + Records the amount of time the Journeys WebUI is open. + + This timer is started when the Journeys WebUI is loaded. The Journeys WebUI + is loaded when either the user directly goes to the Journeys WebUI, or when + the user switches to the Journeys tab from a different tab. + + The timer is stopped and the elapsed time recorded when either the whole + WebUI is closed, or if the user disables the Journeys preference, or if the + user switches tabs off the Journeys tab onto a different one. + + Elapsed times longer than one hour are recorded as one hour. + </summary> +</histogram> + <histogram name="History.DatabaseAdvancedMetricsTime" units="ms" expires_after="M77"> <owner>shess@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/language/histograms.xml b/tools/metrics/histograms/metadata/language/histograms.xml index 116c95f..8dfefb5 100644 --- a/tools/metrics/histograms/metadata/language/histograms.xml +++ b/tools/metrics/histograms/metadata/language/histograms.xml
@@ -67,7 +67,7 @@ </histogram> <histogram name="LanguageSettings.Actions" enum="LanguageSettingsActionType" - expires_after="2022-06-30"> + expires_after="2022-09-11"> <owner>perrier@chromium.org</owner> <owner>chrome-language@google.com</owner> <summary> @@ -132,7 +132,7 @@ </histogram> <histogram name="LanguageSettings.AppLanguagePrompt.Language" - enum="LocaleCodeISO639" expires_after="2022-06-30"> + enum="LocaleCodeISO639" expires_after="2022-09-11"> <owner>perrier@chromium.org</owner> <owner>chrome-language@google.com</owner> <summary> @@ -287,7 +287,7 @@ </histogram> <histogram name="LanguageUsage.UI.Android.Correctness" - enum="LanguageUsage.UI.Android.Correctness" expires_after="2022-06-30"> + enum="LanguageUsage.UI.Android.Correctness" expires_after="2022-09-11"> <owner>perrier@chromium.org</owner> <owner>chrome-language@google.com</owner> <summary> @@ -410,7 +410,7 @@ </histogram> <histogram name="LanguageUsage.ULP.Initiation.Status{AccountType}" - enum="ULPInitiationStatus" expires_after="2022-06-30"> + enum="ULPInitiationStatus" expires_after="2022-09-11"> <owner>jds@google.com</owner> <owner>chrome-language@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/platform/histograms.xml b/tools/metrics/histograms/metadata/platform/histograms.xml index a8a6970..f3cf390 100644 --- a/tools/metrics/histograms/metadata/platform/histograms.xml +++ b/tools/metrics/histograms/metadata/platform/histograms.xml
@@ -714,7 +714,19 @@ <summary> The percentage of CPU time that the Missive daemon has been using. The CPU usage is not expected to be high and any usage beyond 100% is considered to - be in the overflow bucket. This is reported once every 10 minutes. + be in the overflow bucket. This is reported once every 10 minutes and only + if the Missive daemon is running. + </summary> +</histogram> + +<histogram name="Platform.Missive.MemoryUsage" units="0.1MiB" + expires_after="2023-05-03"> + <owner>xuhong@chromium.org</owner> + <owner>lbaraz@chromium.org</owner> + <owner>cros-reporting-team@google.com</owner> + <summary> + The amount of memory that the Missive daemon has been using. This is + reported once every 10 minutes and only if the Missive daemon is running. </summary> </histogram> @@ -725,7 +737,8 @@ <owner>cros-reporting-team@google.com</owner> <summary> The amount of disk storage that the Missive daemon has been using for - storing encrypted records. This is reported once every 10 minutes. + storing encrypted records. This is reported once every 10 minutes and only + if the Missive daemon is running. </summary> </histogram>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 8a33c29..90d9a37 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@ "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "win": { - "hash": "ce86af6a7e4d2258fa27e5356ff6663139e9dea5", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/6ebcd58ed94f88099a1d8ab5fb28fa28bc0d3e9a/trace_processor_shell.exe" + "hash": "dfa666ba78c81ad93ac36b4893c39fde6419e661", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/370def59dcc5b6423f805754160cab7c5b772c2d/trace_processor_shell.exe" }, "linux_arm": { "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893", "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "mac": { - "hash": "f9e92827759f3431ba8ce181abb1fb48187cfe84", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/6ebcd58ed94f88099a1d8ab5fb28fa28bc0d3e9a/trace_processor_shell" + "hash": "64fd82d275dcd99827bdd14de3d41f70c6363a3c", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/a4217a18debea8b9f02ab15f65097533568bf810/trace_processor_shell" }, "mac_arm64": { "hash": "e1ad4861384b06d911a65f035317914b8cc975c6", "full_remote_path": "perfetto-luci-artifacts/v25.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "1cd581f6e67132e4a29f8316fe516c3bd42ab3ff", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/6ebcd58ed94f88099a1d8ab5fb28fa28bc0d3e9a/trace_processor_shell" + "hash": "cba2db3019906c1d886a8436d402bd359af1eec7", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/370def59dcc5b6423f805754160cab7c5b772c2d/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/aura/screen_ozone.cc b/ui/aura/screen_ozone.cc index d133110..a78a6a4 100644 --- a/ui/aura/screen_ozone.cc +++ b/ui/aura/screen_ozone.cc
@@ -13,10 +13,13 @@ namespace aura { -ScreenOzone::ScreenOzone() = default; +ScreenOzone::ScreenOzone() { + DCHECK(!display::Screen::HasScreen()); + display::Screen::SetScreenInstance(this); +} ScreenOzone::~ScreenOzone() { - display::Screen::SetScreenInstance(old_screen_); + display::Screen::SetScreenInstance(nullptr); } void ScreenOzone::Initialize() { @@ -34,6 +37,11 @@ } } +// static +bool ScreenOzone::IsOzoneInitialized() { + return ui::OzonePlatform::IsInitialized(); +} + gfx::Point ScreenOzone::GetCursorScreenPoint() { return platform_screen_->GetCursorScreenPoint(); } @@ -149,4 +157,17 @@ void ScreenOzone::OnBeforePlatformScreenInit() {} +ScopedScreenOzone::ScopedScreenOzone(const base::Location& location) + : ScopedNativeScreen(/*call_maybe_init=*/false, location) { + MaybeInit(); +} + +ScopedScreenOzone::~ScopedScreenOzone() = default; + +display::Screen* ScopedScreenOzone::CreateScreen() { + auto* screen = new ScreenOzone(); + screen->Initialize(); + return screen; +} + } // namespace aura
diff --git a/ui/aura/screen_ozone.h b/ui/aura/screen_ozone.h index 980c083b..2970a0e 100644 --- a/ui/aura/screen_ozone.h +++ b/ui/aura/screen_ozone.h
@@ -60,6 +60,8 @@ virtual gfx::NativeWindow GetNativeWindowFromAcceleratedWidget( gfx::AcceleratedWidget widget) const; + static bool IsOzoneInitialized(); + protected: ui::PlatformScreen* platform_screen() { return platform_screen_.get(); } @@ -73,10 +75,22 @@ virtual void OnBeforePlatformScreenInit(); - display::Screen* const old_screen_ = display::Screen::SetScreenInstance(this); std::unique_ptr<ui::PlatformScreen> platform_screen_; }; +// ScopedScreenOzone creates a ScreenOzone instead of NativeScreen +// (created by `CreateNativeScreen()`) if the screen hasn't been set. +class AURA_EXPORT ScopedScreenOzone : public display::ScopedNativeScreen { + public: + explicit ScopedScreenOzone(const base::Location& location = FROM_HERE); + ScopedScreenOzone(const ScopedScreenOzone&) = delete; + ScopedScreenOzone operator=(const ScopedScreenOzone&) = delete; + ~ScopedScreenOzone() override; + + private: + display::Screen* CreateScreen() override; +}; + } // namespace aura #endif // UI_AURA_SCREEN_OZONE_H_
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 4c996a80..2efba1d 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -541,6 +541,13 @@ deps += [ "//third_party/fontconfig" ] } + if (is_chromeos_lacros) { + deps += [ + "//chromeos/crosapi/cpp:crosapi_constants", + "//chromeos/lacros:lacros_paths", + ] + } + if (use_glib) { configs += [ "//build/config/linux:glib" ] sources += [
diff --git a/ui/base/DEPS b/ui/base/DEPS index be9a7fd..d5f0903 100644 --- a/ui/base/DEPS +++ b/ui/base/DEPS
@@ -1,4 +1,6 @@ include_rules = [ + "+chromeos/crosapi/cpp/crosapi_constants.h", + "+chromeos/lacros/lacros_paths.h", "+components/vector_icons", "+components/version_info", "+media/media_buildflags.h",
diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc index 2888b12..2222f4a 100644 --- a/ui/base/resource/resource_bundle.cc +++ b/ui/base/resource/resource_bundle.cc
@@ -98,6 +98,7 @@ ResourceBundle* g_shared_instance_ = nullptr; +#if !BUILDFLAG(IS_CHROMEOS_LACROS) base::FilePath GetResourcesPakFilePath(const std::string& pak_name) { base::FilePath path; if (base::PathService::Get(base::DIR_ASSETS, &path)) @@ -110,6 +111,7 @@ return base::FilePath(pak_name.c_str()); #endif // BUILDFLAG(IS_WIN) } +#endif // !BUILDFLAG(IS_CHROMEOS_LACROS) SkBitmap CreateEmptyBitmap() { SkBitmap bitmap; @@ -949,6 +951,7 @@ #endif } +#if !BUILDFLAG(IS_CHROMEOS_LACROS) void ResourceBundle::LoadChromeResources() { // Always load the 1x data pack first as the 2x data pack contains both 1x and // 2x images. The 1x data pack only has 1x images, thus passes in an accurate @@ -963,6 +966,7 @@ GetResourcesPakFilePath("chrome_200_percent.pak"), k200Percent); } } +#endif // !BUILDFLAG(IS_CHROMEOS_LACROS) void ResourceBundle::AddDataPackFromPathInternal( const base::FilePath& path,
diff --git a/ui/base/resource/resource_bundle_lacros.cc b/ui/base/resource/resource_bundle_lacros.cc index 3badf24..fdfc963 100644 --- a/ui/base/resource/resource_bundle_lacros.cc +++ b/ui/base/resource/resource_bundle_lacros.cc
@@ -4,11 +4,42 @@ #include "ui/base/resource/resource_bundle.h" +#include "base/command_line.h" +#include "base/files/file_util.h" #include "base/logging.h" +#include "base/path_service.h" +#include "chromeos/crosapi/cpp/crosapi_constants.h" +#include "chromeos/lacros/lacros_paths.h" #include "ui/base/resource/data_pack_with_resource_sharing_lacros.h" +#include "ui/base/ui_base_switches.h" namespace ui { +namespace { + +constexpr char k100PercentPack[] = "chrome_100_percent.pak"; +constexpr char k200PercentPack[] = "chrome_200_percent.pak"; + +base::FilePath GetResourcesPakFilePath(const std::string& pak_name) { + base::FilePath path; + if (base::PathService::Get(base::DIR_ASSETS, &path)) + return path.AppendASCII(pak_name.c_str()); + + // Return just the name of the pak file. + return base::FilePath(pak_name.c_str()); +} + +base::FilePath GetGeneratedFilePath(const std::string& pak_name) { + base::FilePath path; + if (base::PathService::Get(chromeos::lacros_paths::USER_DATA_DIR, &path)) + return path.AppendASCII(pak_name.c_str()); + + // Return just the name of the pak file. + return base::FilePath(pak_name.c_str()); +} + +} // namespace + void ResourceBundle::AddDataPackFromPathWithAshResourcesInternal( const base::FilePath& shared_resource_path, const base::FilePath& ash_path, @@ -23,7 +54,8 @@ std::make_unique<DataPack>(scale_factor); if (data_pack_with_lacros_resource->LoadFromPath(lacros_path)) { LOG(WARNING) - << "Failed to load shared resource data pack from file. " + << "Failed to load shared resource data pack " << shared_resource_path + << ": " << "Use lacros resource data pack instead of shared resource " << "data pack."; AddResourceHandle(std::move(data_pack_with_lacros_resource)); @@ -52,4 +84,43 @@ lacros_path, scale_factor, true); } +void ResourceBundle::LoadChromeResources() { + // Always load the 1x data pack first as the 2x data pack contains both 1x and + // 2x images. The 1x data pack only has 1x images, thus passes in an accurate + // scale factor to gfx::ImageSkia::AddRepresentation. + + base::FilePath ash_resources_dir; + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(switches::kEnableResourcesFileSharing) || + !base::PathService::Get(chromeos::lacros_paths::ASH_RESOURCES_DIR, + &ash_resources_dir)) { + // If resource sharing feature is not enabled or ash resources dir path is + // not available, use DataPack instead. + if (IsScaleFactorSupported(k100Percent)) { + AddDataPackFromPath(GetResourcesPakFilePath(k100PercentPack), + k100Percent); + } + + if (IsScaleFactorSupported(k200Percent)) { + AddOptionalDataPackFromPath(GetResourcesPakFilePath(k200PercentPack), + k200Percent); + } + return; + } + + if (IsScaleFactorSupported(k100Percent)) { + AddDataPackFromPathWithAshResources( + GetGeneratedFilePath(crosapi::kSharedChrome100PercentPackName), + ash_resources_dir.Append(k100PercentPack), + GetResourcesPakFilePath(k200PercentPack), k100Percent); + } + + if (IsScaleFactorSupported(k200Percent)) { + AddOptionalDataPackFromPathWithAshResources( + GetGeneratedFilePath(crosapi::kSharedChrome200PercentPackName), + ash_resources_dir.Append(k200PercentPack), + GetResourcesPakFilePath(k200PercentPack), k200Percent); + } +} + } // namespace ui
diff --git a/ui/base/test/cocoa_helper.h b/ui/base/test/cocoa_helper.h index 4ec09b1..c9030fe 100644 --- a/ui/base/test/cocoa_helper.h +++ b/ui/base/test/cocoa_helper.h
@@ -13,6 +13,7 @@ #import "base/mac/scoped_nsobject.h" #import "base/strings/sys_string_conversions.h" #include "testing/platform_test.h" +#include "ui/display/screen.h" // CocoaTestHelperWindow behaves differently from a regular NSWindow in the // following ways: @@ -74,6 +75,8 @@ CocoaTestHelperWindow* test_window(); private: + display::ScopedNativeScreen screen_; + // Return a set of currently open windows. Avoiding NSArray so // contents aren't retained, the pointer values can only be used for // comparison purposes. Using std::set to make progress-checking
diff --git a/ui/display/display.cc b/ui/display/display.cc index 3693f89..2871e5b 100644 --- a/ui/display/display.cc +++ b/ui/display/display.cc
@@ -34,7 +34,7 @@ // -1.0, we read the forced device scale factor again. float g_forced_device_scale_factor = -1.0; -// An alloance error epsilon cauesd by fractional scale factor to produce +// An allowance error epsilon caused by fractional scale factor to produce // expected DP display size. constexpr float kDisplaySizeAllowanceEpsilon = 0.01f;
diff --git a/ui/display/display.h b/ui/display/display.h index 5a9b7ec..faaf504 100644 --- a/ui/display/display.h +++ b/ui/display/display.h
@@ -172,7 +172,7 @@ gfx::Insets GetWorkAreaInsets() const; // Sets the device scale factor and display bounds in pixel. This - // updates the work are using the same insets between old bounds and + // updates the work area using the same insets between old bounds and // work area. void SetScaleAndBounds(float device_scale_factor, const gfx::Rect& bounds_in_pixel);
diff --git a/ui/display/display_list.h b/ui/display/display_list.h index 2eb14bc..4c90bea3 100644 --- a/ui/display/display_list.h +++ b/ui/display/display_list.h
@@ -71,6 +71,9 @@ bool IsValid() const; base::ObserverList<DisplayObserver>* observers() { return &observers_; } + const base::ObserverList<DisplayObserver>* observers() const { + return &observers_; + } private: // A non-const version of FindDisplayById.
diff --git a/ui/display/screen.cc b/ui/display/screen.cc index 2225ae6..b972388 100644 --- a/ui/display/screen.cc +++ b/ui/display/screen.cc
@@ -31,8 +31,7 @@ // static Screen* Screen::GetScreen() { -#if BUILDFLAG(IS_APPLE) - // TODO(scottmg): https://crbug.com/558054 +#if BUILDFLAG(IS_IOS) if (!g_screen) g_screen = CreateNativeScreen(); #endif @@ -40,10 +39,23 @@ } // static -Screen* Screen::SetScreenInstance(Screen* instance) { +Screen* Screen::SetScreenInstance(Screen* instance, + const base::Location& location) { + // Do not allow screen instance override. The screen object has a lot of + // states, such as current display settings as well as observers, and safely + // transferring these to new screen implementation is very difficult and not + // safe. If you hit the DCHECK in a test, please look for other examples that + // that set a test screen instance in the setup process. + DCHECK(!g_screen || !instance || (instance && instance->shutdown_)) + << "fail=" << location.ToString(); return std::exchange(g_screen, instance); } +// static +bool Screen::HasScreen() { + return !!g_screen; +} + void Screen::SetCursorScreenPointForTesting(const gfx::Point& point) { NOTIMPLEMENTED_LOG_ONCE(); } @@ -213,4 +225,49 @@ return result; } +#if !BUILDFLAG(IS_ANDROID) + +ScopedNativeScreen::ScopedNativeScreen(const base::Location& location) { + MaybeInit(location); +} + +ScopedNativeScreen::ScopedNativeScreen(bool call_maybe_init, + const base::Location& location) { + if (call_maybe_init) + MaybeInit(location); +} + +ScopedNativeScreen::~ScopedNativeScreen() { + Shutdown(); +} + +void ScopedNativeScreen::MaybeInit(const base::Location& location) { + maybe_init_called_ = true; + if (!Screen::HasScreen()) { +#if BUILDFLAG(IS_IOS) + Screen::GetScreen(); +#else + screen_ = base::WrapUnique(CreateScreen()); + // ScreenOzone and DesktopScreenWin sets the instance by itself. + if (Screen::GetScreen() != screen_.get()) + Screen::SetScreenInstance(screen_.get(), location); +#endif + } +} + +void ScopedNativeScreen::Shutdown() { + DCHECK(maybe_init_called_); + if (screen_) { + DCHECK_EQ(screen_.get(), Screen::GetScreen()); + Screen::SetScreenInstance(nullptr); + screen_.reset(); + } +} + +Screen* ScopedNativeScreen::CreateScreen() { + return CreateNativeScreen(); +} + +#endif + } // namespace display
diff --git a/ui/display/screen.h b/ui/display/screen.h index 3771a345..a86c5b6 100644 --- a/ui/display/screen.h +++ b/ui/display/screen.h
@@ -9,8 +9,9 @@ #include <set> #include <vector> +#include "base/location.h" #include "base/values.h" -#include "build/chromeos_buildflags.h" +#include "build/build_config.h" #include "ui/display/display.h" #include "ui/display/display_export.h" #include "ui/display/screen_infos.h" @@ -47,13 +48,20 @@ virtual ~Screen(); - // Retrieves the single Screen object; this may be null (e.g. in some tests). + // Retrieves the single Screen object; this may be null if it's not already + // created, except for IOS where it creates a native screen instance + // automatically. static Screen* GetScreen(); + // Returns whether a Screen singleton exists or not. + static bool HasScreen(); + + // [Deprecated] as a public method. Do not use this. // Sets the global screen. Returns the previously installed screen, if any. // NOTE: this does not take ownership of |screen|. Tests must be sure to reset // any state they install. - static Screen* SetScreenInstance(Screen* instance); + static Screen* SetScreenInstance(Screen* instance, + const base::Location& location = FROM_HERE); // Returns the current absolute position of the mouse pointer. virtual gfx::Point GetCursorScreenPoint() = 0; @@ -198,6 +206,8 @@ virtual bool SetScreenSaverSuspended(bool suspend); #endif // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX) + void set_shutdown(bool shutdown) { shutdown_ = shutdown; } + private: friend class ScopedDisplayForNewWindows; @@ -208,6 +218,9 @@ static gfx::NativeWindow GetWindowForView(gfx::NativeView view); + // A flag indicates that the instance is a special one used during shutdown. + bool shutdown_ = false; + int64_t display_id_for_new_windows_; int64_t scoped_display_id_for_new_windows_ = display::kInvalidDisplayId; @@ -216,7 +229,41 @@ #endif // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX) }; -Screen* CreateNativeScreen(); +// TODO(crbug.com/1317416): Make this static private member of +// ScopedNativeScreen. +DISPLAY_EXPORT Screen* CreateNativeScreen(); + +// Android does not have `CreateNativeScreen()`. +#if !BUILDFLAG(IS_ANDROID) + +// ScopedNativeScreen creates a native screen if there is no screen created yet +// (e.g. by a unit test). +class DISPLAY_EXPORT ScopedNativeScreen { + public: + explicit ScopedNativeScreen(const base::Location& location = FROM_HERE); + ScopedNativeScreen(const ScopedNativeScreen&) = delete; + ScopedNativeScreen& operator=(const ScopedNativeScreen&) = delete; + virtual ~ScopedNativeScreen(); + + // Create and initialize the screen instance if the screen instance does not + // exist yet. + void MaybeInit(const base::Location& location = FROM_HERE); + void Shutdown(); + + Screen* screen() { return screen_.get(); } + + virtual Screen* CreateScreen(); + + protected: + explicit ScopedNativeScreen(bool call_maybe_init, + const base::Location& location = FROM_HERE); + + private: + bool maybe_init_called_{false}; + std::unique_ptr<Screen> screen_; +}; + +#endif } // namespace display
diff --git a/ui/display/screen_base.cc b/ui/display/screen_base.cc index 03d89f0..2e9e375 100644 --- a/ui/display/screen_base.cc +++ b/ui/display/screen_base.cc
@@ -75,6 +75,10 @@ display_list_.RemoveObserver(observer); } +bool ScreenBase::HasDisplayObservers() const { + return !display_list_.observers()->empty(); +} + void ScreenBase::SetPanelRotationForTesting(int64_t display_id, Display::Rotation rotation) { Display display = *display_list_.FindDisplayById(display_id);
diff --git a/ui/display/screen_base.h b/ui/display/screen_base.h index 1b63863..ef3f7013 100644 --- a/ui/display/screen_base.h +++ b/ui/display/screen_base.h
@@ -45,6 +45,8 @@ void SetPanelRotationForTesting(int64_t display_id, Display::Rotation rotation) override; + bool HasDisplayObservers() const; + protected: // Invoked when a display changed in some way, including being added. // If |is_primary| is true, |changed_display| is the primary display.
diff --git a/ui/display/test/scoped_screen_override.h b/ui/display/test/scoped_screen_override.h index 0ba1c31..aba5307f 100644 --- a/ui/display/test/scoped_screen_override.h +++ b/ui/display/test/scoped_screen_override.h
@@ -11,6 +11,8 @@ namespace test { +// [Deprecated] Do not use this in new code. +// // This class represents a RAII wrapper for global screen overriding. An object // of this class restores original display::Screen instance when it goes out of // scope. Prefer to use it instead of directly call of
diff --git a/ui/display/test/test_screen.cc b/ui/display/test/test_screen.cc index e2ae5bb5..af96e29 100644 --- a/ui/display/test/test_screen.cc +++ b/ui/display/test/test_screen.cc
@@ -10,18 +10,33 @@ namespace display { namespace test { +namespace { +TestScreen* test_screen = nullptr; +} // static constexpr gfx::Rect TestScreen::kDefaultScreenBounds; TestScreen::TestScreen(bool create_display) { + DCHECK(!test_screen); + test_screen = this; + if (!create_display) return; Display display(1, kDefaultScreenBounds); ProcessDisplayChanged(display, /* is_primary = */ true); } -TestScreen::~TestScreen() {} +TestScreen::~TestScreen() { + DCHECK_EQ(test_screen, this); + test_screen = nullptr; +} + +// static +TestScreen* TestScreen::Get() { + DCHECK_EQ(Screen::GetScreen(), test_screen); + return test_screen; +} void TestScreen::set_cursor_screen_point(const gfx::Point& point) { cursor_screen_point_ = point;
diff --git a/ui/display/test/test_screen.h b/ui/display/test/test_screen.h index ff7fe07..9962e07 100644 --- a/ui/display/test/test_screen.h +++ b/ui/display/test/test_screen.h
@@ -21,6 +21,8 @@ public: static constexpr gfx::Rect kDefaultScreenBounds = gfx::Rect(0, 0, 800, 600); + static TestScreen* Get(); + // TODO(weili): Split this into a protected no-argument constructor for // subclass uses and the public one with gfx::Size argument. explicit TestScreen(bool create_display = true);
diff --git a/ui/display/win/test/scoped_screen_win.cc b/ui/display/win/test/scoped_screen_win.cc index 84c1b4ca..edb39b8c 100644 --- a/ui/display/win/test/scoped_screen_win.cc +++ b/ui/display/win/test/scoped_screen_win.cc
@@ -20,10 +20,6 @@ gfx::Vector2dF(96.0, 96.0), DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER}}); } -ScopedScreenWin::~ScopedScreenWin() { - Screen::SetScreenInstance(old_screen_); -} - } // namespace test } // namespace win } // namespace display
diff --git a/ui/display/win/test/scoped_screen_win.h b/ui/display/win/test/scoped_screen_win.h index ca6cb2c..0633d2e 100644 --- a/ui/display/win/test/scoped_screen_win.h +++ b/ui/display/win/test/scoped_screen_win.h
@@ -12,6 +12,10 @@ namespace win { namespace test { +// [Deprecated] +// TODO(crbug.com/1317416): The initialization code of this class should be +// moved to the test that depends on it. +// // ScopedScreenWin construct a instance of ScreenWinDisplay with bounds // (1920,1080). This will allow unittests to query the details about ScreenWin // using static methods. ScopedScreenWin needs to be initialized before running @@ -23,10 +27,7 @@ ScopedScreenWin(const ScopedScreenWin&) = delete; ScopedScreenWin& operator=(const ScopedScreenWin&) = delete; - ~ScopedScreenWin() override; - - private: - raw_ptr<Screen> old_screen_ = Screen::SetScreenInstance(this); + ~ScopedScreenWin() override = default; }; } // namespace test
diff --git a/ui/events/ozone/evdev/BUILD.gn b/ui/events/ozone/evdev/BUILD.gn index e1f06d8..ccd75f0 100644 --- a/ui/events/ozone/evdev/BUILD.gn +++ b/ui/events/ozone/evdev/BUILD.gn
@@ -142,6 +142,8 @@ if (is_chromeos_ash) { sources += [ + "fake_keyboard_heuristic_metrics.cc", + "fake_keyboard_heuristic_metrics.h", "numberpad_metrics.cc", "numberpad_metrics.h", ]
diff --git a/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.cc b/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.cc new file mode 100644 index 0000000..5bef3c9b5 --- /dev/null +++ b/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.cc
@@ -0,0 +1,28 @@ +// Copyright 2022 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 "ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.h" + +#include "ui/events/ozone/features.h" + +namespace ui { + +FakeKeyboardHeuristicMetrics::FakeKeyboardHeuristicMetrics() + : feature_usage_metrics_("FakeKeyboardHeuristic", this) {} + +FakeKeyboardHeuristicMetrics::~FakeKeyboardHeuristicMetrics() = default; + +bool FakeKeyboardHeuristicMetrics::IsEligible() const { + return true; +} + +bool FakeKeyboardHeuristicMetrics::IsEnabled() const { + return base::FeatureList::IsEnabled(kEnableFakeKeyboardHeuristic); +} + +void FakeKeyboardHeuristicMetrics::RecordUsage(bool success) { + feature_usage_metrics_.RecordUsage(success); +} + +} // namespace ui \ No newline at end of file
diff --git a/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.h b/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.h new file mode 100644 index 0000000..b07112a9 --- /dev/null +++ b/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.h
@@ -0,0 +1,26 @@ +// Copyright 2022 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 UI_EVENTS_OZONE_EVDEV_FAKE_KEYBOARD_HEURISTIC_METRICS_H_ +#define UI_EVENTS_OZONE_EVDEV_FAKE_KEYBOARD_HEURISTIC_METRICS_H_ + +#include "chromeos/components/feature_usage/feature_usage_metrics.h" + +namespace ui { +class FakeKeyboardHeuristicMetrics + : public feature_usage::FeatureUsageMetrics::Delegate { + public: + explicit FakeKeyboardHeuristicMetrics(); + ~FakeKeyboardHeuristicMetrics() override; + + bool IsEligible() const override; + bool IsEnabled() const override; + void RecordUsage(bool success); + + private: + feature_usage::FeatureUsageMetrics feature_usage_metrics_; +}; +} // namespace ui + +#endif // UI_EVENTS_OZONE_EVDEV_FAKE_KEYBOARD_HEURISTIC_METRICS_H_
diff --git a/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.cc b/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.cc index 27de338..9d8461c2 100644 --- a/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.cc +++ b/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.cc
@@ -44,6 +44,9 @@ } converter->SetSuspectedImposter(true); +#if BUILDFLAG(IS_CHROMEOS_ASH) + fake_keyboard_heuristic_metrics_.RecordUsage(true); +#endif return true; }
diff --git a/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h b/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h index 6494059..871416c 100644 --- a/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h +++ b/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h
@@ -11,6 +11,10 @@ #include "ui/events/devices/input_device.h" #include "ui/events/ozone/evdev/event_converter_evdev.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.h" +#endif + namespace ui { class COMPONENT_EXPORT(EVDEV) KeyboardImposterCheckerEvdev { public: @@ -33,6 +37,10 @@ // Number of devices per phys path. std::multimap<std::string, int> devices_on_phys_path_; + +#if BUILDFLAG(IS_CHROMEOS_ASH) + FakeKeyboardHeuristicMetrics fake_keyboard_heuristic_metrics_; +#endif }; } // namespace ui
diff --git a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc index 97cc367..5bb81b2 100644 --- a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc +++ b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc
@@ -14,7 +14,8 @@ #define USE_EIGEN 0 #endif -namespace ui { +namespace ui::internal_onedevice::alpha_model { + namespace { // ----------------------------------------------------------------------------- @@ -3878,7 +3879,6 @@ 323}; int32_t logits_MatMul_merged_with_dnn_logits_BiasAdd0Shape[2] = {1, 1}; -namespace internal_onedevice { void Inference( const float* __restrict input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,323 */ , @@ -3921,5 +3921,4 @@ #endif } -} // namespace internal_onedevice -} // namespace ui +} // namespace ui::internal_onedevice::alpha_model
diff --git a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h index 02bb87d2..601d4af9 100644 --- a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h +++ b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h
@@ -6,8 +6,7 @@ #define UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_H_ #include <cstdint> -namespace ui { -namespace internal_onedevice { +namespace ui::internal_onedevice::alpha_model { struct alignas(16) FixedAllocations { float alloc0[20]; int32_t shape0[2]; @@ -36,6 +35,5 @@ , FixedAllocations* __restrict fixed); -} // namespace internal_onedevice -} // namespace ui +} // namespace ui::internal_onedevice::alpha_model #endif // UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_H_
diff --git a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.cc b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.cc index fd3add9..c431878 100644 --- a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.cc +++ b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.cc
@@ -14,7 +14,7 @@ #define USE_EIGEN 0 #endif -namespace ui::v2 { +namespace ui::internal_onedevice::alpha_model_v2 { namespace { // ----------------------------------------------------------------------------- @@ -15349,7 +15349,7 @@ int32_t input_from_feature_columns_input_layer_concat_concat0Shape[2] = {1, 173}; int32_t logits_MatMul_merged_with_dnn_logits_BiasAdd0Shape[2] = {1, 1}; -namespace internal_onedevice { + void Inference( const float* __restrict input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,173 */ , @@ -15419,5 +15419,4 @@ Singleton<PerOpTimings>::get()->WriteTimingsToInfoLog(); #endif } -} // namespace internal_onedevice -} // namespace ui::v2 +} // namespace ui::internal_onedevice::alpha_model_v2
diff --git a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.h b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.h index 733d0bd..97b5366 100644 --- a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.h +++ b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.h
@@ -6,7 +6,7 @@ #define UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_V2_H_ #include <cstdint> -namespace ui::v2::internal_onedevice { +namespace ui::internal_onedevice::alpha_model_v2 { struct alignas(16) FixedAllocations { float alloc0[117]; float alloc1[115]; @@ -36,5 +36,5 @@ , FixedAllocations* __restrict fixed); -} // namespace ui::v2::internal_onedevice +} // namespace ui::internal_onedevice::alpha_model_v2 #endif // UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_V2_H_
diff --git a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc index 6b65980..1c7e45c 100644 --- a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc +++ b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc
@@ -25,6 +25,9 @@ namespace ui { +namespace alpha = internal_onedevice::alpha_model; +namespace alpha_v2 = internal_onedevice::alpha_model_v2; + float OneDeviceTrainNeuralStylusPalmDetectionFilterModel::Inference( const std::vector<float>& features) const { DVLOG(1) << "In Inference."; @@ -41,15 +44,13 @@ } float output = 0; if (base::FeatureList::IsEnabled(kEnableNeuralPalmRejectionModelV2)) { - std::unique_ptr<v2::internal_onedevice::FixedAllocations> fixed_allocations( - new v2::internal_onedevice::FixedAllocations()); - v2::internal_onedevice::Inference(&features[0], &output, - fixed_allocations.get()); + std::unique_ptr<alpha_v2::FixedAllocations> fixed_allocations( + new alpha_v2::FixedAllocations()); + alpha_v2::Inference(&features[0], &output, fixed_allocations.get()); } else { - std::unique_ptr<internal_onedevice::FixedAllocations> fixed_allocations( - new internal_onedevice::FixedAllocations()); - internal_onedevice::Inference(&features[0], &output, - fixed_allocations.get()); + std::unique_ptr<alpha::FixedAllocations> fixed_allocations( + new alpha::FixedAllocations()); + alpha::Inference(&features[0], &output, fixed_allocations.get()); } return output; }
diff --git a/ui/file_manager/integration_tests/file_manager/zip_files.js b/ui/file_manager/integration_tests/file_manager/zip_files.js index 3aeef16..f14c339 100644 --- a/ui/file_manager/integration_tests/file_manager/zip_files.js +++ b/ui/file_manager/integration_tests/file_manager/zip_files.js
@@ -15,6 +15,12 @@ const ZipCreationTimeHistogramName = 'FileBrowser.ZipTask.Time'; /** + * The name of the UMA to track extract archive status. + * @const {string} + */ +const ExtractArchiveStatusHistogramName = 'FileBrowser.ExtractTask.Status'; + +/** * Returns the expected file list row entries after opening (mounting) the * ENTRIES.zipArchive file list entry. */ @@ -349,6 +355,9 @@ caller, `Expected feedback panel msg: "${expectedMsg}", got "${actualMsg}"`); }); + + // Check: a extract archive status histogram value should have been recorded. + await expectHistogramTotalCount(ExtractArchiveStatusHistogramName, 1); }; /** @@ -507,6 +516,9 @@ await remoteCall.waitForElement(appId, '#file-list [file-name="folder"]'); await remoteCall.waitForElement(appId, '#file-list [file-name="text.txt"]'); await remoteCall.waitForElement(appId, '#file-list [file-name="image.png"]'); + + // Check: a extract archive status histogram value should have been recorded. + await expectHistogramTotalCount(ExtractArchiveStatusHistogramName, 1); }; /** @@ -570,6 +582,9 @@ await remoteCall.waitForElement(appId, '#file-list [file-name="folder"]'); await remoteCall.waitForElement(appId, '#file-list [file-name="text.txt"]'); await remoteCall.waitForElement(appId, '#file-list [file-name="image.png"]'); + + // Check: 2 extract archive status histogram value should have been recorded. + await expectHistogramTotalCount(ExtractArchiveStatusHistogramName, 2); }; /** @@ -614,6 +629,9 @@ // Check: File content in the ZIP with decoded name should appear. await remoteCall.waitForElement( appId, '#file-list [file-name="新しいフォルダ"]'); + + // Check: a extract archive status histogram value should have been recorded. + await expectHistogramTotalCount(ExtractArchiveStatusHistogramName, 1); }; /** @@ -689,4 +707,7 @@ caller, `Expected feedback panel msg: "${expectedMsg}", got "${actualMsg}"`); }); + + // Check: a extract archive status histogram value should have been recorded. + await expectHistogramTotalCount(ExtractArchiveStatusHistogramName, 1); };
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn index 626e9ebf..1ab4bd9 100644 --- a/ui/ozone/platform/wayland/BUILD.gn +++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -163,6 +163,8 @@ "host/wayland_window_manager.h", "host/wayland_window_observer.cc", "host/wayland_window_observer.h", + "host/wayland_zaura_output.cc", + "host/wayland_zaura_output.h", "host/wayland_zaura_shell.cc", "host/wayland_zaura_shell.h", "host/wayland_zcr_cursor_shapes.cc", @@ -468,6 +470,8 @@ "test/test_wp_pointer_gestures.h", "test/test_xdg_popup.cc", "test/test_xdg_popup.h", + "test/test_zaura_output.cc", + "test/test_zaura_output.h", "test/test_zcr_text_input_extension.cc", "test/test_zcr_text_input_extension.h", "test/test_zwp_linux_buffer_params.cc", @@ -529,6 +533,7 @@ "host/wayland_window_drag_controller_unittest.cc", "host/wayland_window_manager_unittests.cc", "host/wayland_window_unittest.cc", + "host/wayland_zaura_output_unittest.cc", "host/wayland_zaura_shell_unittest.cc", "host/wayland_zwp_pointer_gestures_unittest.cc", "test/wayland_drag_drop_test.cc",
diff --git a/ui/ozone/platform/wayland/common/wayland_object.cc b/ui/ozone/platform/wayland/common/wayland_object.cc index b7625c6..580491c 100644 --- a/ui/ozone/platform/wayland/common/wayland_object.cc +++ b/ui/ozone/platform/wayland/common/wayland_object.cc
@@ -167,6 +167,7 @@ IMPLEMENT_WAYLAND_OBJECT_TRAITS(xdg_surface) IMPLEMENT_WAYLAND_OBJECT_TRAITS(xdg_toplevel) IMPLEMENT_WAYLAND_OBJECT_TRAITS(xdg_wm_base) +IMPLEMENT_WAYLAND_OBJECT_TRAITS(zaura_output) IMPLEMENT_WAYLAND_OBJECT_TRAITS(zaura_shell) IMPLEMENT_WAYLAND_OBJECT_TRAITS(zaura_surface) IMPLEMENT_WAYLAND_OBJECT_TRAITS(zaura_toplevel)
diff --git a/ui/ozone/platform/wayland/common/wayland_object.h b/ui/ozone/platform/wayland/common/wayland_object.h index ef28758..3d9e53a 100644 --- a/ui/ozone/platform/wayland/common/wayland_object.h +++ b/ui/ozone/platform/wayland/common/wayland_object.h
@@ -148,6 +148,7 @@ DECLARE_WAYLAND_OBJECT_TRAITS(xdg_surface) DECLARE_WAYLAND_OBJECT_TRAITS(xdg_toplevel) DECLARE_WAYLAND_OBJECT_TRAITS(xdg_wm_base) +DECLARE_WAYLAND_OBJECT_TRAITS(zaura_output) DECLARE_WAYLAND_OBJECT_TRAITS(zaura_shell) DECLARE_WAYLAND_OBJECT_TRAITS(zaura_surface) DECLARE_WAYLAND_OBJECT_TRAITS(zaura_toplevel)
diff --git a/ui/ozone/platform/wayland/host/wayland_output.cc b/ui/ozone/platform/wayland/host/wayland_output.cc index 2186d6a..01a01b2 100644 --- a/ui/ozone/platform/wayland/host/wayland_output.cc +++ b/ui/ozone/platform/wayland/host/wayland_output.cc
@@ -4,6 +4,7 @@ #include "ui/ozone/platform/wayland/host/wayland_output.h" +#include <aura-shell-client-protocol.h> #include <xdg-output-unstable-v1-client-protocol.h> #include "base/logging.h" @@ -11,6 +12,7 @@ #include "ui/gfx/color_space.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_output_manager.h" +#include "ui/ozone/platform/wayland/host/wayland_zaura_output.h" #include "ui/ozone/platform/wayland/host/xdg_output.h" namespace ui { @@ -66,6 +68,12 @@ zxdg_output_manager_v1_get_xdg_output(xdg_output_manager, output_.get())); } +void WaylandOutput::InitializeZAuraOutput(zaura_shell* aura_shell) { + DCHECK(!aura_output_); + aura_output_ = std::make_unique<WaylandZAuraOutput>( + zaura_shell_get_aura_output(aura_shell, output_.get())); +} + void WaylandOutput::Initialize(Delegate* delegate) { DCHECK(!delegate_); delegate_ = delegate; @@ -84,6 +92,14 @@ : scale_factor(); } +gfx::Insets WaylandOutput::insets() const { + return aura_output_ ? aura_output_->insets() : gfx::Insets(); +} + +zaura_output* WaylandOutput::get_zaura_output() const { + return aura_output_ ? aura_output_->wl_object() : nullptr; +} + void WaylandOutput::TriggerDelegateNotifications() { if (xdg_output_ && connection_->surface_submission_in_pixel_coordinates()) { DCHECK(!rect_in_physical_pixels_.IsEmpty()); @@ -99,7 +115,7 @@ } } delegate_->OnOutputHandleMetrics(output_id_, rect_in_physical_pixels_, - scale_factor_, transform_); + insets(), scale_factor_, transform_); } // static
diff --git a/ui/ozone/platform/wayland/host/wayland_output.h b/ui/ozone/platform/wayland/host/wayland_output.h index c36c7c7..ce225ac 100644 --- a/ui/ozone/platform/wayland/host/wayland_output.h +++ b/ui/ozone/platform/wayland/host/wayland_output.h
@@ -16,6 +16,7 @@ class XDGOutput; class WaylandConnection; +class WaylandZAuraOutput; // WaylandOutput objects keep track of the current output of display // that are available to the application. @@ -33,6 +34,7 @@ public: virtual void OnOutputHandleMetrics(uint32_t output_id, const gfx::Rect& new_bounds, + const gfx::Insets& insets, float scale_factor, int32_t transform) = 0; @@ -51,6 +53,7 @@ void Initialize(Delegate* delegate); void InitializeXdgOutput(struct zxdg_output_manager_v1* manager); + void InitializeZAuraOutput(zaura_shell* aura_shell); float GetUIScaleFactor() const; uint32_t output_id() const { return output_id_; } @@ -58,12 +61,14 @@ float scale_factor() const { return scale_factor_; } int32_t transform() const { return transform_; } gfx::Rect bounds() const { return rect_in_physical_pixels_; } + gfx::Insets insets() const; // Tells if the output has already received physical screen dimensions in the // global compositor space. bool is_ready() const { return !rect_in_physical_pixels_.IsEmpty(); } - wl_output* get_output() { return output_.get(); } + wl_output* get_output() const { return output_.get(); } + zaura_output* get_zaura_output() const; private: static constexpr int32_t kDefaultScaleFactor = 1; @@ -97,6 +102,7 @@ const uint32_t output_id_ = 0; wl::Object<wl_output> output_; std::unique_ptr<XDGOutput> xdg_output_; + std::unique_ptr<WaylandZAuraOutput> aura_output_; float scale_factor_ = kDefaultScaleFactor; int32_t transform_ = WL_OUTPUT_TRANSFORM_NORMAL; gfx::Rect rect_in_physical_pixels_;
diff --git a/ui/ozone/platform/wayland/host/wayland_output_manager.cc b/ui/ozone/platform/wayland/host/wayland_output_manager.cc index a7ccee03..432bc96d 100644 --- a/ui/ozone/platform/wayland/host/wayland_output_manager.cc +++ b/ui/ozone/platform/wayland/host/wayland_output_manager.cc
@@ -11,6 +11,7 @@ #include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_output.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" +#include "ui/ozone/platform/wayland/host/wayland_zaura_shell.h" namespace ui { @@ -45,6 +46,10 @@ wayland_output->Initialize(this); if (connection_->xdg_output_manager_v1()) wayland_output->InitializeXdgOutput(connection_->xdg_output_manager_v1()); + if (connection_->zaura_shell()) { + wayland_output->InitializeZAuraOutput( + connection_->zaura_shell()->wl_object()); + } DCHECK(!wayland_output->is_ready()); output_list_[output_id] = std::move(wayland_output); @@ -74,6 +79,14 @@ output.second->InitializeXdgOutput(connection_->xdg_output_manager_v1()); } +void WaylandOutputManager::InitializeAllZAuraOutputs() { + DCHECK(connection_->zaura_shell()); + for (const auto& output : output_list_) { + output.second->InitializeZAuraOutput( + connection_->zaura_shell()->wl_object()); + } +} + std::unique_ptr<WaylandScreen> WaylandOutputManager::CreateWaylandScreen() { auto wayland_screen = std::make_unique<WaylandScreen>(connection_); wayland_screen_ = wayland_screen->GetWeakPtr(); @@ -94,7 +107,8 @@ if (output.second->is_ready()) { screen->OnOutputAddedOrUpdated( output.second->output_id(), output.second->bounds(), - output.second->scale_factor(), output.second->transform()); + output.second->insets(), output.second->scale_factor(), + output.second->transform()); } } } @@ -115,10 +129,11 @@ void WaylandOutputManager::OnOutputHandleMetrics(uint32_t output_id, const gfx::Rect& new_bounds, + const gfx::Insets& insets, float scale_factor, int32_t transform) { if (wayland_screen_) { - wayland_screen_->OnOutputAddedOrUpdated(output_id, new_bounds, + wayland_screen_->OnOutputAddedOrUpdated(output_id, new_bounds, insets, scale_factor, transform); } auto* wayland_window_manager = connection_->wayland_window_manager();
diff --git a/ui/ozone/platform/wayland/host/wayland_output_manager.h b/ui/ozone/platform/wayland/host/wayland_output_manager.h index 9f5711b4..49e2245 100644 --- a/ui/ozone/platform/wayland/host/wayland_output_manager.h +++ b/ui/ozone/platform/wayland/host/wayland_output_manager.h
@@ -38,6 +38,7 @@ void RemoveWaylandOutput(const uint32_t output_id); void InitializeAllXdgOutputs(); + void InitializeAllZAuraOutputs(); // Creates a platform screen. std::unique_ptr<WaylandScreen> CreateWaylandScreen(); @@ -54,6 +55,7 @@ // WaylandOutput::Delegate: void OnOutputHandleMetrics(uint32_t output_id, const gfx::Rect& new_bounds, + const gfx::Insets& insets, float scale_factor, int32_t transform) override;
diff --git a/ui/ozone/platform/wayland/host/wayland_screen.cc b/ui/ozone/platform/wayland/host/wayland_screen.cc index c574965..4f5b2ae 100644 --- a/ui/ozone/platform/wayland/host/wayland_screen.cc +++ b/ui/ozone/platform/wayland/host/wayland_screen.cc
@@ -109,9 +109,10 @@ void WaylandScreen::OnOutputAddedOrUpdated(uint32_t output_id, const gfx::Rect& bounds, + const gfx::Insets& insets, float scale, int32_t transform) { - AddOrUpdateDisplay(output_id, bounds, scale, transform); + AddOrUpdateDisplay(output_id, bounds, insets, scale, transform); } void WaylandScreen::OnOutputRemoved(uint32_t output_id) { @@ -142,15 +143,12 @@ void WaylandScreen::AddOrUpdateDisplay(uint32_t output_id, const gfx::Rect& new_bounds, + const gfx::Insets& insets, float scale_factor, int32_t transform) { display::Display changed_display(output_id); - if (!display::Display::HasForceDeviceScaleFactor()) { - changed_display.SetScaleAndBounds(scale_factor, new_bounds); - } else { - changed_display.set_bounds(new_bounds); - changed_display.set_work_area(new_bounds); - } + changed_display.SetScaleAndBounds(scale_factor, new_bounds); + changed_display.UpdateWorkAreaFromInsets(insets); DCHECK_GE(transform, WL_OUTPUT_TRANSFORM_NORMAL); DCHECK_LE(transform, WL_OUTPUT_TRANSFORM_FLIPPED_270);
diff --git a/ui/ozone/platform/wayland/host/wayland_screen.h b/ui/ozone/platform/wayland/host/wayland_screen.h index 5b59b77..da79707 100644 --- a/ui/ozone/platform/wayland/host/wayland_screen.h +++ b/ui/ozone/platform/wayland/host/wayland_screen.h
@@ -41,6 +41,7 @@ void OnOutputAddedOrUpdated(uint32_t output_id, const gfx::Rect& bounds, + const gfx::Insets& insets, float output_scale, int32_t output_transform); void OnOutputRemoved(uint32_t output_id); @@ -73,8 +74,11 @@ const gfx::GpuExtraInfo& gpu_extra_info) override; private: + // |bounds| is given in physical pixel coordinates. + // |insets| is given in DIP screen coordinates. void AddOrUpdateDisplay(uint32_t output_id, const gfx::Rect& bounds, + const gfx::Insets& insets, float scale, int32_t transform);
diff --git a/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc b/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc index ca80363..343e01a 100644 --- a/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
@@ -21,6 +21,7 @@ #include "ui/ozone/platform/wayland/test/mock_pointer.h" #include "ui/ozone/platform/wayland/test/mock_surface.h" #include "ui/ozone/platform/wayland/test/mock_wayland_platform_window_delegate.h" +#include "ui/ozone/platform/wayland/test/mock_zaura_shell.h" #include "ui/ozone/platform/wayland/test/test_output.h" #include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h" #include "ui/ozone/platform/wayland/test/wayland_test.h" @@ -90,6 +91,9 @@ WaylandTest::SetUp(); + mock_zaura_shell_ = std::make_unique<wl::MockZAuraShell>(); + mock_zaura_shell_->Initialize(server_.display()); + output_->SetRect({kOutputWidth, kOutputHeight}); output_->SetScale(1); output_->Flush(); @@ -124,6 +128,8 @@ EXPECT_EQ(display_for_widget.id(), expected_display_id); } + std::unique_ptr<wl::MockZAuraShell> mock_zaura_shell_; + wl::TestOutput* output_ = nullptr; WaylandOutputManager* output_manager_ = nullptr; @@ -295,7 +301,7 @@ TestDisplayObserver observer; platform_screen_->AddObserver(&observer); - gfx::Rect new_rect{100, 100}; + const gfx::Rect new_rect{100, 100}; output_->SetRect(new_rect); output_->Flush(); @@ -305,7 +311,24 @@ display::DisplayObserver::DISPLAY_METRIC_WORK_AREA; EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values); EXPECT_EQ(observer.GetDisplay().bounds(), new_rect); + EXPECT_EQ(observer.GetDisplay().work_area(), new_rect); + // Test work area. + const gfx::Rect new_work_area{80, 80}; + ASSERT_TRUE(output_->GetAuraOutput()); + output_->GetAuraOutput()->SetInsets(new_rect.InsetsFrom(new_work_area)); + output_->Flush(); + + Sync(); + + changed_values = display::DisplayObserver::DISPLAY_METRIC_WORK_AREA; + EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values); + // Bounds should be unchanged. + EXPECT_EQ(observer.GetDisplay().bounds(), new_rect); + // Work area should have new value. + EXPECT_EQ(observer.GetDisplay().work_area(), new_work_area); + + // Test scaling. const int32_t new_scale_value = 2; output_->SetScale(new_scale_value); output_->Flush(); @@ -319,6 +342,7 @@ EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values); EXPECT_EQ(observer.GetDisplay().device_scale_factor(), new_scale_value); EXPECT_EQ(observer.GetDisplay().bounds(), gfx::Rect(50, 50)); + EXPECT_EQ(observer.GetDisplay().work_area(), gfx::Rect(30, 30)); platform_screen_->RemoveObserver(&observer); }
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output.cc b/ui/ozone/platform/wayland/host/wayland_zaura_output.cc new file mode 100644 index 0000000..4df501f --- /dev/null +++ b/ui/ozone/platform/wayland/host/wayland_zaura_output.cc
@@ -0,0 +1,47 @@ +// Copyright 2022 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 "ui/ozone/platform/wayland/host/wayland_zaura_output.h" + +#include <aura-shell-client-protocol.h> + +#include "base/check.h" + +namespace ui { + +WaylandZAuraOutput::WaylandZAuraOutput(zaura_output* aura_output) + : obj_(aura_output) { + DCHECK(obj_); + + static constexpr zaura_output_listener kZAuraOutputListener = { + &OnScale, &OnConnection, &OnDeviceScaleFactor, &OnInsets}; + zaura_output_add_listener(obj_.get(), &kZAuraOutputListener, this); +} + +WaylandZAuraOutput::~WaylandZAuraOutput() = default; + +void WaylandZAuraOutput::OnScale(void* data, + struct zaura_output* zaura_output, + uint32_t flags, + uint32_t scale) {} + +void WaylandZAuraOutput::OnConnection(void* data, + struct zaura_output* zaura_output, + uint32_t connection) {} + +void WaylandZAuraOutput::OnDeviceScaleFactor(void* data, + struct zaura_output* zaura_output, + uint32_t scale) {} + +void WaylandZAuraOutput::OnInsets(void* data, + struct zaura_output* zaura_output, + int32_t top, + int32_t left, + int32_t bottom, + int32_t right) { + if (auto* aura_output = static_cast<WaylandZAuraOutput*>(data)) + aura_output->insets_ = gfx::Insets::TLBR(top, left, bottom, right); +} + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output.h b/ui/ozone/platform/wayland/host/wayland_zaura_output.h new file mode 100644 index 0000000..ba813cbf --- /dev/null +++ b/ui/ozone/platform/wayland/host/wayland_zaura_output.h
@@ -0,0 +1,52 @@ +// Copyright 2022 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 UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZAURA_OUTPUT_H_ +#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZAURA_OUTPUT_H_ + +#include <cstdint> + +#include "ui/gfx/geometry/insets.h" +#include "ui/ozone/platform/wayland/common/wayland_object.h" + +namespace ui { + +// Wraps the zaura_output object. +class WaylandZAuraOutput { + public: + explicit WaylandZAuraOutput(zaura_output* aura_output); + WaylandZAuraOutput(const WaylandZAuraOutput&) = delete; + WaylandZAuraOutput& operator=(const WaylandZAuraOutput&) = delete; + ~WaylandZAuraOutput(); + + zaura_output* wl_object() { return obj_.get(); } + + const gfx::Insets& insets() const { return insets_; } + + private: + // zaura_output_listeners + static void OnScale(void* data, + struct zaura_output* zaura_output, + uint32_t flags, + uint32_t scale); + static void OnConnection(void* data, + struct zaura_output* zaura_output, + uint32_t connection); + static void OnDeviceScaleFactor(void* data, + struct zaura_output* zaura_output, + uint32_t scale); + static void OnInsets(void* data, + struct zaura_output* zaura_output, + int32_t top, + int32_t left, + int32_t bottom, + int32_t right); + + wl::Object<zaura_output> obj_; + gfx::Insets insets_; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZAURA_OUTPUT_H_
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output_unittest.cc b/ui/ozone/platform/wayland/host/wayland_zaura_output_unittest.cc new file mode 100644 index 0000000..b26a72c7 --- /dev/null +++ b/ui/ozone/platform/wayland/host/wayland_zaura_output_unittest.cc
@@ -0,0 +1,107 @@ +// Copyright 2022 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 "ui/ozone/platform/wayland/host/wayland_zaura_output.h" + +#include <components/exo/wayland/protocol/aura-shell-client-protocol.h> +#include <components/exo/wayland/protocol/aura-shell-server-protocol.h> + +#include "base/run_loop.h" +#include "base/test/task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/ozone/platform/wayland/host/wayland_connection.h" +#include "ui/ozone/platform/wayland/host/wayland_event_source.h" +#include "ui/ozone/platform/wayland/host/wayland_output.h" +#include "ui/ozone/platform/wayland/host/wayland_output_manager.h" +#include "ui/ozone/platform/wayland/test/mock_zaura_shell.h" +#include "ui/ozone/platform/wayland/test/server_object.h" +#include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h" +#include "ui/ozone/platform/wayland/test/test_zaura_output.h" + +namespace ui { +namespace { + +using ::testing::Values; + +class WaylandZAuraOutputTest : public ::testing::Test { + public: + WaylandZAuraOutputTest() + : task_environment_( + base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {} + + WaylandZAuraOutputTest(const WaylandZAuraOutputTest&) = delete; + WaylandZAuraOutputTest& operator=(const WaylandZAuraOutputTest&) = delete; + + ~WaylandZAuraOutputTest() override = default; + + void SetUp() override { + ::testing::Test::SetUp(); + + ASSERT_TRUE(server_.Start({.shell_version = wl::ShellVersion::kStable})); + mock_zaura_shell_.Initialize(server_.display()); + + ASSERT_TRUE(connection_.Initialize()); + connection_.event_source()->StartProcessingEvents(); + base::RunLoop().RunUntilIdle(); + + // Set default values for the output. + wl::TestOutput* output = server_.output(); + output->SetRect({800, 600}); + output->SetScale(1); + output->Flush(); + + base::RunLoop().RunUntilIdle(); + server_.Pause(); + + output_manager_ = connection_.wayland_output_manager(); + ASSERT_TRUE(output_manager_); + EXPECT_TRUE(output_manager_->IsOutputReady()); + + // Initializing the screen also connects it to the primary output, so it's + // easier for us to get the associated WaylandOutput object later. + platform_screen_ = output_manager_->CreateWaylandScreen(); + output_manager_->InitWaylandScreen(platform_screen_.get()); + } + + protected: + base::test::SingleThreadTaskEnvironment task_environment_; + wl::TestWaylandServerThread server_; + wl::MockZAuraShell mock_zaura_shell_; + WaylandConnection connection_; + + WaylandOutputManager* output_manager_ = nullptr; + std::unique_ptr<WaylandScreen> platform_screen_; +}; + +TEST_F(WaylandZAuraOutputTest, HandleInsets) { + WaylandOutput* wayland_output = output_manager_->GetPrimaryOutput(); + ASSERT_TRUE(wayland_output); + EXPECT_TRUE(wayland_output->is_ready()); + EXPECT_EQ(wayland_output->bounds(), gfx::Rect(800, 600)); + EXPECT_TRUE(wayland_output->insets().IsEmpty()); + EXPECT_TRUE(wayland_output->get_zaura_output()); + + // Simulate server sending updated insets to the client. + wl_resource* zaura_output_resource = + server_.output()->GetAuraOutput()->resource(); + ASSERT_TRUE(zaura_output_resource); + const gfx::Insets sent_insets = + gfx::Rect(800, 600).InsetsFrom(gfx::Rect(10, 10, 500, 400)); + EXPECT_FALSE(sent_insets.IsEmpty()); + zaura_output_send_insets(zaura_output_resource, sent_insets.top(), + sent_insets.left(), sent_insets.bottom(), + sent_insets.right()); + + server_.Resume(); + base::RunLoop().RunUntilIdle(); + server_.Pause(); + + // Verify that insets is updated. + EXPECT_TRUE(wayland_output->is_ready()); + EXPECT_EQ(wayland_output->bounds(), gfx::Rect(800, 600)); + EXPECT_EQ(wayland_output->insets(), sent_insets); +} + +} // namespace +} // namespace ui \ No newline at end of file
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc b/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc index 5114ddf..5532e22 100644 --- a/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc +++ b/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc
@@ -20,7 +20,7 @@ namespace { constexpr uint32_t kMinVersion = 1; -constexpr uint32_t kMaxVersion = 31; +constexpr uint32_t kMaxVersion = 32; } // static @@ -48,6 +48,13 @@ connection->zaura_shell_ = std::make_unique<WaylandZAuraShell>(zaura_shell.release(), connection); ReportShellUMA(UMALinuxWaylandShell::kZauraShell); + + // Usually WaylandOutputManager is instantiated first, so any ZAuraOutputs it + // created wouldn't have been initialized, since the zaura_shell didn't exist + // yet. So initialize them now. + if (connection->wayland_output_manager()) { + connection->wayland_output_manager()->InitializeAllZAuraOutputs(); + } } WaylandZAuraShell::WaylandZAuraShell(zaura_shell* aura_shell,
diff --git a/ui/ozone/platform/wayland/test/mock_zaura_shell.cc b/ui/ozone/platform/wayland/test/mock_zaura_shell.cc index 7e5fae6..0f2c508 100644 --- a/ui/ozone/platform/wayland/test/mock_zaura_shell.cc +++ b/ui/ozone/platform/wayland/test/mock_zaura_shell.cc
@@ -5,12 +5,15 @@ #include "ui/ozone/platform/wayland/test/mock_zaura_shell.h" #include "ui/ozone/platform/wayland/test/server_object.h" +#include "ui/ozone/platform/wayland/test/test_output.h" +#include "ui/ozone/platform/wayland/test/test_zaura_output.h" namespace wl { namespace { -constexpr uint32_t kZAuraShellVersion = 26; +constexpr uint32_t kZAuraShellVersion = 32; +constexpr uint32_t kZAuraOutputVersion = 32; void GetAuraSurface(wl_client* client, wl_resource* resource, @@ -20,7 +23,12 @@ void GetAuraOutput(wl_client* client, wl_resource* resource, uint32_t id, - wl_resource* output_resource) {} + wl_resource* output_resource) { + wl_resource* zaura_output_resource = CreateResourceWithImpl<TestZAuraOutput>( + client, &zaura_output_interface, kZAuraOutputVersion, nullptr, id); + auto* output = GetUserDataAs<TestOutput>(output_resource); + output->SetAuraOutput(GetUserDataAs<TestZAuraOutput>(zaura_output_resource)); +} void SurfaceSubmissionInPixelCoordinates(wl_client* client, wl_resource* resource) {}
diff --git a/ui/ozone/platform/wayland/test/test_output.cc b/ui/ozone/platform/wayland/test/test_output.cc index 3d8b0d2..c0ec7a90 100644 --- a/ui/ozone/platform/wayland/test/test_output.cc +++ b/ui/ozone/platform/wayland/test/test_output.cc
@@ -56,6 +56,10 @@ scale_ = std::move(pending_scale_.value()); wl_output_send_scale(resource(), scale_); } + + if (aura_output_) + aura_output_->Flush(); + wl_output_send_done(resource()); } @@ -71,4 +75,12 @@ Flush(); } +void TestOutput::SetAuraOutput(TestZAuraOutput* aura_output) { + aura_output_ = aura_output; +} + +TestZAuraOutput* TestOutput::GetAuraOutput() { + return aura_output_; +} + } // namespace wl
diff --git a/ui/ozone/platform/wayland/test/test_output.h b/ui/ozone/platform/wayland/test/test_output.h index b8ed75c8..5b90dc0 100644 --- a/ui/ozone/platform/wayland/test/test_output.h +++ b/ui/ozone/platform/wayland/test/test_output.h
@@ -11,6 +11,7 @@ #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/geometry/rect.h" #include "ui/ozone/platform/wayland/test/global_object.h" +#include "ui/ozone/platform/wayland/test/test_zaura_output.h" namespace wl { @@ -32,6 +33,9 @@ void Flush(); + void SetAuraOutput(TestZAuraOutput* aura_output); + TestZAuraOutput* GetAuraOutput(); + protected: void OnBind() override; @@ -43,6 +47,8 @@ absl::optional<gfx::Rect> pending_rect_ = absl::nullopt; absl::optional<int32_t> pending_scale_ = absl::nullopt; absl::optional<wl_output_transform> pending_transform_ = absl::nullopt; + + TestZAuraOutput* aura_output_ = nullptr; }; } // namespace wl
diff --git a/ui/ozone/platform/wayland/test/test_zaura_output.cc b/ui/ozone/platform/wayland/test/test_zaura_output.cc new file mode 100644 index 0000000..afcead2 --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_zaura_output.cc
@@ -0,0 +1,25 @@ +// Copyright 2022 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 "ui/ozone/platform/wayland/test/test_zaura_output.h" + +#include <aura-shell-server-protocol.h> + +namespace wl { + +TestZAuraOutput::TestZAuraOutput(wl_resource* resource) + : ServerObject(resource) {} + +TestZAuraOutput::~TestZAuraOutput() = default; + +void TestZAuraOutput::Flush() { + if (pending_insets_) { + insets_ = std::move(*pending_insets_); + pending_insets_.reset(); + zaura_output_send_insets(resource(), insets_.top(), insets_.left(), + insets_.bottom(), insets_.right()); + } +} + +} // namespace wl
diff --git a/ui/ozone/platform/wayland/test/test_zaura_output.h b/ui/ozone/platform/wayland/test/test_zaura_output.h new file mode 100644 index 0000000..9aabb5b5 --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_zaura_output.h
@@ -0,0 +1,36 @@ +// Copyright 2022 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 UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_ZAURA_OUTPUT_H_ +#define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_ZAURA_OUTPUT_H_ + +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/gfx/geometry/insets.h" +#include "ui/ozone/platform/wayland/test/server_object.h" + +namespace wl { + +// Manages zaura_output object. +class TestZAuraOutput : public ServerObject { + public: + explicit TestZAuraOutput(wl_resource* resource); + + TestZAuraOutput(const TestZAuraOutput&) = delete; + TestZAuraOutput& operator=(const TestZAuraOutput&) = delete; + + ~TestZAuraOutput() override; + + const gfx::Insets& GetInsets() const { return insets_; } + void SetInsets(const gfx::Insets& insets) { pending_insets_ = insets; } + + void Flush(); + + private: + gfx::Insets insets_; + absl::optional<gfx::Insets> pending_insets_; +}; + +} // namespace wl + +#endif // UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_ZAURA_OUTPUT_H_
diff --git a/ui/ozone/platform/x11/BUILD.gn b/ui/ozone/platform/x11/BUILD.gn index b1180a8..252986e 100644 --- a/ui/ozone/platform/x11/BUILD.gn +++ b/ui/ozone/platform/x11/BUILD.gn
@@ -151,6 +151,7 @@ "//ui/base/x", "//ui/base/x:test_support", "//ui/base/x:unittests", + "//ui/display:test_support", "//ui/events:test_support", "//ui/events/devices/x11", "//ui/events/platform/x11",
diff --git a/ui/ozone/platform/x11/test/x11_window_unittest.cc b/ui/ozone/platform/x11/test/x11_window_unittest.cc index f499dbe..cccb2e24 100644 --- a/ui/ozone/platform/x11/test/x11_window_unittest.cc +++ b/ui/ozone/platform/x11/test/x11_window_unittest.cc
@@ -15,6 +15,7 @@ #include "ui/base/x/x11_util.h" #include "ui/display/display_switches.h" #include "ui/display/screen_base.h" +#include "ui/display/test/test_screen.h" #include "ui/events/devices/x11/touch_factory_x11.h" #include "ui/events/event.h" #include "ui/events/platform/x11/x11_event_source.h" @@ -215,8 +216,8 @@ ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(pointer_devices); // X11 requires display::Screen instance. - test_screen_ = new TestScreen(); - display::Screen::SetScreenInstance(test_screen_); + test_screen_.emplace(); + display::Screen::SetScreenInstance(&test_screen_.value()); // Make X11 synchronous for our display connection. This does not force the // window manager to behave synchronously. @@ -226,6 +227,8 @@ protected: void TearDown() override { x11::Connection::Get()->SynchronizeForTest(false); + display::Screen::SetScreenInstance(nullptr); + test_screen_.reset(); } std::unique_ptr<X11Window> CreateX11Window( @@ -252,7 +255,7 @@ std::unique_ptr<base::test::TaskEnvironment> task_env_; std::unique_ptr<X11EventSource> event_source_; - TestScreen* test_screen_ = nullptr; + absl::optional<TestScreen> test_screen_; }; // https://crbug.com/898742: Test is flaky.
diff --git a/ui/ozone/platform/x11/x11_window_ozone_unittest.cc b/ui/ozone/platform/x11/x11_window_ozone_unittest.cc index f130507c..8f8953c 100644 --- a/ui/ozone/platform/x11/x11_window_ozone_unittest.cc +++ b/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
@@ -78,12 +78,13 @@ void SetUp() override { event_source_ = std::make_unique<X11EventSource>(x11::Connection::Get()); - test_screen_ = new TestScreen(); - display::Screen::SetScreenInstance(test_screen_); + display::Screen::SetScreenInstance(&test_screen_); TouchFactory::GetInstance()->SetPointerDeviceForTest({kPointerDeviceId}); } + void TearDown() override { display::Screen::SetScreenInstance(nullptr); } + protected: std::unique_ptr<PlatformWindow> CreatePlatformWindow( MockPlatformWindowDelegate* delegate, @@ -112,7 +113,7 @@ return window_manager; } - TestScreen* test_screen_ = nullptr; + TestScreen test_screen_; private: std::unique_ptr<base::test::TaskEnvironment> task_env_; @@ -283,7 +284,7 @@ // Verifies X11Window sets fullscreen bounds in pixels when going to fullscreen. TEST_F(X11WindowOzoneTest, ToggleFullscreen) { constexpr gfx::Rect screen_bounds_in_px(640, 480, 1280, 720); - test_screen_->SetScaleAndBoundsForPrimaryDisplay(2, screen_bounds_in_px); + test_screen_.SetScaleAndBoundsForPrimaryDisplay(2, screen_bounds_in_px); MockPlatformWindowDelegate delegate; gfx::AcceleratedWidget widget;
diff --git a/ui/ozone/public/ozone_platform.cc b/ui/ozone/public/ozone_platform.cc index aa32ca5..30fcf86d 100644 --- a/ui/ozone/public/ozone_platform.cc +++ b/ui/ozone/public/ozone_platform.cc
@@ -97,6 +97,11 @@ } // static +bool OzonePlatform::IsInitialized() { + return !!g_instance; +} + +// static std::string OzonePlatform::GetPlatformNameForTest() { return GetOzonePlatformName(); }
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h index 22ba323..df6b551 100644 --- a/ui/ozone/public/ozone_platform.h +++ b/ui/ozone/public/ozone_platform.h
@@ -240,6 +240,8 @@ static OzonePlatform* GetInstance(); + static bool IsInitialized(); + // Returns the current ozone platform name. // Some tests may skip based on the platform name. static std::string GetPlatformNameForTest();
diff --git a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc index f786b1b..45189c7 100644 --- a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc +++ b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
@@ -820,30 +820,33 @@ : public BubbleDialogDelegateViewTest, public testing::WithParamInterface<ArrowTestParameters> { public: - BubbleDialogDelegateViewArrowTest() : screen_override_(SetUpTestScreen()) {} + BubbleDialogDelegateViewArrowTest() { SetUpTestScreen(); } BubbleDialogDelegateViewArrowTest(const BubbleDialogDelegateViewArrowTest&) = delete; BubbleDialogDelegateViewArrowTest& operator=( const BubbleDialogDelegateViewArrowTest&) = delete; - ~BubbleDialogDelegateViewArrowTest() override = default; + ~BubbleDialogDelegateViewArrowTest() override { + display::Screen::SetScreenInstance(nullptr); + } private: - display::Screen* SetUpTestScreen() { - const display::Display test_display = test_screen_.GetPrimaryDisplay(); + void SetUpTestScreen() { + DCHECK(!display::test::TestScreen::Get()); + test_screen_ = std::make_unique<display::test::TestScreen>(); + display::Screen::SetScreenInstance(test_screen_.get()); + const display::Display test_display = test_screen_->GetPrimaryDisplay(); display::Display display(test_display); display.set_id(0x2); display.set_bounds(gfx::Rect(0, 0, kScreenWidth, kScreenHeight)); display.set_work_area(gfx::Rect(0, 0, kScreenWidth, kScreenHeight)); - test_screen_.display_list().RemoveDisplay(test_display.id()); - test_screen_.display_list().AddDisplay(display, - display::DisplayList::Type::PRIMARY); - return &test_screen_; + test_screen_->display_list().RemoveDisplay(test_display.id()); + test_screen_->display_list().AddDisplay( + display, display::DisplayList::Type::PRIMARY); } - display::test::TestScreen test_screen_; - display::test::ScopedScreenOverride screen_override_; + std::unique_ptr<display::test::TestScreen> test_screen_; }; TEST_P(BubbleDialogDelegateViewArrowTest, AvailableScreenSpaceTest) {
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm index 4c219d938..34b4af7 100644 --- a/ui/views/cocoa/bridged_native_widget_unittest.mm +++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -24,6 +24,7 @@ #import "ui/base/cocoa/window_size_constants.h" #include "ui/base/ime/input_method.h" #import "ui/base/test/cocoa_helper.h" +#include "ui/display/screen.h" #include "ui/events/test/cocoa_test_event_utils.h" #import "ui/gfx/mac/coordinate_conversion.h" #import "ui/views/cocoa/native_widget_mac_ns_window_host.h" @@ -385,6 +386,8 @@ private: TestViewsDelegate test_views_delegate_; + + display::ScopedNativeScreen screen_; }; class BridgedNativeWidgetTest : public BridgedNativeWidgetTestBase,
diff --git a/ui/views/controls/base_control_test_widget.cc b/ui/views/controls/base_control_test_widget.cc index 1bee91040..1131f0eb 100644 --- a/ui/views/controls/base_control_test_widget.cc +++ b/ui/views/controls/base_control_test_widget.cc
@@ -23,8 +23,6 @@ BaseControlTestWidget::~BaseControlTestWidget() = default; void BaseControlTestWidget::SetUp() { - ViewsTestBase::SetUp(); - #if BUILDFLAG(IS_MAC) test_screen_ = std::make_unique<display::test::TestScreenMac>(gfx::Size()); // Purposely not use ScopedScreenOverride, in which GetScreen() will @@ -32,6 +30,8 @@ display::Screen::SetScreenInstance(test_screen_.get()); #endif + ViewsTestBase::SetUp(); + widget_ = std::make_unique<Widget>(); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); @@ -47,10 +47,10 @@ void BaseControlTestWidget::TearDown() { widget_.reset(); + ViewsTestBase::TearDown(); #if BUILDFLAG(IS_MAC) display::Screen::SetScreenInstance(nullptr); #endif - ViewsTestBase::TearDown(); } void BaseControlTestWidget::CreateWidgetContent(View* container) {}
diff --git a/ui/views/test/test_desktop_screen_ozone.cc b/ui/views/test/test_desktop_screen_ozone.cc index 7f018a7..61684a2 100644 --- a/ui/views/test/test_desktop_screen_ozone.cc +++ b/ui/views/test/test_desktop_screen_ozone.cc
@@ -4,22 +4,20 @@ #include "ui/views/test/test_desktop_screen_ozone.h" -#include <memory> - -#include "base/memory/singleton.h" - -namespace views { -namespace test { - +namespace views::test { namespace { TestDesktopScreenOzone* g_instance = nullptr; } +// static +std::unique_ptr<display::Screen> TestDesktopScreenOzone::Create() { + auto screen = std::make_unique<TestDesktopScreenOzone>(); + screen->Initialize(); + return screen; +} + TestDesktopScreenOzone* TestDesktopScreenOzone::GetInstance() { - if (!g_instance) { - g_instance = base::Singleton<TestDesktopScreenOzone>::get(); - g_instance->Initialize(); - } + DCHECK_EQ(display::Screen::GetScreen(), g_instance); return g_instance; } @@ -27,8 +25,13 @@ return cursor_screen_point_; } -TestDesktopScreenOzone::TestDesktopScreenOzone() = default; -TestDesktopScreenOzone::~TestDesktopScreenOzone() = default; +TestDesktopScreenOzone::TestDesktopScreenOzone() { + DCHECK(!g_instance); + g_instance = this; +} -} // namespace test -} // namespace views +TestDesktopScreenOzone::~TestDesktopScreenOzone() { + g_instance = nullptr; +} + +} // namespace views::test
diff --git a/ui/views/test/test_desktop_screen_ozone.h b/ui/views/test/test_desktop_screen_ozone.h index abaea86..1054c1c 100644 --- a/ui/views/test/test_desktop_screen_ozone.h +++ b/ui/views/test/test_desktop_screen_ozone.h
@@ -5,12 +5,13 @@ #ifndef UI_VIEWS_TEST_TEST_DESKTOP_SCREEN_OZONE_H_ #define UI_VIEWS_TEST_TEST_DESKTOP_SCREEN_OZONE_H_ +#include <memory> + #include "ui/gfx/geometry/point.h" #include "ui/views/widget/desktop_aura/desktop_screen_ozone.h" -namespace base { -template <typename T> -struct DefaultSingletonTraits; +namespace display { +class Screen; } namespace views { @@ -26,6 +27,7 @@ TestDesktopScreenOzone(const TestDesktopScreenOzone&) = delete; TestDesktopScreenOzone& operator=(const TestDesktopScreenOzone&) = delete; + static std::unique_ptr<display::Screen> Create(); static TestDesktopScreenOzone* GetInstance(); // DesktopScreenOzone: @@ -35,12 +37,10 @@ cursor_screen_point_ = point; } - private: - friend struct base::DefaultSingletonTraits<TestDesktopScreenOzone>; - TestDesktopScreenOzone(); ~TestDesktopScreenOzone() override; + private: gfx::Point cursor_screen_point_; };
diff --git a/ui/views/test/views_test_helper_mac.h b/ui/views/test/views_test_helper_mac.h index a9abea1..3d5eb38 100644 --- a/ui/views/test/views_test_helper_mac.h +++ b/ui/views/test/views_test_helper_mac.h
@@ -7,9 +7,11 @@ #include <memory> +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/test/scoped_fake_full_keyboard_access.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/test/test_context_factories.h" +#include "ui/display/screen.h" #include "ui/views/test/views_test_helper.h" namespace ui { @@ -58,6 +60,8 @@ // more consistent with other platforms, where most views are focusable by // default. ui::test::ScopedFakeFullKeyboardAccess faked_full_keyboard_access_; + + display::ScopedNativeScreen screen_; }; } // namespace views
diff --git a/ui/views/test/widget_test.cc b/ui/views/test/widget_test.cc index ac1e3a965..459e046 100644 --- a/ui/views/test/widget_test.cc +++ b/ui/views/test/widget_test.cc
@@ -12,8 +12,12 @@ #include "ui/views/test/native_widget_factory.h" #include "ui/views/widget/root_view.h" -namespace views { -namespace test { +#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \ + !BUILDFLAG(IS_CHROMECAST) +#include "ui/views/test/test_desktop_screen_ozone.h" +#endif + +namespace views::test { namespace { @@ -130,9 +134,21 @@ void DesktopWidgetTestInteractive::SetUp() { SetUpForInteractiveTests(); +#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \ + !BUILDFLAG(IS_CHROMECAST) + screen_ = views::test::TestDesktopScreenOzone::Create(); +#endif DesktopWidgetTest::SetUp(); } +#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \ + !BUILDFLAG(IS_CHROMECAST) +void DesktopWidgetTestInteractive::TearDown() { + DesktopWidgetTest::TearDown(); + screen_.reset(); +} +#endif + TestDesktopWidgetDelegate::TestDesktopWidgetDelegate() : TestDesktopWidgetDelegate(nullptr) {} @@ -270,5 +286,4 @@ widget_observation_.Reset(); } -} // namespace test -} // namespace views +} // namespace views::test
diff --git a/ui/views/test/widget_test.h b/ui/views/test/widget_test.h index 24b792f..1ba22f67 100644 --- a/ui/views/test/widget_test.h +++ b/ui/views/test/widget_test.h
@@ -14,11 +14,17 @@ #include "base/scoped_observation.h" #include "base/test/bind.h" #include "build/build_config.h" +#include "build/chromecast_buildflags.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/test/views_test_base.h" #include "ui/views/widget/widget_delegate.h" #include "ui/views/widget/widget_observer.h" +#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \ + !BUILDFLAG(IS_CHROMECAST) +#include "ui/display/screen.h" +#endif + namespace ui { namespace internal { class InputMethodDelegate; @@ -156,6 +162,12 @@ // DesktopWidgetTest void SetUp() override; + +#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \ + !BUILDFLAG(IS_CHROMECAST) + void TearDown() override; + std::unique_ptr<display::Screen> screen_; +#endif }; // A helper WidgetDelegate for tests that require hooks into WidgetDelegate
diff --git a/ui/views/widget/desktop_aura/desktop_screen_win.cc b/ui/views/widget/desktop_aura/desktop_screen_win.cc index 7c352dd..b5ad964 100644 --- a/ui/views/widget/desktop_aura/desktop_screen_win.cc +++ b/ui/views/widget/desktop_aura/desktop_screen_win.cc
@@ -13,10 +13,13 @@ namespace views { -DesktopScreenWin::DesktopScreenWin() = default; +DesktopScreenWin::DesktopScreenWin() { + DCHECK(!display::Screen::HasScreen()); + display::Screen::SetScreenInstance(this); +} DesktopScreenWin::~DesktopScreenWin() { - display::Screen::SetScreenInstance(old_screen_); + display::Screen::SetScreenInstance(nullptr); } HWND DesktopScreenWin::GetHWNDFromNativeWindow(gfx::NativeWindow window) const {
diff --git a/ui/views/widget/desktop_aura/desktop_screen_win.h b/ui/views/widget/desktop_aura/desktop_screen_win.h index 6ab217c..c2cbf5a 100644 --- a/ui/views/widget/desktop_aura/desktop_screen_win.h +++ b/ui/views/widget/desktop_aura/desktop_screen_win.h
@@ -23,9 +23,6 @@ HWND GetHWNDFromNativeWindow(gfx::NativeWindow window) const override; gfx::NativeWindow GetNativeWindowFromHWND(HWND hwnd) const override; bool IsNativeWindowOccluded(gfx::NativeWindow window) const override; - - const raw_ptr<display::Screen> old_screen_ = - display::Screen::SetScreenInstance(this); }; } // namespace views
diff --git a/ui/wm/BUILD.gn b/ui/wm/BUILD.gn index 660b5a3..d006f7979 100644 --- a/ui/wm/BUILD.gn +++ b/ui/wm/BUILD.gn
@@ -100,10 +100,15 @@ sources = [ "test/testing_cursor_client_observer.cc", "test/testing_cursor_client_observer.h", - "test/wm_test_helper.cc", - "test/wm_test_helper.h", ] + if (is_chromeos_ash) { + sources += [ + "test/wm_test_helper.cc", + "test/wm_test_helper.h", + ] + } + public_deps = [ "//ui/base/cursor" ] deps = [
diff --git a/ui/wm/test/wm_test_helper.cc b/ui/wm/test/wm_test_helper.cc index 5088317..6e09afb6 100644 --- a/ui/wm/test/wm_test_helper.cc +++ b/ui/wm/test/wm_test_helper.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/memory/ptr_util.h" +#include "build/build_config.h" #include "ui/aura/client/default_capture_client.h" #include "ui/aura/test/test_focus_client.h" #include "ui/aura/test/test_screen.h" @@ -21,10 +22,10 @@ WMTestHelper::WMTestHelper(const gfx::Size& default_window_size) { wm_state_ = std::make_unique<WMState>(); - - // Install a screen, like TestWindowService's AuraTestHelper for InitMusHost. - test_screen_ = base::WrapUnique(aura::TestScreen::Create(gfx::Size())); - display::Screen::SetScreenInstance(test_screen_.get()); + if (!display::Screen::HasScreen()) { + test_screen_ = base::WrapUnique(aura::TestScreen::Create(gfx::Size())); + display::Screen::SetScreenInstance(test_screen_.get()); + } host_ = aura::WindowTreeHost::Create( ui::PlatformWindowInitProperties{gfx::Rect(default_window_size)}); @@ -46,8 +47,7 @@ WMTestHelper::~WMTestHelper() { host_->window()->RemovePreTargetHandler(root_window_event_filter_.get()); - - if (display::Screen::GetScreen() == test_screen_.get()) + if (test_screen_) display::Screen::SetScreenInstance(nullptr); }